Initial integration with MD-SAL 93/2193/1
authorTony Tkacik <ttkacik@cisco.com>
Sun, 27 Oct 2013 15:56:01 +0000 (16:56 +0100)
committerTony Tkacik <ttkacik@cisco.com>
Sun, 27 Oct 2013 15:56:01 +0000 (16:56 +0100)
  - Added SessionListener support to SessionManager implementation
  - Implemented OpenflowPluginProvider which get's Provider Context
    and delegates it to SalRegistrationManager
  - Added SALRegistrationManager - SAL Registration Manager is
    responsible to update node and service registrations in MD-SAL
    based on Session Events.
  - Implemented skeleton of ModelDrivenSwitch - unified class
    which serves as Session/Switch-specific instance of Openflow
    Services to MD-SAL. This removes need to lookup of session
    inside a plugin.

  - Added Integration test which test incoming nodeUpdated notification
    in simple scenario.

Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
openflowplugin-it/pom.xml
openflowplugin-it/src/test/java/org/opendaylight/openflowplugin/openflow/md/it/SalIntegrationTest.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/internal/Activator.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/ModelDrivenSwitch.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/AbstractModelDrivenSwitch.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/ModelDrivenSwitchImpl.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/OpenflowPluginProvider.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/SalRegistrationManager.java [new file with mode: 0644]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionListener.java [new file with mode: 0644]
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

index 16f852cc8376252485aa60c965af0acac1291766..63105f102fbdd7ba7dca005b533dccf3beaf0993 100644 (file)
     </build>
 
     <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-it</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-binding-broker-impl</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.openflowplugin</groupId>
             <artifactId>openflowplugin</artifactId>
diff --git a/openflowplugin-it/src/test/java/org/opendaylight/openflowplugin/openflow/md/it/SalIntegrationTest.java b/openflowplugin-it/src/test/java/org/opendaylight/openflowplugin/openflow/md/it/SalIntegrationTest.java
new file mode 100644 (file)
index 0000000..631bb8f
--- /dev/null
@@ -0,0 +1,168 @@
+package org.opendaylight.openflowplugin.openflow.md.it;
+
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
+import org.opendaylight.controller.sal.binding.api.NotificationService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.test.sal.binding.it.TestHelper;
+import org.opendaylight.openflowjava.protocol.impl.clients.ScenarioFactory;
+import org.opendaylight.openflowjava.protocol.impl.clients.ScenarioHandler;
+import org.opendaylight.openflowjava.protocol.impl.clients.SimpleClient;
+import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.*;
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.*;
+
+/**
+ * @author mirehak
+ */
+@RunWith(PaxExam.class)
+public class SalIntegrationTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SalIntegrationTest.class);
+
+    /** base controller package */
+    public static final String ODL = "org.opendaylight.controller";
+    /** controller.model package */
+    public static final String ODL_MODEL = "org.opendaylight.controller.model";
+    /** yangtools package */
+    public static final String YANG = "org.opendaylight.yangtools";
+    /** yangtools.model package */
+    public static final String YANG_MODEL = "org.opendaylight.yangtools.model";
+    /** OFPlugin package */
+    public static final String OFPLUGIN = "org.opendaylight.openflowplugin";
+    /** OFLibrary package */
+    public static final String OFLIBRARY = "org.opendaylight.openflowjava";
+    /** netty.io package */
+    public static final String NETTY = "io.netty";
+
+    @Inject
+    SwitchConnectionProvider switchConnectionProvider;
+
+    @Inject
+    BundleContext ctx;
+
+    @Inject
+    BindingAwareBroker broker;
+
+    /**
+     * test basic integration with OFLib running the handshake
+     *
+     * @throws Exception
+     */
+    @Test
+    public void handshakeAndNodeUpdate() throws Exception {
+
+        final TestInventoryListener listener = new TestInventoryListener();
+        BindingAwareConsumer openflowConsumer = new BindingAwareConsumer() {
+
+            @Override
+            public void onSessionInitialized(ConsumerContext session) {
+                session.getSALService(NotificationService.class).registerNotificationListener(listener);
+            }
+        };
+        ConsumerContext consumerReg = broker.registerConsumer(openflowConsumer, ctx);
+        assertNotNull(consumerReg);
+
+        LOG.debug("handshake integration test");
+        LOG.debug("switchConnectionProvider: " + switchConnectionProvider);
+
+        SimpleClient switchSim = new SimpleClient("localhost", 6653);
+        switchSim.setSecuredClient(false);
+        ScenarioHandler scenario = new ScenarioHandler(ScenarioFactory.createHandshakeScenario());
+        switchSim.setScenarioHandler(scenario);
+        switchSim.start();
+
+        switchSim.getScenarioDone().get();
+        Thread.sleep(2000);
+        assertEquals(1, listener.nodeUpdated.size());
+        assertNotNull(listener.nodeUpdated.get(0));
+
+    }
+
+    /**
+     * @return bundle options
+     */
+    @Configuration
+    public Option[] config() {
+        return options(systemProperty("osgi.console").value("2401"), mavenBundle("org.slf4j", "slf4j-api")
+                .versionAsInProject(), mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
+                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(),
+                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(),
+                mavenBundle("org.opendaylight.yangtools.thirdparty", "xtend-lib-osgi").versionAsInProject(),
+                mavenBundle("com.google.guava", "guava").versionAsInProject(),
+                mavenBundle("org.javassist", "javassist").versionAsInProject(),
+                mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
+                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
+
+                mavenBundle(ODL, "sal").versionAsInProject(), mavenBundle(ODL, "sal.connection").versionAsInProject(),
+
+                mdSalCoreBundles(), bindingAwareSalBundles(), baseModelBundles(), flowCapableModelBundles(),
+
+                mavenBundle("org.opendaylight.controller.thirdparty", "org.openflow.openflowj").versionAsInProject(),
+
+                mavenBundle(OFLIBRARY, "openflow-protocol-impl").versionAsInProject(),
+                mavenBundle(OFLIBRARY, "openflow-protocol-api").versionAsInProject(),
+                mavenBundle(OFLIBRARY, "openflow-protocol-spi").versionAsInProject(),
+
+                mavenBundle(NETTY, "netty-handler").versionAsInProject(), mavenBundle(NETTY, "netty-buffer")
+                        .versionAsInProject(), mavenBundle(NETTY, "netty-common").versionAsInProject(),
+                mavenBundle(NETTY, "netty-transport").versionAsInProject(), mavenBundle(NETTY, "netty-codec")
+                        .versionAsInProject(),
+
+                mavenBundle(OFLIBRARY, "simple-client").versionAsInProject().start(),
+                mavenBundle(OFPLUGIN, "openflowplugin").versionAsInProject(), junitBundles());
+    }
+
+    private static class TestInventoryListener implements OpendaylightInventoryListener {
+
+        List<NodeUpdated> nodeUpdated = new ArrayList<>();
+        List<NodeRemoved> nodeRemoved = new ArrayList<>();
+        List<NodeConnectorUpdated> nodeConnectorUpdated = new ArrayList<>();
+        List<NodeConnectorRemoved> nodeConnectorRemoved = new ArrayList<>();
+
+        @Override
+        public void onNodeUpdated(NodeUpdated notification) {
+            nodeUpdated.add(notification);
+        }
+
+        @Override
+        public void onNodeRemoved(NodeRemoved notification) {
+            nodeRemoved.add(notification);
+        }
+
+        @Override
+        public void onNodeConnectorUpdated(NodeConnectorUpdated notification) {
+            nodeConnectorUpdated.add(notification);
+        }
+
+        @Override
+        public void onNodeConnectorRemoved(NodeConnectorRemoved notification) {
+            nodeConnectorRemoved.add(notification);
+        }
+    };
+
+}
index 61eb4f469b910d78cc7a245c113b1513fb335452..147569d8dee8778d69abc01d574fef856c514f6e 100644 (file)
@@ -8,10 +8,17 @@
 
 package org.opendaylight.openflowplugin.openflow.internal;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.Hashtable;
 
 import org.apache.felix.dm.Component;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality;
 import org.opendaylight.controller.sal.connection.IPluginInConnectionService;
 import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
