Project Floodlight - Listening for openflow messages - sdn

I am using project Floodlight to understand the software defined networking for my personal project. My custom module uses floodlightProvider controller module and IOFMessageListener to listen for openflow messages. I can successfully listen to PACKET_IN openflow messages, however I am not able to listen to any synchronous openflow messages(HELLO, EQHO_REQUEST, etc). I followed the documentation and if I am not mistaken, openflow messages can be listened by using the floodlightProvider controller module. Can anyone assist me as I am very curious. The program for listening for messages is given on floodlight tutorial under "how to write a module" . However, I am editing the startup method and the receive method. Those are as follows:
#Override
public void startUp(FloodlightModuleContext context) {
floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
floodlightProvider.addOFMessageListener(OFType.HELLO, this);
}
#Override
public net.floodlightcontroller.core.IListener.Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
switch(msg.getType()){
case PACKET_IN:
// print the openflow message in console
break;
case HELLO:
// print the openflow message in console
break;
default:
break;
}
return Command.CONTINUE;
}

Related

How to handle errors when RabbitMQ exchange doesn't exist (and messages are sent through a messaging gateway interface)

I'd like to know what is the canonical way to handle errors in the following situation (code is a minimal working example):
Messages are sent through a messaging gateway which defines its defaultRequestChannel and a #Gateway method:
#MessagingGateway(name = MY_GATEWAY, defaultRequestChannel = INPUT_CHANNEL)
public interface MyGateway
{
#Gateway
public void sendMessage(String message);
Messages are read from the channel and sent through an AMQP outbound adapter:
#Bean
public IntegrationFlow apiMutuaInputFlow()
{
return IntegrationFlows
.from(INPUT_CHANNEL)
.handle(Amqp.outboundAdapter(rabbitConfig.myTemplate()))
.get();
}
The RabbitMQ configuration is skeletal:
#Configuration
public class RabbitMqConfiguration
{
#Autowired
private ConnectionFactory rabbitConnectionFactory;
#Bean
public RabbitTemplate myTemplate()
{
RabbitTemplate r = new RabbitTemplate(rabbitConnectionFactory);
r.setExchange(INPUT_QUEUE_NAME);
r.setConnectionFactory(rabbitConnectionFactory);
return r;
}
}
I generally include a bean to define the RabbitMQ configuration I'm relying upon (exchange, queues and bindings), and it actually works fine. But while testing for failure scenarios, I found a situation I don't know how to properly handle using Spring Integration. The steps are:
Remove the beans that configure RabbitMQ
Run the flow against an unconfigured, vanilla RabbitMQ instance.
What I would expect is:
The message cannot be delivered because the exchange cannot be found.
Either I find some way to get an exception from the messaging gateway on the caller thread.
Either I find some way to otherwise intercept this error.
What I find:
The message cannot be delivered because the exchange cannot be found, and indeed this error message is logged every time the #Gateway method is called.
2020-02-11 08:18:40.746 ERROR 42778 --- [ 127.0.0.1:5672] o.s.a.r.c.CachingConnectionFactory : Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'my.exchange' in vhost '/', class-id=60, method-id=40)
The gateway is not failing, nor have I find a way to configure it to do so (e.g.: adding throws clauses to the interface methods, configuring a transactional channel, setting wait-for-confirm and a confirm-timeout).
I haven't found a way to otherwise catch that CachingConectionFactory error (e.g.: configuring a transactional channel).
I haven't found a way to catch an error message on another channel (specified on the gateway's errorChannel), or in Spring Integration's default errorChannel.
I understand such a failure may not be propagated upstream by the messaging gateway, whose job is isolating callers from the messaging API, but I definitely expect such an error to be interceptable.
Could you point me in the right direction?
Thank you.
RabbitMQ is inherently async, which is one reason that it performs so well.
You can, however, block the caller by enabling confirms and returns and setting this option:
/**
* Set to true if you want to block the calling thread until a publisher confirm has
* been received. Requires a template configured for returns. If a confirm is not
* received within the confirm timeout or a negative acknowledgment or returned
* message is received, an exception will be thrown. Does not apply to the gateway
* since it blocks awaiting the reply.
* #param waitForConfirm true to block until the confirmation or timeout is received.
* #since 5.2
* #see #setConfirmTimeout(long)
* #see #setMultiSend(boolean)
*/
public void setWaitForConfirm(boolean waitForConfirm) {
this.waitForConfirm = waitForConfirm;
}
(With the DSL .waitForConfirm(true)).
This also requires a confirm correlation expression. Here's an example from one of the test cases
#Bean
public IntegrationFlow flow(RabbitTemplate template) {
return f -> f.handle(Amqp.outboundAdapter(template)
.exchangeName("")
.routingKeyFunction(msg -> msg.getHeaders().get("rk", String.class))
.confirmCorrelationFunction(msg -> msg)
.waitForConfirm(true));
}
#Bean
public CachingConnectionFactory cf() {
CachingConnectionFactory ccf = new CachingConnectionFactory(
RabbitAvailableCondition.getBrokerRunning().getConnectionFactory());
ccf.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
ccf.setPublisherReturns(true);
return ccf;
}
#Bean
public RabbitTemplate template(ConnectionFactory cf) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(cf);
rabbitTemplate.setMandatory(true); // for returns
rabbitTemplate.setReceiveTimeout(10_000);
return rabbitTemplate;
}
Bear in mind this will slow down things considerably (similar to using transactions) so you may want to reconsider whether you want to do this on every send (unless performance is not an issue).

