private SessionContext sessionContext;
- private ImmutableMap<Class<? extends DataObject>, Collection<IMessageListener>> listenerMapping;
+ private ImmutableMap<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping;
/**
* @param connectionAdapter
* @param listenerMapping the listenerMapping to set
*/
public void setListenerMapping(
- ImmutableMap<Class<? extends DataObject>, Collection<IMessageListener>> listenerMapping) {
+ ImmutableMap<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping) {
//TODO: adjust the listener interface
this.listenerMapping = listenerMapping;
}
* @param message
*/
private void notifyListeners(Class<? extends DataObject> messageType, DataObject message) {
- Collection<IMessageListener> listeners = listenerMapping.get(messageType);
+ Collection<IMDMessageListener> listeners = listenerMapping.get(messageType);
if (listeners != null) {
- for (IMessageListener listener : listeners) {
- //TODO: use some iface (message, conductor (connection+session id)
- //listener.receive(someId, message);
+ for (IMDMessageListener listener : listeners) {
+ //TODO : need to add unit-tests
+ //listener.receive(this.getAuxiliaryKey().getId(), this.getSessionContext(), message);
}
}
}
--- /dev/null
+package org.opendaylight.openflowplugin.openflow.md.core;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public interface IMDController {
+
+ /**
+ * Allows application to start receiving OF messages received from switches.
+ *
+ * @param type
+ * the type of OF message that applications want to receive
+ * @param listener
+ * : Object that implements the IMDMessageListener
+ */
+ public void addMessageListener(Class<? extends DataObject> messageType, IMDMessageListener listener);
+
+ /**
+ * Allows application to stop receiving OF message received from switches.
+ *
+ * @param type
+ * The type of OF message that applications want to stop
+ * receiving
+ * @param listener
+ * The object that implements the IMDMessageListener
+ */
+ public void removeMessageListener(Class<? extends DataObject> messageType, IMDMessageListener listener);
+
+}
--- /dev/null
+package org.opendaylight.openflowplugin.openflow.md.core;
+
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public interface IMDMessageListener {
+
+ /**
+ * This method is called by the MDController/ConnectionConductor when a
+ * message is received from a switch. Application who is interested in
+ * receiving OF Messages needs to implement this method.
+ *
+ * @param sw
+ * The SessionContext which sent the OF message
+ * @param msg
+ * The OF message
+ */
+ public void receive(byte[] cookie, SessionContext sw, DataObject msg);
+
+}
package org.opendaylight.openflowplugin.openflow.md.core;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Future;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;
import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @author mirehak
*
*/
-public class MDController {
+public class MDController implements IMDController {
- private static final Logger LOG = LoggerFactory
- .getLogger(MDController.class);
+ private static final Logger LOG = LoggerFactory.getLogger(MDController.class);
private SwitchConnectionProvider switchConnectionProvider;
+ private ConcurrentMap<Class<? extends DataObject>, Collection<IMDMessageListener>> messageListeners;
+
+ public Map<Class<? extends DataObject>, Collection<IMDMessageListener>> getMessageListeners() {
+ return messageListeners;
+ }
+
+
+ public void init() {
+ LOG.debug("Initializing!");
+ this.messageListeners = new ConcurrentHashMap<Class<? extends DataObject>, Collection<IMDMessageListener>>();
+ }
+
/**
- * @param switchConnectionProvider the switchConnectionProvider to set
+ * @param switchConnectionProvider
+ * the switchConnectionProvider to set
*/
- public void setSwitchConnectionProvider(
- SwitchConnectionProvider switchConnectionProvider) {
+ public void setSwitchConnectionProvider(SwitchConnectionProvider switchConnectionProvider) {
this.switchConnectionProvider = switchConnectionProvider;
}
/**
- * @param switchConnectionProviderToUnset the switchConnectionProvider to unset
+ * @param switchConnectionProviderToUnset
+ * the switchConnectionProvider to unset
*/
- public void unsetSwitchConnectionProvider(
- SwitchConnectionProvider switchConnectionProviderToUnset) {
+ public void unsetSwitchConnectionProvider(SwitchConnectionProvider switchConnectionProviderToUnset) {
if (this.switchConnectionProvider == switchConnectionProviderToUnset) {
this.switchConnectionProvider = null;
}
*/
public void start() {
LOG.debug("starting ..");
- LOG.debug("switchConnectionProvider: "+switchConnectionProvider);
+ LOG.debug("switchConnectionProvider: " + switchConnectionProvider);
// setup handler
SwitchConnectionHandler switchConnectionHandler = new SwitchConnectionHandlerImpl();
switchConnectionProvider.setSwitchConnectionHandler(switchConnectionHandler);
* @return wished connections configurations
*/
private static Collection<ConnectionConfiguration> getConnectionConfiguration() {
- //TODO:: get config from state manager
+ // TODO:: get config from state manager
ConnectionConfiguration configuration = ConnectionConfigurationFactory.getDefault();
return Lists.newArrayList(configuration);
}
// do nothing
}
+ @Override
+ public void addMessageListener(Class<? extends DataObject> messageType, IMDMessageListener listener) {
+
+ Collection<IMDMessageListener> existingValues = messageListeners.get(messageType);
+ if (existingValues == null) {
+ existingValues = new ArrayList<IMDMessageListener>();
+ }
+ existingValues.add(listener);
+ messageListeners.put(messageType, existingValues);
+ // Push the updated Listeners to Session Manager which will be then picked up by ConnectionConductor eventually
+ OFSessionUtil.getSessionManager().setListenerMapping(messageListeners);
+ LOG.debug("{} is now listened by {}", messageType, listener);
+ }
+
+ @Override
+ public void removeMessageListener(Class<? extends DataObject> messageType, IMDMessageListener listener) {
+
+ Collection<IMDMessageListener> values = messageListeners.get(messageType);
+ if (values != null) {
+ values.remove(listener);
+ if (values.size() == 0) {
+ messageListeners.remove(messageType);
+ }
+ //Push the updated Listeners to Session Manager which will be then picked up by ConnectionConductor eventually
+ OFSessionUtil.getSessionManager().setListenerMapping(messageListeners);
+ LOG.debug("{} is now removed", listener);
+ }
+ }
+
+
+
}
package org.opendaylight.openflowplugin.openflow.md.core.session;
+import java.util.Collection;
+import java.util.Map;
+
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.openflow.md.core.IMDMessageListener;
import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+
/**
* @author mirehak
* @return corresponding conductor, holding {@link ConnectionAdapter} to
* primary connection
*/
- public SessionContext getSessionContext(
- SwitchConnectionDistinguisher sessionKey);
+ public SessionContext getSessionContext(SwitchConnectionDistinguisher sessionKey);
/**
* disconnect all underlying {@link ConnectionAdapter}s and notify listeners
* @param sessionKey
* @param context
*/
- public void addSessionContext(SwitchConnectionDistinguisher sessionKey,
- SessionContext context);
+ public void addSessionContext(SwitchConnectionDistinguisher sessionKey, SessionContext context);
/**
* disconnect particular auxiliary {@link ConnectionAdapter}, identified by
* @param connectionConductor
*/
public void invalidateOnDisconnect(ConnectionConductor connectionConductor);
+
+ public void setListenerMapping(Map<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping);
}
package org.opendaylight.openflowplugin.openflow.md.core.session;
+import java.util.Collection;
+import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.openflow.md.core.IMDMessageListener;
import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
public class SessionManagerOFImpl implements SessionManager {
- private static final Logger LOG = LoggerFactory
- .getLogger(SessionManagerOFImpl.class);
+ private static final Logger LOG = LoggerFactory.getLogger(SessionManagerOFImpl.class);
private static SessionManagerOFImpl instance;
private ConcurrentHashMap<SwitchConnectionDistinguisher, SessionContext> sessionLot;
+ private Map<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping;
/**
* @return singleton instance
}
@Override
- public SessionContext getSessionContext(
- SwitchConnectionDistinguisher sessionKey) {
+ public SessionContext getSessionContext(SwitchConnectionDistinguisher sessionKey) {
return sessionLot.get(sessionKey);
}
@Override
- public void invalidateSessionContext(
- SwitchConnectionDistinguisher sessionKey) {
+ public void invalidateSessionContext(SwitchConnectionDistinguisher sessionKey) {
SessionContext context = getSessionContext(sessionKey);
if (context == null) {
LOG.warn("context for invalidation not found");
} else {
- for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context
- .getAuxiliaryConductors()) {
+ for (Entry<SwitchConnectionDistinguisher, ConnectionConductor> auxEntry : context.getAuxiliaryConductors()) {
invalidateAuxiliary(sessionKey, auxEntry.getKey());
}
context.getPrimaryConductor().disconnect();
}
@Override
- public void addSessionContext(SwitchConnectionDistinguisher sessionKey,
- SessionContext context) {
+ public void addSessionContext(SwitchConnectionDistinguisher sessionKey, SessionContext context) {
sessionLot.put(sessionKey, context);
// TODO:: notify listeners
}
* @param disconnect
* true if auxiliary connection is to be disconnected
*/
- private static void invalidateAuxiliary(SessionContext context,
- SwitchConnectionDistinguisher connectionCookie, boolean disconnect) {
+ private static void invalidateAuxiliary(SessionContext context, SwitchConnectionDistinguisher connectionCookie,
+ boolean disconnect) {
if (context == null) {
LOG.warn("context for invalidation not found");
} else {
- ConnectionConductor auxiliaryConductor = context
- .removeAuxiliaryConductor(connectionCookie);
+ ConnectionConductor auxiliaryConductor = context.removeAuxiliaryConductor(connectionCookie);
if (auxiliaryConductor == null) {
LOG.warn("auxiliary conductor not found");
} else {
invalidateDeadSessionContext(conductor.getSessionContext());
// TODO:: notify listeners
} else {
- invalidateAuxiliary(conductor.getSessionContext(),
- conductor.getAuxiliaryKey(), false);
+ invalidateAuxiliary(conductor.getSessionContext(), conductor.getAuxiliaryKey(), false);
}
}
+
+ /**
+ * @param listenerMapping
+ * the listenerMapping to set
+ */
+ public void setListenerMapping(Map<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping) {
+ this.listenerMapping = listenerMapping;
+ }
}
--- /dev/null
+package org.opendaylight.openflowplugin.openflow.md.core;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemoved;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MDControllerTest {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(ConnectionConductorImplTest.class);
+
+ protected MDController controller;
+
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ controller = new MDController();
+ controller.init();
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ controller = null;
+ }
+
+
+ /**
+ * Test method for
+ * {@link org.opendaylight.openflowplugin.openflow.md.core.MDController#addMessageListeners}
+ * .
+ */
+ @Test
+ public void testAddMessageListeners() {
+ // Empty map
+ int size = controller.getMessageListeners().size();
+ Assert.assertEquals(size, 0);
+ // Add one
+ IMDMessageListener objDps = new DataPacketService() ;
+ controller.addMessageListener(PacketIn.class, objDps);
+ size = controller.getMessageListeners().size();
+ Assert.assertEquals(size, 1);
+ // Remove one
+ controller.removeMessageListener(PacketIn.class, objDps);
+ size = controller.getMessageListeners().size();
+ Assert.assertEquals(size, 0);
+ // Add two and remove One
+ IMDMessageListener objFps = new FlowProgrammerService();
+ controller.addMessageListener(PacketIn.class, objDps);
+ controller.addMessageListener(FlowRemoved.class, objFps);
+ controller.removeMessageListener(FlowRemoved.class, objFps);
+ size = controller.getMessageListeners().size();
+ Assert.assertEquals(size, 1);
+ // Add one more and remove both
+ controller.addMessageListener(FlowRemoved.class, objFps);
+ controller.removeMessageListener(PacketIn.class, objDps);
+ controller.removeMessageListener(FlowRemoved.class, objFps);
+ size = controller.getMessageListeners().size();
+ Assert.assertEquals(size, 0);
+ // Add multiple listeners to messageTypes
+ controller.addMessageListener(PacketIn.class, objDps);
+ controller.addMessageListener(PacketIn.class, objFps); // Duplicate value entry
+ controller.addMessageListener(FlowRemoved.class, objFps);
+ size = controller.getMessageListeners().size();
+ Assert.assertEquals(size, 2);
+ // Remove one of the multiple listener, still size remains same
+ controller.removeMessageListener(PacketIn.class, objFps);
+ size = controller.getMessageListeners().size();
+ Assert.assertEquals(size, 2);
+
+ }
+
+ private class DataPacketService implements IMDMessageListener {
+ @Override
+ public void receive(byte[] cookie, SessionContext sw, DataObject msg) {
+ LOG.debug("Received a packet in DataPacket Service");
+ }
+ }
+
+ private class FlowProgrammerService implements IMDMessageListener {
+ @Override
+ public void receive(byte[] cookie, SessionContext sw, DataObject msg) {
+ LOG.debug("Received a packet in Flow Programmer Service");
+ }
+ }
+
+
+
+}