@@ -46,17 +53,20 @@ import org.opendaylight.openflowplugin.openflow.core.IController;
 import org.opendaylight.openflowplugin.openflow.core.IMessageListener;
 import org.opendaylight.openflowplugin.openflow.core.internal.Controller;
 import org.opendaylight.openflowplugin.openflow.md.core.MDController;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.SalRegistrationManager;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * Openflow protocol plugin Activator
- *
- *
  */
 public class Activator extends ComponentActivatorAbstractBase {
-    protected static final Logger logger = LoggerFactory
-            .getLogger(Activator.class);
+    protected static final Logger logger = LoggerFactory.getLogger(Activator.class);
+
+    private OpenflowPluginProvider pluginProvider = new OpenflowPluginProvider();
 
     /**
      * Function called when the activator starts just after some initializations
@@ -74,6 +84,12 @@ public class Activator extends ComponentActivatorAbstractBase {
     public void destroy() {
     }
 
+    @Override
+    public void start(BundleContext arg0) {
+        super.start(arg0);
+        pluginProvider.setContext(arg0);
+    }
+
     /**
      * Function that is used to communicate to dependency manager the list of
      * known implementations for services inside a container
@@ -84,8 +100,7 @@ public class Activator extends ComponentActivatorAbstractBase {
      *         Object
      */
     public Object[] getImplementations() {
-        Object[] res = { TopologyServices.class, DataPacketServices.class,
-                InventoryService.class, ReadService.class,
+        Object[] res = { TopologyServices.class, DataPacketServices.class, InventoryService.class, ReadService.class,
                 FlowProgrammerNotifier.class };
         return res;
     }
@@ -113,34 +128,23 @@ public class Activator extends ComponentActivatorAbstractBase {
                             ITopologyServiceShimListener.class.getName() }, null);
             // Hook the services coming in from SAL, as optional in
             // case SAL is not yet there, could happen
-            c.add(createContainerServiceDependency(containerName)
-                    .setService(IPluginOutTopologyService.class)
-                    .setCallbacks("setPluginOutTopologyService",
-                            "unsetPluginOutTopologyService").setRequired(false));
-            c.add(createServiceDependency()
-                    .setService(IRefreshInternalProvider.class)
-                    .setCallbacks("setRefreshInternalProvider",
-                            "unsetRefreshInternalProvider").setRequired(false));
+            c.add(createContainerServiceDependency(containerName).setService(IPluginOutTopologyService.class)
+                    .setCallbacks("setPluginOutTopologyService", "unsetPluginOutTopologyService").setRequired(false));
+            c.add(createServiceDependency().setService(IRefreshInternalProvider.class)
+                    .setCallbacks("setRefreshInternalProvider", "unsetRefreshInternalProvider").setRequired(false));
         }
 
         if (imp.equals(InventoryService.class)) {
             // export the service
-            c.setInterface(
-                    new String[] {
-                            IPluginInInventoryService.class.getName(),
-                            IInventoryShimInternalListener.class.getName(),
-                            IInventoryProvider.class.getName() }, null);
+            c.setInterface(new String[] { IPluginInInventoryService.class.getName(),
+                    IInventoryShimInternalListener.class.getName(), IInventoryProvider.class.getName() }, null);
 
             // Now lets add a service dependency to make sure the
             // provider of service exists
-            c.add(createServiceDependency()
-                    .setService(IController.class, "(name=Controller)")
-                    .setCallbacks("setController", "unsetController")
-                    .setRequired(true));
-            c.add(createContainerServiceDependency(containerName)
-                    .setService(IPluginOutInventoryService.class)
-                    .setCallbacks("setPluginOutInventoryServices",
-                            "unsetPluginOutInventoryServices")
+            c.add(createServiceDependency().setService(IController.class, "(name=Controller)")
+                    .setCallbacks("setController", "unsetController").setRequired(true));
+            c.add(createContainerServiceDependency(containerName).setService(IPluginOutInventoryService.class)
+                    .setCallbacks("setPluginOutInventoryServices", "unsetPluginOutInventoryServices")
                     .setRequired(false));
         }
 
@@ -153,23 +157,16 @@ public class Activator extends ComponentActivatorAbstractBase {
             c.setInterface(IPluginInDataPacketService.class.getName(), props);
             // Hook the services coming in from SAL, as optional in
             // case SAL is not yet there, could happen
-            c.add(createServiceDependency()
-                    .setService(IController.class, "(name=Controller)")
-                    .setCallbacks("setController", "unsetController")
-                    .setRequired(true));
+            c.add(createServiceDependency().setService(IController.class, "(name=Controller)")
+                    .setCallbacks("setController", "unsetController").setRequired(true));
             // This is required for the transmission to happen properly
             c.add(createServiceDependency().setService(IDataPacketMux.class)
-                    .setCallbacks("setIDataPacketMux", "unsetIDataPacketMux")
-                    .setRequired(true));
-            c.add(createContainerServiceDependency(containerName)
-                    .setService(IPluginOutDataPacketService.class)
-                    .setCallbacks("setPluginOutDataPacketService",
-                            "unsetPluginOutDataPacketService")
+                    .setCallbacks("setIDataPacketMux", "unsetIDataPacketMux").setRequired(true));
+            c.add(createContainerServiceDependency(containerName).setService(IPluginOutDataPacketService.class)
+                    .setCallbacks("setPluginOutDataPacketService", "unsetPluginOutDataPacketService")
                     .setRequired(false));
-            c.add(createServiceDependency()
-                    .setService(IPluginOutConnectionService.class)
-                    .setCallbacks("setIPluginOutConnectionService",
-                            "unsetIPluginOutConnectionService")
+            c.add(createServiceDependency().setService(IPluginOutConnectionService.class)
+                    .setCallbacks("setIPluginOutConnectionService", "unsetIPluginOutConnectionService")
                     .setRequired(false));
         }
 
@@ -179,25 +176,18 @@ public class Activator extends ComponentActivatorAbstractBase {
             // Set the protocolPluginType property which will be used
             // by SAL
             props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
-            c.setInterface(new String[] {
-                    IReadFilterInternalListener.class.getName(),
-                    IPluginInReadService.class.getName() }, props);
+            c.setInterface(
+                    new String[] { IReadFilterInternalListener.class.getName(), IPluginInReadService.class.getName() },
+                    props);
 
-            c.add(createServiceDependency()
-                    .setService(IReadServiceFilter.class)
-                    .setCallbacks("setService", "unsetService")
-                    .setRequired(true));
+            c.add(createServiceDependency().setService(IReadServiceFilter.class)
+                    .setCallbacks("setService", "unsetService").setRequired(true));
 
-            c.add(createContainerServiceDependency(containerName)
-                    .setService(IPluginOutReadService.class)
-                    .setCallbacks("setPluginOutReadServices",
-                            "unsetPluginOutReadServices")
-                    .setRequired(false));
+            c.add(createContainerServiceDependency(containerName).setService(IPluginOutReadService.class)
+                    .setCallbacks("setPluginOutReadServices", "unsetPluginOutReadServices").setRequired(false));
 
-            c.add(createServiceDependency()
-                    .setService(IPluginOutConnectionService.class)
-                    .setCallbacks("setIPluginOutConnectionService",
-                            "unsetIPluginOutConnectionService")
+            c.add(createServiceDependency().setService(IPluginOutConnectionService.class)
+                    .setCallbacks("setIPluginOutConnectionService", "unsetIPluginOutConnectionService")
                     .setRequired(false));
         }
 
@@ -209,15 +199,11 @@ public class Activator extends ComponentActivatorAbstractBase {
             props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
             c.setInterface(IFlowProgrammerNotifier.class.getName(), props);
 
-            c.add(createContainerServiceDependency(containerName)
-                    .setService(IPluginOutFlowProgrammerService.class)
-                    .setCallbacks("setPluginOutFlowProgrammerService",
-                            "unsetPluginOutFlowProgrammerService")
+            c.add(createContainerServiceDependency(containerName).setService(IPluginOutFlowProgrammerService.class)
+                    .setCallbacks("setPluginOutFlowProgrammerService", "unsetPluginOutFlowProgrammerService")
                     .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IPluginOutConnectionService.class)
-                    .setCallbacks("setIPluginOutConnectionService",
-                            "unsetIPluginOutConnectionService")
+            c.add(createServiceDependency().setService(IPluginOutConnectionService.class)
+                    .setCallbacks("setIPluginOutConnectionService", "unsetIPluginOutConnectionService")
                     .setRequired(false));
         }
     }
@@ -232,11 +218,9 @@ public class Activator extends ComponentActivatorAbstractBase {
      *         Object
      */
     public Object[] getGlobalImplementations() {
-        Object[] res = { Controller.class, OFStatisticsManager.class,
-                FlowProgrammerService.class, ReadServiceFilter.class,
-                DiscoveryService.class, DataPacketMuxDemux.class, InventoryService.class,
-                InventoryServiceShim.class, TopologyServiceShim.class,
-                MDController.class};
+        Object[] res = { Controller.class, OFStatisticsManager.class, FlowProgrammerService.class,
+                ReadServiceFilter.class, DiscoveryService.class, DataPacketMuxDemux.class, InventoryService.class,
+                InventoryServiceShim.class, TopologyServiceShim.class, MDController.class, pluginProvider };
         return res;
     }
 
@@ -258,10 +242,9 @@ public class Activator extends ComponentActivatorAbstractBase {
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             props.put("name", "Controller");
             props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
-            c.setInterface(new String[] { IController.class.getName(),
-                                          IPluginInConnectionService.class.getName()},
-                                          props);
-        }
+            c.setInterface(new String[] { IController.class.getName(), IPluginInConnectionService.class.getName() },
+                    props);
+        } else
 
         if (imp.equals(FlowProgrammerService.class)) {
             // export the service to be used by SAL
@@ -270,207 +253,149 @@ public class Activator extends ComponentActivatorAbstractBase {
             // by SAL
             props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
             c.setInterface(
-                    new String[] {
-                            IPluginInFlowProgrammerService.class.getName(),
-                            IMessageListener.class.getName(),
-                            IContainerListener.class.getName(),
-                            IInventoryShimExternalListener.class.getName() },
-                            props);
-
-            c.add(createServiceDependency()
-                    .setService(IController.class, "(name=Controller)")
-                    .setCallbacks("setController", "unsetController")
-                    .setRequired(true));
+                    new String[] { IPluginInFlowProgrammerService.class.getName(), IMessageListener.class.getName(),
+                            IContainerListener.class.getName(), IInventoryShimExternalListener.class.getName() }, props);
 
-            c.add(createServiceDependency()
-                    .setService(IFlowProgrammerNotifier.class)
-                    .setCallbacks("setFlowProgrammerNotifier",
-                            "unsetsetFlowProgrammerNotifier")
-                    .setRequired(false));
+            c.add(createServiceDependency().setService(IController.class, "(name=Controller)")
+                    .setCallbacks("setController", "unsetController").setRequired(true));
 
-            c.add(createServiceDependency()
-                    .setService(IPluginOutConnectionService.class)
-                    .setCallbacks("setIPluginOutConnectionService",
-                            "unsetIPluginOutConnectionService")
+            c.add(createServiceDependency().setService(IFlowProgrammerNotifier.class)
+                    .setCallbacks("setFlowProgrammerNotifier", "unsetsetFlowProgrammerNotifier").setRequired(false));
+
+            c.add(createServiceDependency().setService(IPluginOutConnectionService.class)
+                    .setCallbacks("setIPluginOutConnectionService", "unsetIPluginOutConnectionService")
                     .setRequired(false));
-        }
+        } else
 
         if (imp.equals(ReadServiceFilter.class)) {
 
-            c.setInterface(new String[] {
-                    IReadServiceFilter.class.getName(),
-                    IContainerListener.class.getName(),
+            c.setInterface(new String[] { IReadServiceFilter.class.getName(), IContainerListener.class.getName(),
                     IOFStatisticsListener.class.getName() }, null);
 
-            c.add(createServiceDependency()
-                    .setService(IController.class, "(name=Controller)")
-                    .setCallbacks("setController", "unsetController")
-                    .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IOFStatisticsManager.class)
-                    .setCallbacks("setService", "unsetService")
-                    .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IReadFilterInternalListener.class)
-                    .setCallbacks("setReadFilterInternalListener",
-                            "unsetReadFilterInternalListener")
+            c.add(createServiceDependency().setService(IController.class, "(name=Controller)")
+                    .setCallbacks("setController", "unsetController").setRequired(true));
+            c.add(createServiceDependency().setService(IOFStatisticsManager.class)
+                    .setCallbacks("setService", "unsetService").setRequired(true));
+            c.add(createServiceDependency().setService(IReadFilterInternalListener.class)
+                    .setCallbacks("setReadFilterInternalListener", "unsetReadFilterInternalListener")
                     .setRequired(false));
-        }
+        } else
 
         if (imp.equals(OFStatisticsManager.class)) {
 
-            c.setInterface(new String[] { IOFStatisticsManager.class.getName(),
-                    IInventoryShimExternalListener.class.getName() }, null);
+            c.setInterface(
+                    new String[] { IOFStatisticsManager.class.getName(), IInventoryShimExternalListener.class.getName() },
+                    null);
 
-            c.add(createServiceDependency()
-                    .setService(IController.class, "(name=Controller)")
-                    .setCallbacks("setController", "unsetController")
-                    .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IOFStatisticsListener.class)
-                    .setCallbacks("setStatisticsListener",
-                            "unsetStatisticsListener").setRequired(false));
-        }
+            c.add(createServiceDependency().setService(IController.class, "(name=Controller)")
+                    .setCallbacks("setController", "unsetController").setRequired(true));
+            c.add(createServiceDependency().setService(IOFStatisticsListener.class)
+                    .setCallbacks("setStatisticsListener", "unsetStatisticsListener").setRequired(false));
+        } else
 
         if (imp.equals(DiscoveryService.class)) {
             // export the service
             c.setInterface(
-                    new String[] {
-                            IInventoryShimExternalListener.class.getName(),
-                            IDataPacketListen.class.getName(),
+                    new String[] { IInventoryShimExternalListener.class.getName(), IDataPacketListen.class.getName(),
                             IContainerListener.class.getName() }, null);
 
-            c.add(createServiceDependency()
-                    .setService(IController.class, "(name=Controller)")
-                    .setCallbacks("setController", "unsetController")
-                    .setRequired(true));
-            c.add(createContainerServiceDependency(
-                    GlobalConstants.DEFAULT.toString())
+            c.add(createServiceDependency().setService(IController.class, "(name=Controller)")
+                    .setCallbacks("setController", "unsetController").setRequired(true));
+            c.add(createContainerServiceDependency(GlobalConstants.DEFAULT.toString())
                     .setService(IInventoryProvider.class)
-                    .setCallbacks("setInventoryProvider",
-                    "unsetInventoryProvider").setRequired(true));
+                    .setCallbacks("setInventoryProvider", "unsetInventoryProvider").setRequired(true));
             c.add(createServiceDependency().setService(IDataPacketMux.class)
-                    .setCallbacks("setIDataPacketMux", "unsetIDataPacketMux")
-                    .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IDiscoveryListener.class)
-                    .setCallbacks("setDiscoveryListener",
-                            "unsetDiscoveryListener").setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IPluginOutConnectionService.class)
-                    .setCallbacks("setIPluginOutConnectionService",
-                            "unsetIPluginOutConnectionService")
+                    .setCallbacks("setIDataPacketMux", "unsetIDataPacketMux").setRequired(true));
+            c.add(createServiceDependency().setService(IDiscoveryListener.class)
+                    .setCallbacks("setDiscoveryListener", "unsetDiscoveryListener").setRequired(true));
+            c.add(createServiceDependency().setService(IPluginOutConnectionService.class)
+                    .setCallbacks("setIPluginOutConnectionService", "unsetIPluginOutConnectionService")
                     .setRequired(false));
-        }
+        } else
 
         // DataPacket mux/demux services, which is teh actual engine
         // doing the packet switching
         if (imp.equals(DataPacketMuxDemux.class)) {
-            c.setInterface(new String[] { IDataPacketMux.class.getName(),
-                    IContainerListener.class.getName(),
+            c.setInterface(new String[] { IDataPacketMux.class.getName(), IContainerListener.class.getName(),
                     IInventoryShimExternalListener.class.getName() }, null);
 
-            c.add(createServiceDependency()
-                    .setService(IController.class, "(name=Controller)")
-                    .setCallbacks("setController", "unsetController")
-                    .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IPluginOutDataPacketService.class)
-                    .setCallbacks("setPluginOutDataPacketService",
-                            "unsetPluginOutDataPacketService")
+            c.add(createServiceDependency().setService(IController.class, "(name=Controller)")
+                    .setCallbacks("setController", "unsetController").setRequired(true));
+            c.add(createServiceDependency().setService(IPluginOutDataPacketService.class)
+                    .setCallbacks("setPluginOutDataPacketService", "unsetPluginOutDataPacketService")
                     .setRequired(false));
             // See if there is any local packet dispatcher
-            c.add(createServiceDependency()
-                    .setService(IDataPacketListen.class)
-                    .setCallbacks("setIDataPacketListen",
-                            "unsetIDataPacketListen").setRequired(false));
-            c.add(createServiceDependency()
-                    .setService(IPluginOutConnectionService.class)
-                    .setCallbacks("setIPluginOutConnectionService",
-                            "unsetIPluginOutConnectionService")
+            c.add(createServiceDependency().setService(IDataPacketListen.class)
+                    .setCallbacks("setIDataPacketListen", "unsetIDataPacketListen").setRequired(false));
+            c.add(createServiceDependency().setService(IPluginOutConnectionService.class)
+                    .setCallbacks("setIPluginOutConnectionService", "unsetIPluginOutConnectionService")
                     .setRequired(false));
-        }
+        } else
 
         if (imp.equals(InventoryService.class)) {
             // export the service
             Dictionary<String, Object> props = new Hashtable<String, Object>();
             props.put("scope", "Global");
 
-            c.setInterface(
-                    new String[] { IPluginInInventoryService.class.getName(),
-                            IInventoryShimInternalListener.class.getName(),
-                            IInventoryProvider.class.getName() }, props);
+            c.setInterface(new String[] { IPluginInInventoryService.class.getName(),
+                    IInventoryShimInternalListener.class.getName(), IInventoryProvider.class.getName() }, props);
 
             // Now lets add a service dependency to make sure the
             // provider of service exists
-            c.add(createServiceDependency()
-                    .setService(IController.class, "(name=Controller)")
-                    .setCallbacks("setController", "unsetController")
-                    .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IPluginOutInventoryService.class, "(scope=Global)")
-                    .setCallbacks("setPluginOutInventoryServices",
-                            "unsetPluginOutInventoryServices")
+            c.add(createServiceDependency().setService(IController.class, "(name=Controller)")
+                    .setCallbacks("setController", "unsetController").setRequired(true));
+            c.add(createServiceDependency().setService(IPluginOutInventoryService.class, "(scope=Global)")
+                    .setCallbacks("setPluginOutInventoryServices", "unsetPluginOutInventoryServices")
                     .setRequired(false));
-        }
+        } else
 
         if (imp.equals(InventoryServiceShim.class)) {
-            c.setInterface(new String[] { IContainerListener.class.getName(),
-                    IOFStatisticsListener.class.getName()}, null);
+            c.setInterface(new String[] { IContainerListener.class.getName(), IOFStatisticsListener.class.getName() },
+                    null);
 
-            c.add(createServiceDependency()
-                    .setService(IController.class, "(name=Controller)")
-                    .setCallbacks("setController", "unsetController")
+            c.add(createServiceDependency().setService(IController.class, "(name=Controller)")
+                    .setCallbacks("setController", "unsetController").setRequired(true));
+            c.add(createServiceDependency().setService(IInventoryShimInternalListener.class, "(!(scope=Global))")
+                    .setCallbacks("setInventoryShimInternalListener", "unsetInventoryShimInternalListener")
                     .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IInventoryShimInternalListener.class, "(!(scope=Global))")
-                    .setCallbacks("setInventoryShimInternalListener",
-                            "unsetInventoryShimInternalListener")
+            c.add(createServiceDependency().setService(IInventoryShimInternalListener.class, "(scope=Global)")
+                    .setCallbacks("setInventoryShimGlobalInternalListener", "unsetInventoryShimGlobalInternalListener")
                     .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IInventoryShimInternalListener.class, "(scope=Global)")
-                    .setCallbacks("setInventoryShimGlobalInternalListener",
-                            "unsetInventoryShimGlobalInternalListener")
-                    .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IInventoryShimExternalListener.class)
-                    .setCallbacks("setInventoryShimExternalListener",
-                            "unsetInventoryShimExternalListener")
+            c.add(createServiceDependency().setService(IInventoryShimExternalListener.class)
+                    .setCallbacks("setInventoryShimExternalListener", "unsetInventoryShimExternalListener")
                     .setRequired(false));
-            c.add(createServiceDependency()
-                    .setService(IPluginOutConnectionService.class)
-                    .setCallbacks("setIPluginOutConnectionService",
-                            "unsetIPluginOutConnectionService")
+            c.add(createServiceDependency().setService(IPluginOutConnectionService.class)
+                    .setCallbacks("setIPluginOutConnectionService", "unsetIPluginOutConnectionService")
                     .setRequired(false));
-        }
+        } else
 
         if (imp.equals(TopologyServiceShim.class)) {
-            c.setInterface(new String[] { IDiscoveryListener.class.getName(),
-                    IContainerListener.class.getName(),
-                    IRefreshInternalProvider.class.getName(),
-                    IInventoryShimExternalListener.class.getName() }, null);
-          c.add(createServiceDependency()
-                    .setService(ITopologyServiceShimListener.class)
-                    .setCallbacks("setTopologyServiceShimListener",
-                            "unsetTopologyServiceShimListener")
+            c.setInterface(new String[] { IDiscoveryListener.class.getName(), IContainerListener.class.getName(),
+                    IRefreshInternalProvider.class.getName(), IInventoryShimExternalListener.class.getName() }, null);
+            c.add(createServiceDependency().setService(ITopologyServiceShimListener.class)
+                    .setCallbacks("setTopologyServiceShimListener", "unsetTopologyServiceShimListener")
                     .setRequired(true));
-            c.add(createServiceDependency()
-                    .setService(IOFStatisticsManager.class)
-                    .setCallbacks("setStatisticsManager",
-                            "unsetStatisticsManager").setRequired(false));
-        }
+            c.add(createServiceDependency().setService(IOFStatisticsManager.class)
+                    .setCallbacks("setStatisticsManager", "unsetStatisticsManager").setRequired(false));
+        } else
 
         if (imp.equals(MDController.class)) {
-//            c.setInterface(new String[] { IDiscoveryListener.class.getName(),
-//                    IContainerListener.class.getName(),
-//                    IRefreshInternalProvider.class.getName(),
-//                    IInventoryShimExternalListener.class.getName() }, null);
-            c.add(createServiceDependency()
-                    .setService(SwitchConnectionProvider.class)
-                    .setCallbacks("setSwitchConnectionProvider",
-                            "unsetSwitchConnectionProvider")
-                    .setRequired(true));
+            // c.setInterface(new String[] { IDiscoveryListener.class.getName(),
+            // IContainerListener.class.getName(),
+            // IRefreshInternalProvider.class.getName(),
+            // IInventoryShimExternalListener.class.getName() }, null);
+            c.add(createServiceDependency().setService(SwitchConnectionProvider.class)
+                    .setCallbacks("setSwitchConnectionProvider", "unsetSwitchConnectionProvider").setRequired(true));
             logger.debug("configuring MDController ..");
+        } else if (imp == pluginProvider) {
+            // c.setInterface(new String[] { IDiscoveryListener.class.getName(),
+            // IContainerListener.class.getName(),
+            // IRefreshInternalProvider.class.getName(),
+            // IInventoryShimExternalListener.class.getName() }, null);
+            c.add(createServiceDependency().setService(BindingAwareBroker.class)
+                    .setCallbacks("setBroker", "unsetBroker").setRequired(true));
+            logger.debug("configuring Binding Aware Provider");
         }
     }
