Adding Listener Registration for OF Messages in plugin 24/2124/1
authorYugandhar <ysarraju@in.ibm.com>
Tue, 22 Oct 2013 11:19:06 +0000 (16:49 +0530)
committerYugandhar <ysarraju@in.ibm.com>
Thu, 24 Oct 2013 08:25:51 +0000 (13:55 +0530)
Incorporated comment to return Map

Included cookie in Message notifications

Signed-off-by: Yugandhar <ysarraju@in.ibm.com>
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/ConnectionConductorImpl.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/IMDController.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/IMDMessageListener.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/MDController.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionManager.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionManagerOFImpl.java
openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/MDControllerTest.java [new file with mode: 0644]

index 902eb0e8a69a2e0c7afb9af7715d6e01c0a33b79..c40e49321975d3fe6b0ffef5fa475d5fd625845c 100644 (file)
@@ -67,7 +67,7 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
 
     private SessionContext sessionContext;
 
-    private ImmutableMap<Class<? extends DataObject>, Collection<IMessageListener>> listenerMapping;
+    private ImmutableMap<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping;
 
     /**
      * @param connectionAdapter
@@ -327,7 +327,7 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
      * @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;
     }
@@ -337,11 +337,11 @@ public class ConnectionConductorImpl implements OpenflowProtocolListener,
      * @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);
             }
         }
     }
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/IMDController.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/IMDController.java
new file mode 100644 (file)
index 0000000..d2269c8
--- /dev/null
@@ -0,0 +1,28 @@
+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);
+
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/IMDMessageListener.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/IMDMessageListener.java
new file mode 100644 (file)
index 0000000..5ff3185
--- /dev/null
@@ -0,0 +1,20 @@
+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);
+
+}
index b13eada421257205eb91fc58d0dcb6b0a858dc12..26b3d87356a59de2bb119f3863f6a97efc29a657 100644 (file)
@@ -8,13 +8,19 @@
 
 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;
 
@@ -24,26 +30,37 @@ import com.google.common.collect.Lists;
  * @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;
         }
@@ -56,7 +73,7 @@ public class MDController {
      */
     public void start() {
         LOG.debug("starting ..");
-        LOG.debug("switchConnectionProvider: "+switchConnectionProvider);
+        LOG.debug("switchConnectionProvider: " + switchConnectionProvider);
         // setup handler
         SwitchConnectionHandler switchConnectionHandler = new SwitchConnectionHandlerImpl();
         switchConnectionProvider.setSwitchConnectionHandler(switchConnectionHandler);
@@ -69,7 +86,7 @@ public class MDController {
      * @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);
     }
@@ -94,4 +111,35 @@ public class MDController {
         // 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);
+         }
+    }
+
+
+
 }
index 0dacd5dc16a9ec903a40418b611ff5cc9e10607e..398836dbe38393fec00d8e1a84c774b3fb965ca3 100644 (file)
@@ -8,9 +8,16 @@
 
 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
@@ -22,8 +29,7 @@ public interface SessionManager {
      * @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
@@ -38,8 +44,7 @@ public interface SessionManager {
      * @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
@@ -55,4 +60,6 @@ public interface SessionManager {
      * @param connectionConductor
      */
     public void invalidateOnDisconnect(ConnectionConductor connectionConductor);
+
+    public void setListenerMapping(Map<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping);
 }
index 01b87ff4203bbd8e192476a3f673127e03f7889d..112b2c7598d915925939dbfe34c85d26272106b8 100644 (file)
@@ -8,11 +8,15 @@
 
 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;
 
@@ -21,10 +25,10 @@ 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
@@ -41,20 +45,17 @@ public class SessionManagerOFImpl implements SessionManager {
     }
 
     @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();
@@ -79,8 +80,7 @@ public class SessionManagerOFImpl implements SessionManager {
     }
 
     @Override
-    public void addSessionContext(SwitchConnectionDistinguisher sessionKey,
-            SessionContext context) {
+    public void addSessionContext(SwitchConnectionDistinguisher sessionKey, SessionContext context) {
         sessionLot.put(sessionKey, context);
         // TODO:: notify listeners
     }
@@ -98,13 +98,12 @@ public class SessionManagerOFImpl implements SessionManager {
      * @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 {
@@ -121,8 +120,15 @@ public class SessionManagerOFImpl implements SessionManager {
             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;
+    }
 }
diff --git a/openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/MDControllerTest.java b/openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/MDControllerTest.java
new file mode 100644 (file)
index 0000000..af536d9
--- /dev/null
@@ -0,0 +1,102 @@
+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");
+        }
+    }
+
+
+
+}