How to log from Debug Adapter Protocol implementation (vscode debugger extension)?

Intro: Hi folks, I'd like to ask some questions about extension developing. I'd like to create a remote lua debuger extension (for linux user, haven't found any working lua debugger). When I touch the launch button, the debug server should be started to listen (on e.g. 0.0.0.0:8723) for waiting debugger connection. And on the other side sould communicate through the DAP (debug adapter protocol) with vscode.
Problem: I'm starting to implement the my own debuger extension... But I am new in this topic and with Node.js also. My question is: How can I log (or debug) my LoggingDebugSession (where the DAP is implemented)?
I looked at the MockDebug extension example project.And tried to rewrite...
Try to log into console, my file luaDebugSession.ts:
export class LuaDebugSession extends LoggingDebugSession {
public constructor() {
super("remote-lua-debug-log.txt");
this.sendEvent(new OutputEvent("Try to log"));
console.log("Try log into console")
}
protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
this.sendEvent(new OutputEvent("Try to log 2"));
console.log("Try log into console 2")
// do something
this.sendEvent(new InitializedEvent());
}
// next code...
}
In console should be the logged output.

Spring Integration two way communication with gps devices

We are using spring integration application for data receiption from gps devices. For current configuration we are able to receive data from device also respose sent back to device through same connection
current configuration is as
#SpringBootApplication
#IntegrationComponentScan
public class SpringIntegrationApplication extends SpringBootServletInitializer{
private Integer TIMEOUT=1000*60*10;
#Value("${TCP_PORT}")
private Integer TCP_PORT;
public static void main(String[] args) throws IOException {
ConfigurableApplicationContext ctx = SpringApplication.run(SpringIntegrationApplication.class, args);
System.in.read();
ctx.close();
}
#Bean
TcpNetServerConnectionFactory cf(){
TcpNetServerConnectionFactory connectionFactory=new TcpNetServerConnectionFactory(TCP_PORT);
connectionFactory.setSerializer(new CustomSerializerDeserializer());
connectionFactory.setDeserializer(new CustomSerializerDeserializer());
connectionFactory.setSoTimeout(TIMEOUT);
return connectionFactory;
}
#Bean
TcpInboundGateway tcpGate(){
TcpInboundGateway gateway=new TcpInboundGateway();
gateway.setConnectionFactory(cf());
gateway.setRequestChannel(requestChannel());
gateway.setRequestTimeout(TIMEOUT);
return gateway;
}
#Bean
public MessageChannel requestChannel(){
return new DirectChannel();
}
}
and message end point
#MessageEndpoint
public class Echo {
#ServiceActivator(inputChannel="requestChannel")
public byte[] echo(byte[] in,#SuppressWarnings("deprecation") #Header("ip_address") String ip){
//here we receive packet data in bytes from gps device
return "".getBytes();//string will contains expected result for device.
}
Above configuartion works fine for one way communication. but we want to implement two way communication. What we want after connection established between server and device we want to send message explicitely.To send command through server we dont know ip and port of device, so how can we send command through server to connected device.
I am trying following solution
created oubound channel adapter
#Bean
public TcpSendingMessageHandler tcpSendingMessageHandler() {
System.out.println("Creating outbound adapter");
TcpSendingMessageHandler outbound = new TcpSendingMessageHandler();
return outbound;
}
then created gateway for explicite message send, this will be called from service where we want to send data explicitely
#MessagingGateway(defaultRequestChannel="toTcp")
public static interface tcpSendService {
public byte [] send(String string);
}
After calling gate way following service activator invoked where we are setting connection ip and port, these ip and ports will be from connection established while receiving data from device
#ServiceActivator(inputChannel="toTcp", outputChannel="fromTcp")
public String send(String in){
System.out.println(new String(in));
TcpNetClientConnectionFactory factory = new TcpNetClientConnectionFactory(ip_extracted_from_inbound_connection, port_extarcted_from_inbound_connection);
factory.start();
tcpSendingMessageHandler.setConnectionFactory(factory);
return in;
}
// for ip and port extraction i am using following service which is inbound sevice
#ServiceActivator(inputChannel="requestChannel")
public byte[] echo(byte[] in,#Header("ip_address") String ip){
System.out.println(new String(in)+ " ; IP : "+ip);
for (String connectionId : factory.getOpenConnectionIds()) {
if(!lastConection.contains(ip))
lastConection = connectionId;
}
return "hello".getBytes();
}
For service activator i am setting new TcpNetClientConnectionFactory every time service called. Ip and port are extracted from TcpNetServerConnectionFactory. whenever device connects with server i am saving its connection ip and port, using these ip and port for data transmission through server but i am getting connection timeout issue.
Kindly help me out and suggest me a solution over it.
Thank you.
Replace the gateway with a pair of Collaborating Outbound and Inbound Channel Adapters.
In order to send arbitrary messages to a connection, you must set the ip_connectionId header.
The challenge, though, is how to direct the reply to the gateway. You would need to capture the replyChannel header from the request and, when a reply is received for that ip_connectionId, set the replyChannel headers.
This will only work, though, if you have only one request/reply outstanding to each device at a time, unless there is some data in the reply that can be used to correlate it to a request.
Another challenge is race conditions, where the device and the server initiate a request at the same time. You would need to look at data in the inbound message to see if it's a request or reply.

NServiceBus 5.2.14 - Scheduler fails to trigger delegate

While using the NServiceBus Scheduler I have been unsuccessful in triggering the delegate defined. I used the documentation at the link below to setup the EndpointScheduler class.
The endpoints corresponding timeout queue is created and a message successfully enters the queue. No errors are encountered during execution, but the scheduler does not trigger the delegate. I am currently using NServiceBus 5.2.14, a similar test works using NServiceBus 3.2.7. Any ideas why the Scheduler isn't triggering the delegate?
http://docs.particular.net/nservicebus/scheduling/
public class EndpointScheduler : IWantToRunWhenBusStartsAndStops, ILoggable
{
public EndpointScheduler(Schedule schedule)
{
this.schedule = schedule;
}
public void Start()
{
schedule.Every(
TimeSpan.FromMinutes(1),
"Test",
() =>
{
Debug.WriteLine("I'm testing the scheduler");
}
);
}
public void Stop()
{
}
}
Thanks to #DavidBoike for pointing out a few potential setup issues.
The endpoint configuration contained:
configuration.DisableFeature<TimeoutManager>()
Removing it corrected the issue I encountered.
The reason for this is that the scheduler is dependent upon the TimeoutManager. It works by deferring a message to be processed later (using the TimeoutManager) and when that message is received, the delegate is invoked. Without the TimeoutManager activated, this can't work.

How to configure RMI over SSL in ehcache for replication

I Have ehcache replication working properly without SSL support.
I am looking to support my ehcache replication via SSL i.e. i want to have RMI over SSL
How can i do that?
Here is sample manual peer discovery i am using.
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//10.100.10.12:40002/ssoSessionStore"/>
Can i have some SSL support to RMI call it is doing?
Thanks
I had to change ehcache source code and change few classes to support SSL. As when ehcache over rmi bootsup , it registers itself on rmiregistry. I need to start this registery via SSL context
Look at class RMICacheManagerPeerListener.java for method startRegistry()
This is main class where RMI registry starts. One who is modifying the code needs to understand then ehcache rmi code flow first. Below code is snippet of what has to be done and respectively change other methods.
final String SSL= System.getProperty("isSSL");
protected void startRegistry() throws RemoteException {
try {
LOG.info("Trying to Get Exsisting Registry =========>> ");
if (SSL != null && SSL.equals("ssl"))
registry = LocateRegistry.getRegistry(hostName, port.intValue(),
new SslRMIClientSocketFactory());
else
registry = LocateRegistry.getRegistry(port.intValue());
try {
registry.list();
} catch (RemoteException e) {
// may not be created. Let's create it.
if (SSL != null && SSL.equals("ssl")) {
LOG.info("Registry not found, Creating New SSL =========>> ");
registry = LocateRegistry.createRegistry(port.intValue(),
new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory(null, null, true));
} else {
LOG.info("Registry not found, Creating New Naming registry =========>> ");
registry = LocateRegistry.createRegistry(port.intValue());
}
registryCreated = true;
}
} catch (ExportException exception) {
LOG.error("Exception starting RMI registry. Error was " + exception.getMessage(), exception);
}
}
Similarly i made change for method
bind()
notifyCacheAdded()
unbind()
disposeRMICachePeer()
populateListOfRemoteCachePeers()
bind()
init()
To patch support for using a custom socket factory you should remove usage of the global defaults. Static method calls on
java.rmi.Naming
should be replaced with the registry returned by the three-argument versions of
LocateRegistry.createRegistry
and
LocateRegistry.getRegistry
and in ConfigurableRMIClientSocketFactory.java change
getConfiguredRMISocketFactory
to return an SSL-based implementation.
See https://gist.github.com/okhobb/4a504e212aef86d4257c69de892e4d7d for an example patch.