+
 }
index 9a23e115df577d9f40e427cc830a2bb23d93a5af..70de544a5da75157a658fc3d35f7b088e068369c 100644 (file)
@@ -1,9 +1,71 @@
 package org.opendaylight.openflowplugin.openflow.md;
 
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.FlowStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public interface ModelDrivenSwitch extends //
+        SalGroupService, //
+        SalFlowService, //
+        SalMeterService, //
+        PacketProcessingService, //
+        Identifiable<InstanceIdentifier<Node>> {
+
+    CompositeObjectRegistration<ModelDrivenSwitch> register(ProviderContext ctx);
+
+    @Override
+    public InstanceIdentifier<Node> getIdentifier();
+
+    public NodeId getNodeId();
+
+    @Override
+    public Future<RpcResult<Void>> addFlow(AddFlowInput input);
+
+    @Override
+    public Future<RpcResult<Void>> removeFlow(RemoveFlowInput input);
+
+    @Override
+    public Future<RpcResult<Void>> transmitPacket(TransmitPacketInput input);
+
+    @Override
+    public Future<RpcResult<Void>> updateFlow(UpdateFlowInput input);
+
+    @Override
+    public Future<RpcResult<Void>> addGroup(AddGroupInput input);
+
+    @Override
+    public Future<RpcResult<Void>> addMeter(AddMeterInput input);
+
+    @Override
+    public Future<RpcResult<Void>> removeGroup(RemoveGroupInput input);
+
+    @Override
+    public Future<RpcResult<Void>> removeMeter(RemoveMeterInput input);
 
-public interface ModelDrivenSwitch extends SalFlowService, PacketProcessingService {
+    @Override
+    public Future<RpcResult<Void>> updateGroup(UpdateGroupInput input);
 
+    @Override
+    public Future<RpcResult<Void>> updateMeter(UpdateMeterInput input);
 }
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/AbstractModelDrivenSwitch.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/AbstractModelDrivenSwitch.java
new file mode 100644 (file)
index 0000000..3425bc8
--- /dev/null
@@ -0,0 +1,71 @@
+package org.opendaylight.openflowplugin.openflow.md.core.sal;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.openflowplugin.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
+import org.opendaylight.yangtools.concepts.CompositeObjectRegistration.CompositeObjectRegistrationBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+public abstract class AbstractModelDrivenSwitch implements ModelDrivenSwitch {
+
+    private final InstanceIdentifier<Node> identifier;
+
+    private RoutedRpcRegistration<SalFlowService> flowRegistration;
+
+    private RoutedRpcRegistration<SalGroupService> groupRegistration;
+
+    private RoutedRpcRegistration<SalMeterService> meterRegistration;
+
+    private RoutedRpcRegistration<PacketProcessingService> packetRegistration;
+
+    private final SessionContext sessionContext;
+
+    protected AbstractModelDrivenSwitch(InstanceIdentifier<Node> identifier,SessionContext conductor) {
+        this.identifier = identifier;
+        this.sessionContext = conductor;
+    }
+
+    @Override
+    public final InstanceIdentifier<Node> getIdentifier() {
+        return this.identifier;
+    }
+
+    @Override
+    public CompositeObjectRegistration<ModelDrivenSwitch> register(ProviderContext ctx) {
+        CompositeObjectRegistrationBuilder<ModelDrivenSwitch> builder = CompositeObjectRegistration
+                .<ModelDrivenSwitch> builderFor(this);
+
+        flowRegistration = ctx.addRoutedRpcImplementation(SalFlowService.class, this);
+        flowRegistration.registerPath(NodeContext.class, getIdentifier());
+        builder.add(flowRegistration);
+
+        //meterRegistration = ctx.addRoutedRpcImplementation(SalMeterService.class, this);
+        //meterRegistration.registerPath(NodeContext.class, getIdentifier());
+        //builder.add(meterRegistration);
+
+        //groupRegistration = ctx.addRoutedRpcImplementation(SalGroupService.class, this);
+        //groupRegistration.registerPath(NodeContext.class, getIdentifier());
+        //builder.add(groupRegistration);
+
+        //packetRegistration = ctx.addRoutedRpcImplementation(PacketProcessingService.class, this);
+        //packetRegistration.registerPath(NodeContext.class, getIdentifier());
+        //builder.add(packetRegistration);
+
+        return builder.toInstance();
+    }
+
+    public SessionContext getConductor() {
+        return sessionContext;
+    }
+
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/ModelDrivenSwitchImpl.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/ModelDrivenSwitchImpl.java
new file mode 100644 (file)
index 0000000..563964a
--- /dev/null
@@ -0,0 +1,134 @@
+package org.opendaylight.openflowplugin.openflow.md.core.sal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+import org.apache.log4j.spi.LoggerFactory;
+import org.opendaylight.openflowplugin.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.FlowModFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowMod;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.flow.mod.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.flow.mod.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+
+public class ModelDrivenSwitchImpl extends AbstractModelDrivenSwitch {
+
+    public static final Logger LOG = org.slf4j.LoggerFactory.getLogger(ModelDrivenSwitchImpl.class);
+    private final NodeId nodeId;
+
+    protected ModelDrivenSwitchImpl(NodeId nodeId, InstanceIdentifier<Node> identifier, SessionContext context) {
+        super(identifier, context);
+        this.nodeId = nodeId;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> addFlow(AddFlowInput input) {
+        // TODO Auto-generated method stub
+
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> addGroup(AddGroupInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> addMeter(AddMeterInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> removeFlow(RemoveFlowInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> removeGroup(RemoveGroupInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> removeMeter(RemoveMeterInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> transmitPacket(TransmitPacketInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    private FlowModInputBuilder toFlowModInputBuilder(Flow source) {
+        FlowModInputBuilder target = new FlowModInputBuilder();
+        target.setCookie(source.getCookie());
+        target.setIdleTimeout(source.getIdleTimeout());
+        target.setHardTimeout(source.getHardTimeout());
+        target.setMatch(toMatch(source.getMatch()));
+
+        return target;
+    }
+
+    private Match toMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow.Match match) {
+        MatchBuilder target = new MatchBuilder();
+
+        target.setMatchEntries(toMatchEntries(match));
+
+        return null;
+    }
+
+    private List<MatchEntries> toMatchEntries(
+            org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow.Match match) {
+        List<MatchEntries> entries = new ArrayList<>();
+
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> updateFlow(UpdateFlowInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> updateGroup(UpdateGroupInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> updateMeter(UpdateMeterInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public NodeId getNodeId() {
+        return nodeId;
+    }
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/OpenflowPluginProvider.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/OpenflowPluginProvider.java
new file mode 100644 (file)
index 0000000..e3e67b9
--- /dev/null
@@ -0,0 +1,60 @@
+package org.opendaylight.openflowplugin.openflow.md.core.sal;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.osgi.framework.BundleContext;
+
+public class OpenflowPluginProvider implements BindingAwareProvider {
+
+    private BindingAwareBroker broker;
+
+    private BundleContext context;
+
+    public BundleContext getContext() {
+        return context;
+    }
+
+    public void setContext(BundleContext context) {
+        this.context = context;
+    }
+
+    SalRegistrationManager registrationManager = new SalRegistrationManager();
+
+    @Override
+    public void onSessionInitiated(ProviderContext session) {
+        registrationManager.onSessionInitiated(session);
+    }
+
+    @Override
+    public void onSessionInitialized(ConsumerContext session) {
+        // NOOP
+    }
+
+    @Override
+    public Collection<? extends ProviderFunctionality> getFunctionality() {
+        return Collections.emptySet();
+    }
+
+    public java.util.Collection<? extends RpcService> getImplementations() {
+        return Collections.emptySet();
+    }
+
+    public BindingAwareBroker getBroker() {
+        return broker;
+    }
+
+    public void setBroker(BindingAwareBroker broker) {
+        this.broker = broker;
+        broker.registerProvider(this, context);
+    };
+
+    public void unsetBroker(BindingAwareBroker broker) {
+        this.broker = null;
+    };
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/SalRegistrationManager.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/SalRegistrationManager.java
new file mode 100644 (file)
index 0000000..2368fab
--- /dev/null
@@ -0,0 +1,109 @@
+package org.opendaylight.openflowplugin.openflow.md.core.sal;
+
+import java.io.Console;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.openflow.md.ModelDrivenSwitch;
+import org.opendaylight.openflowplugin.openflow.md.SwitchInventory;
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionListener;
+import org.opendaylight.openflowplugin.openflow.md.core.session.SessionManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SalRegistrationManager implements SessionListener, SwitchInventory {
+
+    private final static Logger LOG = LoggerFactory.getLogger(SalRegistrationManager.class);
+
+    Map<InstanceIdentifier<Node>, ModelDrivenSwitch> salSwitches = new ConcurrentHashMap<>();
+
+    private ProviderContext providerContext;
+
+    private NotificationProviderService publishService;
+
+    public NotificationProviderService getPublishService() {
+        return publishService;
+    }
+
+    public void setPublishService(NotificationProviderService publishService) {
+        this.publishService = publishService;
+    }
+
+    public ProviderContext getProviderContext() {
+        return providerContext;
+    }
+
+    public void onSessionInitiated(ProviderContext session) {
+        this.providerContext = session;
+        this.publishService = session.getSALService(NotificationProviderService.class);
+
+        // We register as listener for Session Manager
+        getSessionManager().registerSessionListener(this);
+        LOG.info("SalRegistrationManager initialized");
+
+    }
+
+    @Override
+    public void onSessionAdded(SwitchConnectionDistinguisher sessionKey, SessionContext context) {
+        GetFeaturesOutput features = context.getFeatures();
+        BigInteger datapathId = features.getDatapathId();
+        InstanceIdentifier<Node> identifier = identifierFromDatapathId(datapathId);
+
+        NodeId nodeId = nodeIdFromDatapathId(datapathId);
+        ModelDrivenSwitchImpl ofSwitch = new ModelDrivenSwitchImpl(nodeId, identifier, context);
+        salSwitches.put(identifier, ofSwitch);
+        ofSwitch.register(providerContext);
+
+        LOG.info("ModelDrivenSwitch for {} registered to MD-SAL.", datapathId.toString());
+
+        publishService.publish(nodeAdded(ofSwitch, features));
+    }
+
+    private NodeUpdated nodeAdded(ModelDrivenSwitch sw, GetFeaturesOutput features) {
+        NodeUpdatedBuilder builder = new NodeUpdatedBuilder();
+        builder.setId(sw.getNodeId());
+        return builder.build();
+    }
+
+    @Override
+    public ModelDrivenSwitch getSwitch(NodeRef node) {
+        return salSwitches.get(node.getValue());
+    }
+
+    public static InstanceIdentifier<Node> identifierFromDatapathId(BigInteger datapathId) {
+        InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+
+        NodeKey nodeKey = nodeKeyFromDatapathId(datapathId);
+        return builder.node(Node.class, nodeKey).toInstance();
+    }
+
+    public static NodeKey nodeKeyFromDatapathId(BigInteger datapathId) {
+        return new NodeKey(nodeIdFromDatapathId(datapathId));
+    }
+
+    public static NodeId nodeIdFromDatapathId(BigInteger datapathId) {
+        // FIXME: Convert to textual representation of datapathID
+        String current = datapathId.toString();
+        return new NodeId("openflow://" + current);
+    }
+
+    public SessionManager getSessionManager() {
+        return OFSessionUtil.getSessionManager();
+    }
+}
diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionListener.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/session/SessionListener.java
new file mode 100644 (file)
index 0000000..6b2debc
--- /dev/null
@@ -0,0 +1,11 @@
+package org.opendaylight.openflowplugin.openflow.md.core.session;
+
+import java.util.EventListener;
+
+import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
+
+public interface SessionListener extends EventListener {
+
+    void onSessionAdded(SwitchConnectionDistinguisher sessionKey, SessionContext context);
+
+}
index 398836dbe38393fec00d8e1a84c774b3fb965ca3..43901c85f2c11aaf0099ec39a28baca993204bd8 100644 (file)
@@ -15,10 +15,9 @@ 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.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 
-
-
 /**
  * @author mirehak
  */
@@ -62,4 +61,6 @@ public interface SessionManager {
     public void invalidateOnDisconnect(ConnectionConductor connectionConductor);
 
     public void setListenerMapping(Map<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping);
+
+    public ListenerRegistration<SessionListener> registerSessionListener(SessionListener listener);
 }
index 112b2c7598d915925939dbfe34c85d26272106b8..351b1b00316e970d147de19581fe608475edaace 100644 (file)
@@ -13,9 +13,12 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 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.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -30,6 +33,8 @@ public class SessionManagerOFImpl implements SessionManager {
     private ConcurrentHashMap<SwitchConnectionDistinguisher, SessionContext> sessionLot;
     private Map<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping;
 
+    private final ListenerRegistry<SessionListener> sessionListeners = new ListenerRegistry<>();
+
     /**
      * @return singleton instance
      */
@@ -82,7 +87,9 @@ public class SessionManagerOFImpl implements SessionManager {
     @Override
     public void addSessionContext(SwitchConnectionDistinguisher sessionKey, SessionContext context) {
         sessionLot.put(sessionKey, context);
-        // TODO:: notify listeners
+
+        sessionNotifier.onSessionAdded(sessionKey, context);
+
     }
 
     @Override
@@ -131,4 +138,24 @@ public class SessionManagerOFImpl implements SessionManager {
     public void setListenerMapping(Map<Class<? extends DataObject>, Collection<IMDMessageListener>> listenerMapping) {
         this.listenerMapping = listenerMapping;
     }
+
+    @Override
+    public ListenerRegistration<SessionListener> registerSessionListener(SessionListener listener) {
+        return sessionListeners.register(listener);
+    }
+
+    private final SessionListener sessionNotifier = new SessionListener() {
+
+        @Override
+        public void onSessionAdded(SwitchConnectionDistinguisher sessionKey, SessionContext context) {
+            for (ListenerRegistration<SessionListener> listener : sessionListeners) {
+                try {
+                    listener.getInstance().onSessionAdded(sessionKey, context);
+                } catch (Exception e) {
+                    LOG.error("Unhandled exeption occured while invoking onSessionAdded on listener", e);
+                }
+            }
+        }
+    };
+
 }