Merge "Fix NPE caused by ElanServiceProvider"
authorSam Hague <shague@redhat.com>
Mon, 8 Aug 2016 18:19:00 +0000 (18:19 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 8 Aug 2016 18:19:00 +0000 (18:19 +0000)
46 files changed:
openstack/sfc-translator/features/pom.xml
openstack/sfc-translator/features/src/main/features/features.xml
openstack/sfc-translator/impl/pom.xml
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/DelegatingDataTreeListener.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/NeutronMdsalHelper.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/OpenStackSFCTranslatorProvider.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/OvsdbMdsalHelper.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/SfcMdsalHelper.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/FlowClassifierTranslator.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/flowclassifier/NeutronFlowClassifierListener.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/portchain/NeutronPortChainListener.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/portchain/NeutronPortPairGroupListener.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/portchain/NeutronPortPairListener.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/portchain/PortChainTranslator.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/portchain/PortPairGroupTranslator.java
openstack/sfc-translator/impl/src/main/java/org/opendaylight/netvirt/openstack/sfc/translator/portchain/PortPairTranslator.java
openstack/sfc-translator/impl/src/main/resources/org/opendaylight/blueprint/openstack-sfc-translator.xml
vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclConstants.java
vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceOFFlowBuilder.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/config/default-config.xml [deleted file]
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpConfigListener.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpDesignatedDpnListener.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpExternalTunnelManager.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpInterfaceConfigListener.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpInterfaceEventListener.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpLogicalSwitchListener.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpManager.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpNeutronPortListener.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpPktHandler.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpProvider.java [deleted file]
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpUCastMacListener.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/NodeListener.java
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModule.java [deleted file]
vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModuleFactory.java [deleted file]
vpnservice/dhcpservice/dhcpservice-impl/src/main/resources/org/opendaylight/blueprint/dhcpservice-impl.xml [new file with mode: 0644]
vpnservice/dhcpservice/dhcpservice-impl/src/main/yang/dhcpservice-config.yang [new file with mode: 0644]
vpnservice/dhcpservice/dhcpservice-impl/src/main/yang/dhcpservice-impl.yang [deleted file]
vpnservice/features/pom.xml
vpnservice/features/src/main/features/features.xml
vpnservice/it/src/test/java/org/opendaylight/netvirt/it/NetvirtIT.java
vpnservice/it/src/test/java/org/opendaylight/netvirt/it/NetvirtITConstants.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/FloatingIPListener.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/VpnFloatingIpHandler.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronSecurityRuleConstants.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronSecurityRuleListener.java
vpnservice/utils/netvirt-it-utils/src/main/java/org/opendaylight/netvirt/utils/netvirt/it/utils/FlowITUtil.java [new file with mode: 0644]

index d5e954129c787a192cc7223d82143527f1875ecf..766dee6a3206b2c3dd9aaa1188d607166c14d049 100644 (file)
       <classifier>features</classifier>
       <type>xml</type>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>openstack.net-virt-sfc-features</artifactId>
+      <version>${project.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.sfc</groupId>
       <artifactId>features-sfc</artifactId>
index 8b76ad1ee30f1dd3d3bfd1ee1d96088a351c5310..5b3e519d0901ea98e8efdfa608c4e12ab86bedc6 100644 (file)
   <repository>mvn:org.opendaylight.neutron/features-neutron/{{VERSION}}/xml/features</repository>
   <repository>mvn:org.opendaylight.sfc/features-sfc/{{VERSION}}/xml/features</repository>
   <repository>mvn:org.opendaylight.netvirt/features-netvirt/{{VERSION}}/xml/features</repository>
+  <repository>mvn:org.opendaylight.netvirt/openstack.net-virt-sfc-features/{{VERSION}}/xml/features</repository>
   <feature name='odl-netvirt-openstack-sfc-translator' version='${project.version}'
            description='OpenStack SFC to OpenDaylight SFC API data translator'>
     <feature version='${controller.mdsal.version}'>odl-mdsal-broker</feature>
     <feature version="${neutron.version}">odl-neutron-service</feature>
     <feature version='${sfc.version}'>odl-sfc-model</feature>
+    <feature version='${project.version}'>odl-ovsdb-sfc-api</feature>
   <bundle>mvn:org.opendaylight.netvirt/utils.mdsal-utils/{{VERSION}}</bundle>
   <bundle>mvn:org.opendaylight.netvirt/openstack.sfc-translator-impl/{{VERSION}}</bundle>
   </feature>
     <feature version="${project.version}">odl-netvirt-openstack-sfc-translator</feature>
     <feature version="${restconf.version}">odl-restconf</feature>
   </feature>
-  <feature name='odl-netvirt-openstack-sfc-translator-ui' version='${project.version}'
-           description='OpenStack SFC to OpenDaylight SFC API data translator with dlux UI'>
-    <feature version="${project.version}">odl-netvirt-openstack-sfc-translator-rest</feature>
-    <feature version="${restconf.version}">odl-mdsal-apidocs</feature>
-    <feature version="${controller.mdsal.version}">odl-mdsal-xsql</feature>
-    <feature version="${dlux.version}">odl-dlux-yangui</feature>
-  </feature>
 </features>
index b7b821a9f7c8b28f0e1e5b37ab68ce1689ca10cc..a1645b288b3d4b903f5d31c4010c9ed25652eca1 100644 (file)
       <artifactId>slf4j-simple</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>openstack.net-virt-sfc-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>utils.mdsal-utils</artifactId>
index f960c984154f591ce869f34c63170417cabe70ac..9c2292f917fcc2eb1bf248c05d71fb0cb2f2dd1c 100644 (file)
@@ -30,7 +30,9 @@ import java.util.concurrent.ThreadFactory;
 /**
  * Data-tree listener which delegates data processing to a {@link INeutronSfcDataProcessor}.
  */
-public class DelegatingDataTreeListener<T extends DataObject> implements AutoCloseable, DataTreeChangeListener<T> {
+public abstract class DelegatingDataTreeListener<T extends DataObject> implements AutoCloseable,
+        DataTreeChangeListener<T>,
+        INeutronSfcDataProcessor<T> {
     private static final Logger LOG = LoggerFactory.getLogger(DelegatingDataTreeListener.class);
     private static final ThreadFactory threadFactory = new ThreadFactoryBuilder()
         .setNameFormat("NeutronSfcListener-%d").build();
@@ -38,9 +40,8 @@ public class DelegatingDataTreeListener<T extends DataObject> implements AutoClo
     private final INeutronSfcDataProcessor<T> dataProcessor;
     private ListenerRegistration<DelegatingDataTreeListener<T>> listenerRegistration;
 
-    public DelegatingDataTreeListener(INeutronSfcDataProcessor<T> dataProcessor,
-                                      DataBroker db, DataTreeIdentifier<T> treeId) {
-        this.dataProcessor = Preconditions.checkNotNull(dataProcessor, "Data processor can not be null!");
+    public DelegatingDataTreeListener(DataBroker db, DataTreeIdentifier<T> treeId) {
+        this.dataProcessor = Preconditions.checkNotNull(this, "Data processor can not be null!");
         registerListener(Preconditions.checkNotNull(db, "Data broker can not be null!"),
                 Preconditions.checkNotNull(treeId, "Tree identifier can not be null!"));
     }
index 6773c116e5b908e295b0985dc96827d6c5bb8706..916dbf03749d45fe52edc2b2ba9ddc189c33d4c5 100644 (file)
@@ -15,6 +15,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.por
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.SfcFlowClassifiers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifierKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.PortPairGroups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.PortPairs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPairKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -25,9 +34,14 @@ import org.slf4j.LoggerFactory;
  */
 public class NeutronMdsalHelper {
     private static final Logger LOG = LoggerFactory.getLogger(NeutronMdsalHelper.class);
-    private static final InstanceIdentifier<Ports> portsPairIid =
+    private static final InstanceIdentifier<SfcFlowClassifiers> fcIid =
+            InstanceIdentifier.create(Neutron.class).child(SfcFlowClassifiers.class);
+    private static final InstanceIdentifier<Ports> portsIid =
             InstanceIdentifier.create(Neutron.class).child(Ports.class);
-
+    private static final InstanceIdentifier<PortPairs> portPairsIid =
+            InstanceIdentifier.create(Neutron.class).child(PortPairs.class);
+    private static final InstanceIdentifier<PortPairGroups> portPairGroupsIid =
+            InstanceIdentifier.create(Neutron.class).child(PortPairGroups.class);
 
     private final DataBroker dataBroker;
     private final MdsalUtils mdsalUtils;
@@ -42,7 +56,37 @@ public class NeutronMdsalHelper {
         return neutronPort;
     }
 
+    public PortPair getNeutronPortPair(Uuid portPairId) {
+        PortPair neutronPortPair
+                = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION , getNeutronPortPairPath(portPairId));
+        return neutronPortPair;
+    }
+
+    public PortPairGroup getNeutronPortPairGroup(Uuid portPairGroupId) {
+        PortPairGroup neutronPortPairGroup
+                = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION , getNeutronPortPairGroupPath(portPairGroupId));
+        return neutronPortPairGroup;
+    }
+
+    public SfcFlowClassifier getNeutronFlowClassifier(Uuid flowClassifierId) {
+        SfcFlowClassifier sfcFlowClassifier
+                = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION , getNeutronSfcFlowClassifierPath(flowClassifierId));
+        return sfcFlowClassifier;
+    }
+
     private InstanceIdentifier<Port> getNeutronPortPath(Uuid portId) {
-        return portsPairIid.builder().child(Port.class, new PortKey(portId)).build();
+        return portsIid.builder().child(Port.class, new PortKey(portId)).build();
+    }
+
+    private InstanceIdentifier<PortPair> getNeutronPortPairPath(Uuid portPairId) {
+        return portPairsIid.builder().child(PortPair.class, new PortPairKey(portPairId)).build();
+    }
+
+    private InstanceIdentifier<PortPairGroup> getNeutronPortPairGroupPath(Uuid portPairGroupId) {
+        return portPairGroupsIid.builder().child(PortPairGroup.class, new PortPairGroupKey(portPairGroupId)).build();
+    }
+
+    private InstanceIdentifier<SfcFlowClassifier> getNeutronSfcFlowClassifierPath(Uuid portId) {
+        return fcIid.builder().child(SfcFlowClassifier.class, new SfcFlowClassifierKey(portId)).build();
     }
 }
index ce2c543db5ce74f44114f5c8180da76aa2021142..907cc284be19ab362f3c5a038b65eeeca4d7c972 100644 (file)
@@ -9,10 +9,11 @@
 package org.opendaylight.netvirt.openstack.sfc.translator;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netvirt.openstack.sfc.translator.flowclassifier.FlowClassifierTranslator;
-import org.opendaylight.netvirt.openstack.sfc.translator.portchain.PortChainTranslator;
-import org.opendaylight.netvirt.openstack.sfc.translator.portchain.PortPairGroupTranslator;
-import org.opendaylight.netvirt.openstack.sfc.translator.portchain.PortPairTranslator;
+import org.opendaylight.netvirt.openstack.sfc.translator.flowclassifier.NeutronFlowClassifierListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.portchain.NeutronPortChainListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.portchain.NeutronPortPairGroupListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.portchain.NeutronPortPairListener;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePathService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.openstack.sfc.translator.config.rev160720.OpenstackSfcTranslatorConfig;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
@@ -22,30 +23,24 @@ public class OpenStackSFCTranslatorProvider implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(OpenStackSFCTranslatorProvider.class);
 
     private final DataBroker dataBroker;
-    private final BundleContext bundleContext;
-    private final FlowClassifierTranslator flowClassifierTranslator;
-    private final PortPairTranslator portPairTranslator;
-    private final PortPairGroupTranslator portPairGroupTranslator;
-    private final PortChainTranslator portChainTranslator;
+    private final RenderedServicePathService rspService;
+
     public OpenStackSFCTranslatorProvider(
             final DataBroker dataBroker,
+            final RenderedServicePathService rspService,
             final OpenstackSfcTranslatorConfig openstackSfcTranslatorConfig,
             final BundleContext bundleContext) {
         this.dataBroker = dataBroker;
-        this.bundleContext = bundleContext;
-        flowClassifierTranslator = new FlowClassifierTranslator(dataBroker);
-        portPairTranslator = new PortPairTranslator(dataBroker);
-        portPairGroupTranslator = new PortPairGroupTranslator(dataBroker);
-        portChainTranslator = new PortChainTranslator(dataBroker);
+        this.rspService = rspService;
     }
 
     //This method will be called by blueprint, during bundle initialization.
     public void start() {
         LOG.info("OpenStack SFC Translator Session started");
-        flowClassifierTranslator.start();
-        portPairTranslator.start();
-        portPairGroupTranslator.start();
-        portChainTranslator.start();
+        new NeutronFlowClassifierListener(dataBroker);
+        new NeutronPortPairListener(dataBroker);
+        new NeutronPortPairGroupListener(dataBroker);
+        new NeutronPortChainListener(dataBroker, rspService);
     }
 
     @Override
index a96a11ef5f9d184d77ae0f55322b42b3daee7940..433f2e94207224dc6a94a4ac69afb7b440d0a4bd 100644 (file)
@@ -47,9 +47,18 @@ public class OvsdbMdsalHelper {
         mdsalUtils = new MdsalUtils(this.dataBroker);
     }
 
-    public OvsdbPortMetadata getOvsdbPortMetadata(Uuid ingress) {
-        LOG.info("Extract ovsdb port details for neutron port {}", ingress.getValue());
+    public Topology getOvsdbTopologyTree() {
+        LOG.info("Reading OVSDB Topolog Tree (ovsdb:1)");
+        return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
+    }
+
+    public OvsdbPortMetadata getOvsdbPortMetadata(Uuid ingressPort) {
+        LOG.info("Extract ovsdb port details for neutron port {}", ingressPort.getValue());
         Topology ovsdbTopology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
+        return getOvsdbPortMetadata(ingressPort, ovsdbTopology);
+    }
+    public OvsdbPortMetadata getOvsdbPortMetadata(Uuid ingressPort, Topology ovsdbTopology) {
+        LOG.info("Extract ovsdb port details for neutron port {}", ingressPort.getValue());
         OvsdbPortMetadata ovsdbPortMetadata = new OvsdbPortMetadata();
         OvsdbBridgeAugmentation bridgeAugmentation = null;
         if (ovsdbTopology != null) {
@@ -61,7 +70,7 @@ public class OvsdbMdsalHelper {
                                 = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
                         List<InterfaceExternalIds> externalIds = tpAugmentation.getInterfaceExternalIds();
                         for (InterfaceExternalIds externalId : externalIds) {
-                            if(externalId.getExternalIdValue().equals(ingress.getValue())) {
+                            if(externalId.getExternalIdValue().equals(ingressPort.getValue())) {
                                 ovsdbPortMetadata.setOvsdbPort(tpAugmentation);
                                 break;
                             }
@@ -104,12 +113,16 @@ public class OvsdbMdsalHelper {
         return ovsdbPortMetadata;
     }
 
-    public String getOvsdbPortName(OvsdbTerminationPointAugmentation ovsdbPort) {
+    public static String getOvsdbPortName(OvsdbTerminationPointAugmentation ovsdbPort) {
         return ovsdbPort.getName();
     }
 
-    public String getNodeIpAddress(OvsdbNodeAugmentation ovsdbNode) {
+    public static String getNodeIpAddress(OvsdbNodeAugmentation ovsdbNode) {
         //Currently we support only ipv4
         return ovsdbNode.getConnectionInfo().getRemoteIp().getIpv4Address().getValue();
     }
+
+    public static String getNodeKey(InstanceIdentifier<?> node) {
+        return node.firstKeyOf(Node.class).getNodeId().getValue();
+    }
 }
index 0e84a696f8a8fd974f638550480b4c1b860a9aaa..fa7e41f3822617ed39d1855cfaaf15f0a3ee16d4 100644 (file)
@@ -10,14 +10,18 @@ package org.opendaylight.netvirt.openstack.sfc.translator;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.netvirt.utils.mdsal.utils.MdsalUtils;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionKey;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChains;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainKey;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarders;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderKey;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
@@ -50,6 +54,7 @@ public class SfcMdsalHelper {
         mdsalUtils = new MdsalUtils(this.dataBroker);
     }
 
+    //ACL Flow Classifier data store utility methods
     public void addAclFlowClassifier(Acl aclFlowClassifier) {
         InstanceIdentifier<Acl> aclIid = getAclPath(aclFlowClassifier.getKey());
         LOG.info("Write ACL FlowClassifier {} to config data store at {}",aclFlowClassifier, aclIid);
@@ -68,6 +73,7 @@ public class SfcMdsalHelper {
         mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, aclIid);
     }
 
+    //Service Function
     public void addServiceFunction(ServiceFunction sf) {
         InstanceIdentifier<ServiceFunction> sfIid = getSFPath(sf.getKey());
         LOG.info("Write Service Function {} to config data store at {}",sf, sfIid);
@@ -93,7 +99,19 @@ public class SfcMdsalHelper {
         return sfIid.builder().child(ServiceFunction.class, key).build();
     }
 
-    public SffName getExistingSFF(String ipAddress) {
+    private InstanceIdentifier<ServiceFunctionForwarder> getSFFPath(ServiceFunctionForwarderKey key) {
+        return sffIid.builder().child(ServiceFunctionForwarder.class, key).build();
+    }
+
+    private InstanceIdentifier<ServiceFunctionChain> getSFCPath(ServiceFunctionChainKey key) {
+        return sfcIid.builder().child(ServiceFunctionChain.class, key).build();
+    }
+
+    private InstanceIdentifier<ServiceFunctionPath> getSFPPath(ServiceFunctionPathKey key) {
+        return sfpIid.builder().child(ServiceFunctionPath.class, key).build();
+    }
+
+    public ServiceFunctionForwarder getExistingSFF(String ipAddress) {
         ServiceFunctionForwarders existingSffs = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, sffIid);
         if (existingSffs != null
                 && existingSffs.getServiceFunctionForwarder() != null
@@ -102,10 +120,34 @@ public class SfcMdsalHelper {
             List<ServiceFunctionForwarder> existingSffList = existingSffs.getServiceFunctionForwarder();
             for (ServiceFunctionForwarder sff : existingSffList) {
                 if (sff.getIpMgmtAddress().getIpv4Address().equals(new Ipv4Address(ipAddress))) {
-                    return sff.getName();
+                    return sff;
                 }
             }
         }
         return null;
     }
+
+    public void addServiceFunctionForwarder(ServiceFunctionForwarder sff) {
+        InstanceIdentifier<ServiceFunctionForwarder> sffIid = getSFFPath(sff.getKey());
+        LOG.info("Write Service Function Forwarder {} to config data store at {}",sff, sffIid);
+        mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, sffIid, sff);
+    }
+
+    public void addServiceFunctionChain(ServiceFunctionChain sfc) {
+        InstanceIdentifier<ServiceFunctionChain> sfcIid = getSFCPath(sfc.getKey());
+        LOG.info("Write Service Function Chain {} to config data store at {}",sfc, sfcIid);
+        mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, sfcIid, sfc);
+    }
+
+    public void removeServiceFunctionChain(ServiceFunctionChainKey sfcKey) {
+        InstanceIdentifier<ServiceFunctionChain> sfcIid = getSFCPath(sfcKey);
+        LOG.info("Remove Service Function Chain {} from config data store at {}",sfcKey, sfcIid);
+        mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, sfcIid);
+    }
+
+    public void addServiceFunctionPath(ServiceFunctionPath sfp) {
+        InstanceIdentifier<ServiceFunctionPath> sfpIid = getSFPPath(sfp.getKey());
+        LOG.info("Write Service Function Path {} to config data store at {}",sfp, sfpIid);
+        mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, sfpIid, sfp);
+    }
 }
index a0ae0e1a5dfb825310b3b3c28bd58640799d24c7..4a970c116e2d51cd1bd44e09c4be25d30946e98b 100644 (file)
@@ -7,31 +7,22 @@
  */
 package org.opendaylight.netvirt.openstack.sfc.translator.flowclassifier;
 
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.openstack.sfc.translator.INeutronSfcDataProcessor;
-import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
-import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
-import org.opendaylight.netvirt.utils.mdsal.utils.MdsalUtils;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv6Acl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntriesBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.ActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.MatchesBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.AceIpVersion;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6Builder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRange;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.SourcePortRangeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.EthertypeV4;
@@ -39,89 +30,36 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolTcp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.ProtocolUdp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.acl.rev150105.RedirectToSfcBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.Closeable;
 import java.util.ArrayList;
 
 /**
  * Class will convert OpenStack Flow Classifier API yang models to
  * OpenDaylight ACL yang models.
  */
-public class FlowClassifierTranslator implements INeutronSfcDataProcessor<SfcFlowClassifier>{
+public class FlowClassifierTranslator {
     private static final Logger LOG = LoggerFactory.getLogger(FlowClassifierTranslator.class);
     private static final Short PROTO_TCP = 6;
     private static final Short PROTO_UDP = 17;
     private static final String RULE = "_rule";
 
-    private final DataBroker db;
-    private NeutronFlowClassifierListener neutronFlowClassifierListener;
-    private final SfcMdsalHelper sfcMdsalHelper;
-    private final NeutronMdsalHelper neutronMdsalHelper;
-
-    public FlowClassifierTranslator(DataBroker db) {
-        this.db = db;
-        sfcMdsalHelper = new SfcMdsalHelper(db);
-        neutronMdsalHelper = new NeutronMdsalHelper(db);
-    }
-
-    public void start() {
-        LOG.info("Flow Classifier Translator Initialized.");
-        if(neutronFlowClassifierListener == null) {
-            neutronFlowClassifierListener = new NeutronFlowClassifierListener(db, this);
-        }
-    }
-
-    /**
-     * Method removes Acl respective to SfcFlowClassifier which is identified by InstanceIdentifier.
-     *
-     * @param path - the whole path to SfcFlowClassifier
-     * @param deletedSfcFlowClassifier        - SfcFlowClassifier for removing
-     */
-    @Override
-    public void remove(InstanceIdentifier<SfcFlowClassifier> path, SfcFlowClassifier deletedSfcFlowClassifier) {
-        Acl aclFlowClassifier = buildAcl(deletedSfcFlowClassifier);
-        sfcMdsalHelper.removeAclFlowClassifier(aclFlowClassifier);
-    }
-
-    /**
-     * Method updates the original SfcFlowClassifier to the update SfcFlowClassifier.
-     * Both are identified by same InstanceIdentifier.
-     *
-     * @param path - the whole path to SfcFlowClassifier
-     * @param originalSfcFlowClassifier   - original SfcFlowClassifier (for update)
-     * @param updatedSfcFlowClassifier     - changed SfcFlowClassifier (contain updates)
-     */
-    @Override
-    public void update(InstanceIdentifier<SfcFlowClassifier> path,
-                       SfcFlowClassifier originalSfcFlowClassifier,
-                       SfcFlowClassifier updatedSfcFlowClassifier) {
-
-        Acl aclFlowClassifier = buildAcl(updatedSfcFlowClassifier);
-        sfcMdsalHelper.updateAclFlowClassifier(aclFlowClassifier);
-    }
-
-    /**
-     * Method adds the SfcFlowClassifier which is identified by InstanceIdentifier
-     * to device.
-     *
-     * @param path - the whole path to new SfcFlowClassifier
-     * @param sfcFlowClassifier        - new SfcFlowClassifier
-     */
-    @Override
-    public void add(InstanceIdentifier<SfcFlowClassifier> path, SfcFlowClassifier sfcFlowClassifier) {
-        Acl aclFlowClassifier = buildAcl(sfcFlowClassifier);
-        sfcMdsalHelper.addAclFlowClassifier(aclFlowClassifier);
+    public static Acl buildAcl(SfcFlowClassifier flowClassifier) {
+        return buildAcl(flowClassifier, null);
     }
-
-    private Acl buildAcl(SfcFlowClassifier flowClassifier) {
+    public static Acl buildAcl(SfcFlowClassifier flowClassifier, String rspName) {
         LOG.info("OpenStack Networkgin SFC pushed Flow classfier : {}", flowClassifier);
         AclBuilder aclBuilder = new AclBuilder();
         AccessListEntriesBuilder accessListEntriesBuilder = new AccessListEntriesBuilder();
         AceBuilder aceBuilder = new AceBuilder();
         MatchesBuilder matchesBuilder = new MatchesBuilder();
+
+        ActionsBuilder actionsBuilder = new ActionsBuilder();
+        RedirectToSfcBuilder redirectToSfcBuilder = new RedirectToSfcBuilder();
+
         AceIpBuilder aceIpBuilder = new AceIpBuilder();
         DestinationPortRangeBuilder destinationPortRange = new DestinationPortRangeBuilder();
         SourcePortRangeBuilder sourcePortRangeBuilder = new SourcePortRangeBuilder();
@@ -201,6 +139,12 @@ public class FlowClassifierTranslator implements INeutronSfcDataProcessor<SfcFlo
 
         matchesBuilder.setAceType(aceIpBuilder.build());
 
+        //Set redirect-to-rsp action if rsp name is provided
+        if (rspName != null) {
+            redirectToSfcBuilder.setRspName(rspName);
+            actionsBuilder.addAugmentation(RedirectToSfc.class, redirectToSfcBuilder.build());
+            aceBuilder.setActions(actionsBuilder.build());
+        }
         aceBuilder.setMatches(matchesBuilder.build());
 
         //OpenStack networking-sfc don't pass action information
index 09854e1c490d66b23d80f8e0711267fb94af6a19..b2446053fa5c626cdd11fe869729af66f6827cc7 100644 (file)
@@ -11,6 +11,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.netvirt.openstack.sfc.translator.DelegatingDataTreeListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.SfcFlowClassifiers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifier;
@@ -24,8 +26,54 @@ public class NeutronFlowClassifierListener extends DelegatingDataTreeListener<Sf
     private static final InstanceIdentifier<SfcFlowClassifier> flowClassifiersIid =
             InstanceIdentifier.create(Neutron.class).child(SfcFlowClassifiers.class).child(SfcFlowClassifier.class);
 
-    public NeutronFlowClassifierListener(DataBroker db, FlowClassifierTranslator flowClassifierTranslator) {
-        super(flowClassifierTranslator, db,
-                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,flowClassifiersIid));
+    private final SfcMdsalHelper sfcMdsalHelper;
+
+    public NeutronFlowClassifierListener(DataBroker db) {
+        super(db, new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,flowClassifiersIid));
+        sfcMdsalHelper = new SfcMdsalHelper(db);
+
+    }
+
+    /**
+     * Method removes Acl respective to SfcFlowClassifier which is identified by InstanceIdentifier.
+     *
+     * @param path - the whole path to SfcFlowClassifier
+     * @param deletedSfcFlowClassifier        - SfcFlowClassifier for removing
+     */
+    @Override
+    public void remove(InstanceIdentifier<SfcFlowClassifier> path, SfcFlowClassifier deletedSfcFlowClassifier) {
+        Acl aclFlowClassifier = FlowClassifierTranslator.buildAcl(deletedSfcFlowClassifier);
+        sfcMdsalHelper.removeAclFlowClassifier(aclFlowClassifier);
+    }
+
+    /**
+     * Method updates the original SfcFlowClassifier to the update SfcFlowClassifier.
+     * Both are identified by same InstanceIdentifier.
+     *
+     * @param path - the whole path to SfcFlowClassifier
+     * @param originalSfcFlowClassifier   - original SfcFlowClassifier (for update)
+     * @param updatedSfcFlowClassifier     - changed SfcFlowClassifier (contain updates)
+     */
+    @Override
+    public void update(InstanceIdentifier<SfcFlowClassifier> path,
+                       SfcFlowClassifier originalSfcFlowClassifier,
+                       SfcFlowClassifier updatedSfcFlowClassifier) {
+
+        Acl aclFlowClassifier = FlowClassifierTranslator.buildAcl(updatedSfcFlowClassifier);
+        sfcMdsalHelper.updateAclFlowClassifier(aclFlowClassifier);
     }
+
+    /**
+     * Method adds the SfcFlowClassifier which is identified by InstanceIdentifier
+     * to device.
+     *
+     * @param path - the whole path to new SfcFlowClassifier
+     * @param sfcFlowClassifier        - new SfcFlowClassifier
+     */
+    @Override
+    public void add(InstanceIdentifier<SfcFlowClassifier> path, SfcFlowClassifier sfcFlowClassifier) {
+        Acl aclFlowClassifier = FlowClassifierTranslator.buildAcl(sfcFlowClassifier);
+        sfcMdsalHelper.addAclFlowClassifier(aclFlowClassifier);
+    }
+
 }
index 5609da87e6c361dce860a173f0fd9376914400f5..49ca299c6aa2e115015389ffab986c992ac61ef5 100644 (file)
@@ -11,20 +11,268 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.netvirt.openstack.sfc.translator.DelegatingDataTreeListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbPortMetadata;
+import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.flowclassifier.FlowClassifierTranslator;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathOutput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePathService;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.flow.classifier.rev160511.sfc.flow.classifiers.attributes.sfc.flow.classifiers.SfcFlowClassifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.PortChains;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.chains.PortChain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 /**
  * OpenDaylight Neutron Port Chain yang models data change listener
  */
 public class NeutronPortChainListener extends DelegatingDataTreeListener<PortChain> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChainListener.class);
+
     private static final InstanceIdentifier<PortChain> portChainIid =
             InstanceIdentifier.create(Neutron.class).child(PortChains.class).child(PortChain.class);
+    private final SfcMdsalHelper sfcMdsalHelper;
+    private final NeutronMdsalHelper neutronMdsalHelper;
+    private final OvsdbMdsalHelper ovsdbMdsalHelper;
+    private final RenderedServicePathService rspService;
+
+    public NeutronPortChainListener(DataBroker db, RenderedServicePathService rspService) {
+        super(db,new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portChainIid));
+        sfcMdsalHelper = new SfcMdsalHelper(db);
+        neutronMdsalHelper = new NeutronMdsalHelper(db);
+        ovsdbMdsalHelper = new OvsdbMdsalHelper(db);
+        this.rspService = rspService;
+    }
+
+    /**
+     * Method removes PortChain which is identified by InstanceIdentifier.
+     *
+     * @param path - the whole path to PortChain
+     * @param deletedPortChain        - PortChain for removing
+     */
+    @Override
+    public void remove(InstanceIdentifier<PortChain> path, PortChain deletedPortChain) {
+        sfcMdsalHelper.removeServiceFunctionChain(PortChainTranslator.getSFCKey(deletedPortChain));
+    }
+
+    /**
+     * Method updates the original PortChain to the update PortChain.
+     * Both are identified by same InstanceIdentifier.
+     *
+     * @param path - the whole path to PortChain
+     * @param originalPortChain   - original PortChain (for update)
+     * @param updatePortChain     - changed PortChain (contain updates)
+     */
+    @Override
+    public void update(InstanceIdentifier<PortChain> path, PortChain originalPortChain, PortChain updatePortChain) {
+        //TODO: Add support for chain update
+    }
+
+    /**
+     * Method adds the PortChain which is identified by InstanceIdentifier
+     * to device.
+     *
+     * @param path - the whole path to new PortChain
+     * @param newPortChain        - new PortChain
+     */
+    @Override
+    public void add(InstanceIdentifier<PortChain> path, PortChain newPortChain) {
+        processPortChain(newPortChain);
+    }
+
+    private void processPortChain(PortChain newPortChain) {
+        //List of Port Pair Group attached to the Port Chain
+        List<PortPairGroup> portPairGroupList = new ArrayList<>();
+        //Port Pair Group and associated Port Pair
+        Map<Uuid, List<PortPair>> groupPortPairsList = new HashMap<>();
+        //Map of Port Pair uuid and Port pair ingress port related Neutron Port
+        Map<Uuid, Port> portPairToNeutronPortMap = new HashMap<>();
+
+        //Mapping of Port Pair UUID and OvsdbPortMetadata of the port pair ingress port
+        Map<Uuid, OvsdbPortMetadata> portPairOvsdbMetadata = new HashMap<>();
+
+        Map<Uuid, ServiceFunctionForwarderBuilder> portPairGroupToSFFMap = new HashMap<>();
+        List<ServiceFunction> portChainServiceFunctionList = new ArrayList<>();
+
+        //Read chain related port pair group, port pair and neutron port from neutron data store
+        for (Uuid ppgUuid : newPortChain.getPortPairGroups()) {
+            PortPairGroup ppg = neutronMdsalHelper.getNeutronPortPairGroup(ppgUuid);
+            if (ppg != null) {
+                List<PortPair> portPairList = new ArrayList<>();
+                portPairGroupList.add(ppg);
+                for(Uuid ppUuid : ppg.getPortPairs()) {
+                    PortPair pp = neutronMdsalHelper.getNeutronPortPair(ppgUuid);
+                    if (pp != null) {
+                        portPairList.add(pp);
+                        //NOTE:Assuming that ingress and egress port is same.
+                        Port neutronPort = neutronMdsalHelper.getNeutronPort(pp.getIngress());
+                        if (neutronPort != null) {
+                            portPairToNeutronPortMap.put(ppgUuid, neutronPort);
+                        }
+                    }
+                }
+                groupPortPairsList.put(ppgUuid, portPairList);
+            }
+        }
+
+        Topology ovsdbTopology = ovsdbMdsalHelper.getOvsdbTopologyTree();
+
+        //Read ovsdb port details related to neutron port. Each Port pair has two neutron port
+        //With the current implementation, i am assuming that we support SF only with single port
+        //that act as a ingress as well as egress.
+        for(Map.Entry<Uuid, Port> neutronPortEntry : portPairToNeutronPortMap.entrySet()) {
+            OvsdbPortMetadata ovsdbPortMetadata =
+                    ovsdbMdsalHelper.getOvsdbPortMetadata(
+                            neutronPortEntry.getValue().getKey().getUuid(),
+                            ovsdbTopology);
+
+            if(ovsdbPortMetadata != null) {
+                portPairOvsdbMetadata.put(neutronPortEntry.getKey(), ovsdbPortMetadata);
+            }
+        }
+
+        //For each port pair group
+        for (PortPairGroup ppg : portPairGroupList) {
+            List<ServiceFunctionBuilder> portPairSFList = new ArrayList<>();
+
+            List<PortPair> portPairList =  groupPortPairsList.get(ppg.getUuid());
+            Map<Uuid, OvsdbPortMetadata> metadataList = new HashMap<>();
+            //Generate OvsdbPortMetadata for list of all the port pair
+            for (PortPair portPair : portPairList) {
+                OvsdbPortMetadata metadata = portPairOvsdbMetadata.get(portPair.getIngress());
+
+                if (metadata != null) {
+                    metadataList.put(portPair.getIngress(), metadata);
+                }
+            }
+
+            //Build the SFF Builder from port pair group
+            ServiceFunctionForwarderBuilder sffBuilder =
+                    PortPairGroupTranslator.buildServiceFunctionForwarder(ppg,portPairList, metadataList);
+
+            //Check if SFF already exist
+            ServiceFunctionForwarder existingSff =
+                    sfcMdsalHelper.getExistingSFF(sffBuilder.getIpMgmtAddress().getIpv4Address().getValue());
+            if(existingSff != null) {
+                LOG.info("SFF already exist for Port Pair Group {}. Existing SFF is {}",ppg, existingSff);
+                sffBuilder = new ServiceFunctionForwarderBuilder(existingSff);
+            }
+            //Add SFF builder to the map for later reference
+            portPairGroupToSFFMap.put(ppg.getUuid(), sffBuilder);
+
+            //Generate all the SF and write it to SFC data store
+            for (PortPair portPair : portPairList) {
+                OvsdbPortMetadata metadata = portPairOvsdbMetadata.get(portPair.getIngress());
+                //Build the service function for the given port pair.
+                ServiceFunctionBuilder sfBuilder = PortPairTranslator.buildServiceFunction(portPair,
+                        ppg,
+                        portPairToNeutronPortMap.get(portPair.getIngress()),
+                        metadata,
+                        sffBuilder.build());
+
+                if (sfBuilder != null) {
+                    //Write the Service Function to SFC data store.
+                    sfcMdsalHelper.addServiceFunction(sfBuilder.build());
+
+                    //Add to the list, to populated SFF Service Function Dictionary
+                    portPairSFList.add(sfBuilder);
+
+                    //Add the SF to Port Chain related SF list
+                    portChainServiceFunctionList.add(sfBuilder.build());
+                } else {
+                    LOG.warn("Service Function building failed for Port Pair {}", portPair);
+                }
+            }
+
+            //Update the Service Function Dictionary of SFF
+            for (ServiceFunctionBuilder sf : portPairSFList) {
+                PortPairGroupTranslator.buildServiceFunctionDictonary(sffBuilder, sf.build());
+            }
+            // Send SFF create request
+            LOG.info("Add Service Function Forwarder {} for Port Pair Group {}", sffBuilder.build(), ppg);
+            sfcMdsalHelper.addServiceFunctionForwarder(sffBuilder.build());
+        }
+        //Build Service Function Chain Builder
+        ServiceFunctionChain sfc =
+                PortChainTranslator.buildServiceFunctionChain(newPortChain, portChainServiceFunctionList);
+
+        //Write SFC to data store
+        if (sfc != null) {
+            sfcMdsalHelper.addServiceFunctionChain(sfc);
+        } else {
+            LOG.warn("Service Function Chain building failed for Port Chain {}", newPortChain);
+        }
+
+        // Build Service Function Path Builder
+        ServiceFunctionPath sfp = PortChainTranslator.buildServiceFunctionPath(sfc);
+        //Write SFP to data store
+        if (sfp != null) {
+           sfcMdsalHelper.addServiceFunctionPath(sfp);
+        } else {
+            LOG.warn("Service Function Path building failed for Service Chain {}", sfc);
+        }
+
+        //TODO:Generate Flow Classifiers and augment RSP on it.
+
+        if (this.rspService != null) {
+            // Build Create Rendered Service Path input
+            CreateRenderedPathInput rpInput = PortChainTranslator.buildRenderedServicePathInput(sfp);
+
+            //Call Create Rendered Service Path RPC call
+            if (rpInput != null) {
+                Future<RpcResult<CreateRenderedPathOutput>> result =  this.rspService.createRenderedPath(rpInput);
+                try {
+                    result.get();
+                    processFlowClassifiers(newPortChain, newPortChain.getFlowClassifiers(), rpInput.getName());
+                } catch (InterruptedException | ExecutionException e) {
+                    LOG.error("Error occurred during creating Rendered Service Path using RPC call", e);
+                }
+            }
+        } else {
+            LOG.error("Rendered Path Service is not available, can't create Rendered Path for Port Chain", newPortChain);
+        }
+    }
+
+    private void processFlowClassifiers(PortChain pc, List<Uuid> flowClassifiers, String rspName) {
+        for (Uuid uuid : flowClassifiers) {
+            SfcFlowClassifier fc = neutronMdsalHelper.getNeutronFlowClassifier(uuid);
+            if (fc != null) {
+                Acl acl = FlowClassifierTranslator.buildAcl(fc, rspName);
+                if (acl != null ) {
+                    sfcMdsalHelper.addAclFlowClassifier(acl);
+                } else {
+                    LOG.warn("Acl building failed for flow classifier {}. Traffic might not be redirected to RSP", fc);
+                }
 
-    public NeutronPortChainListener(DataBroker db, PortChainTranslator portChainTranslator) {
-        super(portChainTranslator, db,
-                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portChainIid));
+            } else {
+                LOG.error("Neutron Flow Classifier {} attached to Port Chain {} is not present in the neutron data " +
+                        "store", uuid, pc);
+            }
+        }
     }
 }
index 26f4a8f21973aa36d2fcdd94078410fdf93fe7f8..d39b10a8bd85404720def33bae4eaa93f9b4dacb 100644 (file)
@@ -17,14 +17,51 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.a
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /**
- * OpenDaylight Neutron Port Group yang models data change listener
+ * OpenDaylight Neutron Port Pair Group yang models data change listener
  */
 public class NeutronPortPairGroupListener extends DelegatingDataTreeListener<PortPairGroup> {
     private static final InstanceIdentifier<PortPairGroup> portPairGroupIid =
             InstanceIdentifier.create(Neutron.class).child(PortPairGroups.class).child(PortPairGroup.class);
 
-    public NeutronPortPairGroupListener(DataBroker db, PortPairGroupTranslator portPairGroupTranslator) {
-        super(portPairGroupTranslator, db,
-                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portPairGroupIid));
+    public NeutronPortPairGroupListener(DataBroker db) {
+        super(db,new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portPairGroupIid));
+    }
+
+    /**
+     * Method removes PortPairGroup which is identified by InstanceIdentifier.
+     *
+     * @param path - the whole path to PortPairGroup
+     * @param deletedPortPairGroup        - PortPairGroup for removing
+     */
+    @Override
+    public void remove(InstanceIdentifier<PortPairGroup> path, PortPairGroup deletedPortPairGroup) {
+        //NO-OP
+    }
+
+    /**
+     * Method updates the original PortPairGroup to the update PortPairGroup.
+     * Both are identified by same InstanceIdentifier.
+     *
+     * @param path - the whole path to PortPairGroup
+     * @param originalPortPairGroup   - original PortPairGroup (for update)
+     * @param updatePortPairGroup     - changed PortPairGroup (contain updates)
+     */
+    @Override
+    public void update(InstanceIdentifier<PortPairGroup> path,
+                       PortPairGroup originalPortPairGroup,
+                       PortPairGroup updatePortPairGroup) {
+        //NO-OP
+    }
+
+    /**
+     * Method adds the PortPairGroup which is identified by InstanceIdentifier
+     * to device.
+     *
+     * @param path - the whole path to new PortPairGroup
+     * @param newPortPairGroup        - new PortPairGroup
+     */
+    @Override
+    public void add(InstanceIdentifier<PortPairGroup> path, PortPairGroup newPortPairGroup) {
+        //NO-OP
     }
 }
index f917d12085efe650477c90e8ee0fbd62ec8b8a9d..aab654518931a02eb362ccdb22ea918c91d7a2de 100644 (file)
@@ -11,6 +11,9 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.netvirt.openstack.sfc.translator.DelegatingDataTreeListener;
+import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.PortPairs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
@@ -23,8 +26,54 @@ public class NeutronPortPairListener extends DelegatingDataTreeListener<PortPair
     private static final InstanceIdentifier<PortPair> portPairIid =
             InstanceIdentifier.create(Neutron.class).child(PortPairs.class).child(PortPair.class);
 
-    public NeutronPortPairListener(DataBroker db, PortPairTranslator portPairTranslator) {
-        super(portPairTranslator, db,
-                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portPairIid));
+    private final DataBroker db;
+    private final SfcMdsalHelper sfcMdsalHelper;
+    private final NeutronMdsalHelper neutronMdsalHelper;
+    private final OvsdbMdsalHelper ovsdbMdsalHelper;
+
+    public NeutronPortPairListener(DataBroker db) {
+        super(db,new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, portPairIid));
+        this.db = db;
+        sfcMdsalHelper = new SfcMdsalHelper(db);
+        neutronMdsalHelper = new NeutronMdsalHelper(db);
+        ovsdbMdsalHelper = new OvsdbMdsalHelper(db);
+    }
+
+    /**
+     * Method removes PortPair which is identified by InstanceIdentifier.
+     *
+     * @param path - the whole path to PortPair
+     * @param deletedPortPair        - PortPair for removing
+     */
+    @Override
+    public void remove(InstanceIdentifier<PortPair> path, PortPair deletedPortPair) {
+        sfcMdsalHelper.removeServiceFunction(PortPairTranslator.getSFKey(deletedPortPair));
+    }
+
+    /**
+     * Method updates the original PortPair to the update PortPair.
+     * Both are identified by same InstanceIdentifier.
+     *
+     * @param path - the whole path to PortPair
+     * @param originalPortPair   - original PortPair (for update)
+     * @param updatePortPair     - changed PortPair (contain updates)
+     */
+    @Override
+    public void update(InstanceIdentifier<PortPair> path, PortPair originalPortPair, PortPair updatePortPair) {
+        //NO-OP
+    }
+
+    /**
+     * Method adds the PortPair which is identified by InstanceIdentifier
+     * to device.
+     *
+     * @param path - the whole path to new PortPair
+     * @param newPortPair        - new PortPair
+     */
+    @Override
+    public void add(InstanceIdentifier<PortPair> path, PortPair newPortPair) {
+        //NO-OP
+        // Port Pair data written in neutron data store will be used
+        // When user will create port chain.
     }
 }
index a61a0c6d1f29c3575453ee43ef4159d0e0e7ed1e..c20572df38ed94d7e325f22e572bce11a890ceb2 100644 (file)
@@ -7,73 +7,94 @@
  */
 package org.opendaylight.netvirt.openstack.sfc.translator.portchain;
 
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netvirt.openstack.sfc.translator.INeutronSfcDataProcessor;
-import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
-import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
+import com.google.common.base.Preconditions;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfcName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunctionBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunctionKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.port.chain.attributes.ChainParameters;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.chains.PortChain;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Class will convert OpenStack Port Chain API yang models present in
  * neutron northbound project to OpenDaylight SFC yang models.
  */
-public class PortChainTranslator implements INeutronSfcDataProcessor<PortChain> {
+public class PortChainTranslator {
     private static final Logger LOG = LoggerFactory.getLogger(PortChainTranslator.class);
+    private static final String SYMMETRIC_PARAM = "symmetric";
+    private static final String SFP_NAME_PREFIX = "Path-";
 
-    private final DataBroker db;
-    private NeutronPortChainListener neutronPortChainListener;
-    private final SfcMdsalHelper sfcMdsalHelper;
-    private final NeutronMdsalHelper neutronMdsalHelper;
+    public static ServiceFunctionChain buildServiceFunctionChain(
+            PortChain portChain, List<ServiceFunction> sfList) {
+        ServiceFunctionChainBuilder sfcBuilder = new ServiceFunctionChainBuilder();
+        sfcBuilder.setName(new SfcName(portChain.getName()));
+        sfcBuilder.setKey(new ServiceFunctionChainKey(sfcBuilder.getName()));
 
-    public PortChainTranslator(DataBroker db) {
-        this.db = db;
-        sfcMdsalHelper = new SfcMdsalHelper(db);
-        neutronMdsalHelper = new NeutronMdsalHelper(db);
-    }
+        //By default set it to false. If user specify it in chain parameters, it
+        //will be overridden.
+        sfcBuilder.setSymmetric(false);
 
-    public void start() {
-        LOG.info("Port Chain Translator Initialized.");
-        if(neutronPortChainListener == null) {
-            neutronPortChainListener = new NeutronPortChainListener(db, this);
+        //Set service functions
+        List<SfcServiceFunction> sfcSfList = new ArrayList<>();
+        for(ServiceFunction sf : sfList) {
+            SfcServiceFunctionBuilder sfcSfBuilder = new SfcServiceFunctionBuilder();
+            sfcSfBuilder.setName(sf.getName().getValue());
+            sfcSfBuilder.setType(sf.getType());
+            sfcSfBuilder.setKey(new SfcServiceFunctionKey(sfcSfBuilder.getName()));
+
+            //NOTE: no explicit order is set.
+            sfcSfList.add(sfcSfBuilder.build());
+        }
+        List<ChainParameters> cpList = portChain.getChainParameters();
+        if (cpList != null && !cpList.isEmpty()) {
+            for (ChainParameters cp : cpList) {
+                if(cp.getChainParameter().equals(SYMMETRIC_PARAM)) {
+                    //Override the symmetric default value.
+                    sfcBuilder.setSymmetric(new Boolean(cp.getChainParameterValue()));
+                    break;
+                }
+            }
         }
+        sfcBuilder.setSfcServiceFunction(sfcSfList);
+        return sfcBuilder.build();
     }
 
-    /**
-     * Method removes PortChain which is identified by InstanceIdentifier.
-     *
-     * @param path - the whole path to PortChain
-     * @param deletedPortChain        - PortChain for removing
-     */
-    @Override
-    public void remove(InstanceIdentifier<PortChain> path, PortChain deletedPortChain) {
+    public static ServiceFunctionPath buildServiceFunctionPath(ServiceFunctionChain sfc) {
+        Preconditions.checkNotNull(sfc, "Service Function Chain must not be null");
+        ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
 
-    }
-
-    /**
-     * Method updates the original PortChain to the update PortChain.
-     * Both are identified by same InstanceIdentifier.
-     *
-     * @param path - the whole path to PortChain
-     * @param originalPortChain   - original PortChain (for update)
-     * @param updatePortChain     - changed PortChain (contain updates)
-     */
-    @Override
-    public void update(InstanceIdentifier<PortChain> path, PortChain originalPortChain, PortChain updatePortChain) {
+        //Set the name
+        sfpBuilder.setName(new SfpName(SFP_NAME_PREFIX + sfc.getName().getValue()));
 
+        sfpBuilder.setSymmetric(sfc.isSymmetric());
+        //Set related SFC name
+        sfpBuilder.setServiceChainName(sfc.getName());
+        return sfpBuilder.build();
     }
 
-    /**
-     * Method adds the PortChain which is identified by InstanceIdentifier
-     * to device.
-     *
-     * @param path - the whole path to new PortChain
-     * @param newPortChain        - new PortChain
-     */
-    @Override
-    public void add(InstanceIdentifier<PortChain> path, PortChain newPortChain) {
+    public static CreateRenderedPathInput buildRenderedServicePathInput(ServiceFunctionPath sfp) {
+        CreateRenderedPathInputBuilder rpInputBuilder = new CreateRenderedPathInputBuilder();
+        rpInputBuilder.setName(sfp.getName().getValue());
+        rpInputBuilder.setSymmetric(sfp.isSymmetric());
+        rpInputBuilder.setParentServiceFunctionPath(sfp.getName().getValue());
+        return rpInputBuilder.build();
+    }
 
+    public static ServiceFunctionChainKey getSFCKey(PortChain portChain) {
+        return new ServiceFunctionChainKey(new SfcName(portChain.getName()));
     }
 }
index 0185493b6e3f6e654380133d318fe9b19e1a5081..25a1b94f330cd116e2219f7e0cdc7e6ece774b81 100644 (file)
  */
 package org.opendaylight.netvirt.openstack.sfc.translator.portchain;
 
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netvirt.openstack.sfc.translator.INeutronSfcDataProcessor;
-import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
-import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
+import com.google.common.base.Preconditions;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbMdsalHelper;
+import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbPortMetadata;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SnName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsBridgeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsLocatorOptionsAugmentation;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsLocatorOptionsAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.SffOvsNodeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.bridge.OvsBridgeBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.node.OvsNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.options.OvsOptionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.Open;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocator;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocatorBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.sff.data.plane.locator.DataPlaneLocatorBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionary;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionaryBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionaryKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.service.function.dictionary.SffSfDataPlaneLocatorBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.VxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.IpBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * Class will convert OpenStack Port Pair API yang models present in
  * neutron northbound project to OpenDaylight SFC yang models.
  */
-public class PortPairGroupTranslator implements INeutronSfcDataProcessor<PortPairGroup> {
+public class PortPairGroupTranslator {
     private static final Logger LOG = LoggerFactory.getLogger(PortPairGroupTranslator.class);
+    private static final String OPT_FLOW_STR = "flow";
+    private static final String OPT_DST_PORT = "6633";
 
-    private final DataBroker db;
-    private NeutronPortPairGroupListener neutronPortPairGroupListener;
-    private final SfcMdsalHelper sfcMdsalHelper;
-    private final NeutronMdsalHelper neutronMdsalHelper;
+    private static final AtomicInteger counter = new AtomicInteger(0);
+    private static final String SFF_DEFAULT_NAME = "sff";
 
-    public PortPairGroupTranslator(DataBroker db) {
-        this.db = db;
-        sfcMdsalHelper = new SfcMdsalHelper(db);
-        neutronMdsalHelper = new NeutronMdsalHelper(db);
-    }
+    public static ServiceFunctionForwarderBuilder buildServiceFunctionForwarder(
+            PortPairGroup portPairGroup,
+            List<PortPair> portPairs,
+            Map<Uuid, OvsdbPortMetadata> ovsdbPortsMetadata) {
+        Preconditions.checkNotNull(portPairGroup, "Port pair group must not be null");
+
+        ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder();
+        SffOvsBridgeAugmentationBuilder sffOvsBridgeAugBuilder = new SffOvsBridgeAugmentationBuilder();
+        SffOvsNodeAugmentationBuilder sffOvsNodeAugBuilder = new SffOvsNodeAugmentationBuilder();
+
+        List<SffDataPlaneLocator> sffDataPlaneLocator = new ArrayList<>();
+        SffDataPlaneLocatorBuilder sffDplBuilder = new SffDataPlaneLocatorBuilder();
+        DataPlaneLocatorBuilder dplBuilder = new DataPlaneLocatorBuilder();
 
-    public void start() {
-        LOG.info("Port Pair Group Translator Initialized.");
-        if(neutronPortPairGroupListener == null) {
-            neutronPortPairGroupListener = new NeutronPortPairGroupListener(db, this);
+        IpBuilder sffLocator = new IpBuilder();
+
+        //Currently we only support one SF per type. Mean, one port-pair per port-pair-group.
+        //Get port pair from neutron data store.
+        PortPair portPair = portPairs.get(0);
+        if (portPair == null) {
+           LOG.error("Port pair {} does not exist in the neutron data store. Port Pair Group {} request can't be " +
+                   "processed.", portPairGroup.getPortPairs().get(0), portPairGroup);
+            return null;
         }
-    }
+        //Get metadata of neutron port related to port pair ingress port from ovsdb data store.
+        OvsdbPortMetadata ovsdbPortMetadata = ovsdbPortsMetadata.get(portPair.getIngress());
 
-    /**
-     * Method removes PortPairGroup which is identified by InstanceIdentifier.
-     *
-     * @param path - the whole path to PortPairGroup
-     * @param deletedPortPairGroup        - PortPairGroup for removing
-     */
-    @Override
-    public void remove(InstanceIdentifier<PortPairGroup> path, PortPairGroup deletedPortPairGroup) {
+        //Convert the port pair to service function
 
-    }
+        //Set SFF DPL transport type
+        dplBuilder.setTransport(VxlanGpe.class);
 
-    /**
-     * Method updates the original PortPairGroup to the update PortPairGroup.
-     * Both are identified by same InstanceIdentifier.
-     *
-     * @param path - the whole path to PortPairGroup
-     * @param originalPortPairGroup   - original PortPairGroup (for update)
-     * @param updatePortPairGroup     - changed PortPairGroup (contain updates)
-     */
-    @Override
-    public void update(InstanceIdentifier<PortPairGroup> path,
-                       PortPairGroup originalPortPairGroup,
-                       PortPairGroup updatePortPairGroup) {
+        //Set SFF Locator Type
+        OvsdbNodeAugmentation ovsdbNodeAug = ovsdbPortMetadata.getOvsdbNode();
+        if (ovsdbNodeAug != null ) {
+            sffLocator.setIp(ovsdbNodeAug.getConnectionInfo().getRemoteIp());
+            sffLocator.setPort(ovsdbNodeAug.getConnectionInfo().getRemotePort());
+        }
+        dplBuilder.setLocatorType(sffLocator.build());
+        //set data-path-locator for sff-data-path-locator
+        sffDplBuilder.setDataPlaneLocator(dplBuilder.build());
+
+        //Set location options for sff-dp-locator
+        sffDplBuilder.addAugmentation(SffOvsLocatorOptionsAugmentation.class, buildOvsOptions().build());
+
+        //Set ovsdb bridge name for sff
+        OvsBridgeBuilder ovsBridgeBuilder = new OvsBridgeBuilder();
+        OvsdbBridgeAugmentation ovsdbBridgeAugmentation = ovsdbPortMetadata.getOvsdbBridgeNode();
+        if (ovsdbBridgeAugmentation != null) {
+            ovsBridgeBuilder.setBridgeName(ovsdbBridgeAugmentation.getBridgeName().getValue());
 
+            //Set SFF name
+            String serviceNode = OvsdbMdsalHelper.getNodeKey(ovsdbBridgeAugmentation.getManagedBy().getValue());
+            if(serviceNode.isEmpty()) {
+                serviceNode += SFF_DEFAULT_NAME + counter.incrementAndGet();
+                sffBuilder.setName(new SffName(serviceNode));
+                sffBuilder.setServiceNode(new SnName(serviceNode));
+            } else {
+                //Set service node to ovsdbNode
+                sffBuilder.setServiceNode(new SnName(serviceNode));
+
+                //Set SFF name to ovsdbBridgeNode
+                serviceNode += "/" + ovsdbBridgeAugmentation.getBridgeName().getValue();
+                sffBuilder.setName(new SffName(serviceNode));
+            }
+
+            //Set ovsdb-node iid reference for SFF
+            OvsNodeBuilder ovsNodeBuilder = new OvsNodeBuilder();
+            ovsNodeBuilder.setNodeId(ovsdbBridgeAugmentation.getManagedBy());
+            sffOvsNodeAugBuilder.setOvsNode(ovsNodeBuilder.build());
+            sffBuilder.addAugmentation(SffOvsNodeAugmentation.class, sffOvsNodeAugBuilder.build());
+        }
+        sffOvsBridgeAugBuilder.setOvsBridge(ovsBridgeBuilder.build());
+        sffBuilder.addAugmentation(SffOvsBridgeAugmentation.class, sffOvsBridgeAugBuilder.build());
+
+        //Set management ip, same to the ovsdb  node ip
+        sffBuilder.setIpMgmtAddress(sffLocator.getIp());
+
+        sffDataPlaneLocator.add(sffDplBuilder.build());
+        //set SFF key
+        sffBuilder.setKey(new ServiceFunctionForwarderKey(sffBuilder.getName()));
+        sffBuilder.setSffDataPlaneLocator(sffDataPlaneLocator);
+
+        return sffBuilder;
     }
 
-    /**
-     * Method adds the PortPairGroup which is identified by InstanceIdentifier
-     * to device.
-     *
-     * @param path - the whole path to new PortPairGroup
-     * @param newPortPairGroup        - new PortPairGroup
-     */
-    @Override
-    public void add(InstanceIdentifier<PortPairGroup> path, PortPairGroup newPortPairGroup) {
+    public static void buildServiceFunctionDictonary(ServiceFunctionForwarderBuilder sffBuilder,
+                                                                           ServiceFunction sf) {
+        List<ServiceFunctionDictionary> sfdList = new ArrayList<>();
+        ServiceFunctionDictionaryBuilder sfdBuilder = new ServiceFunctionDictionaryBuilder();
+
+        //Build Sff-sf-data-plane-locator
+        SffSfDataPlaneLocatorBuilder sffSfDplBuilder = new SffSfDataPlaneLocatorBuilder();
+        sffSfDplBuilder.setSfDplName(sf.getSfDataPlaneLocator().get(0).getName());
+        sffSfDplBuilder.setSffDplName(sffBuilder.getSffDataPlaneLocator().get(0).getName());
+        sfdBuilder.setSffSfDataPlaneLocator(sffSfDplBuilder.build());
+
+        sfdBuilder.setName(sf.getName());
+        sfdBuilder.setKey(new ServiceFunctionDictionaryKey(sfdBuilder.getName()));
+
+        //NOTE: fail mode is set to Open by default
+        sfdBuilder.setFailmode(Open.class);
+
+        //TODO: set interface name list
+
+        for (Iterator<ServiceFunctionDictionary> sfdItr = sffBuilder.getServiceFunctionDictionary().iterator();sfdItr
+                .hasNext();) {
+            ServiceFunctionDictionary sfd = sfdItr.next();
+            if (sfd.getName().equals(sfdBuilder.getName())) {
+                LOG.info("Existing SF dictionary {} found in SFF {}, removing the SF dictionary", sfd.getName(),
+                        sffBuilder.getName());
+                sfdItr.remove();
+                break;
+            }
+        }
+        sfdList.add(sfdBuilder.build());
+
+        if (sffBuilder.getServiceFunctionDictionary() != null) {
+            sffBuilder.getServiceFunctionDictionary().addAll(sfdList);
+        } else {
+            sffBuilder.setServiceFunctionDictionary(sfdList);
+        }
+        LOG.info("Final Service Function Dictionary {}", sffBuilder.getServiceFunctionDictionary());
+    }
 
+    private static SffOvsLocatorOptionsAugmentationBuilder buildOvsOptions() {
+        SffOvsLocatorOptionsAugmentationBuilder ovsOptions = new SffOvsLocatorOptionsAugmentationBuilder();
+        OvsOptionsBuilder ovsOptionsBuilder = new OvsOptionsBuilder();
+        ovsOptionsBuilder.setRemoteIp(OPT_FLOW_STR);
+        ovsOptionsBuilder.setDstPort(OPT_DST_PORT);
+        ovsOptionsBuilder.setKey(OPT_FLOW_STR);
+        ovsOptionsBuilder.setNsp(OPT_FLOW_STR);
+        ovsOptionsBuilder.setNsi(OPT_FLOW_STR);
+        ovsOptionsBuilder.setNshc1(OPT_FLOW_STR);
+        ovsOptionsBuilder.setNshc2(OPT_FLOW_STR);
+        ovsOptionsBuilder.setNshc3(OPT_FLOW_STR);
+        ovsOptionsBuilder.setNshc4(OPT_FLOW_STR);
+        ovsOptions.setOvsOptions(ovsOptionsBuilder.build());
+        return ovsOptions;
     }
 }
index dbb48f01460143dd6bf74f6d58cfdb372af7c25a..e16ca14372a4a08c757cd3ab2b4f602a4c4888cb 100644 (file)
@@ -7,13 +7,10 @@
  */
 package org.opendaylight.netvirt.openstack.sfc.translator.portchain;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableBiMap;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.netvirt.openstack.sfc.translator.INeutronSfcDataProcessor;
-import org.opendaylight.netvirt.openstack.sfc.translator.NeutronMdsalHelper;
 import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbMdsalHelper;
 import org.opendaylight.netvirt.openstack.sfc.translator.OvsdbPortMetadata;
-import org.opendaylight.netvirt.openstack.sfc.translator.SfcMdsalHelper;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfDataPlaneLocatorName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
@@ -22,9 +19,9 @@ import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev1
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocator;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocatorBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocatorKey;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.SlTransportType;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.VxlanGpe;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.IpBuilder;
@@ -37,8 +34,8 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.AllowedAddressPairs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.port.pair.attributes.ServiceFunctionParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pair.groups.PortPairGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.sfc.rev160511.sfc.attributes.port.pairs.PortPair;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,7 +47,7 @@ import java.util.concurrent.atomic.AtomicInteger;
  * Class will convert OpenStack Port Pair API yang models present in
  * neutron northbound project to OpenDaylight SFC Service Function yang models.
  */
-public class PortPairTranslator implements INeutronSfcDataProcessor<PortPair> {
+public class PortPairTranslator {
     private static final Logger LOG = LoggerFactory.getLogger(PortPairTranslator.class);
     private static final String NSH_AWARE_PARAM = "nsh-aware";
     private static final String SF_TYPE_PARAM = "type";
@@ -67,65 +64,15 @@ public class PortPairTranslator implements INeutronSfcDataProcessor<PortPair> {
     private static final AtomicInteger counter = new AtomicInteger(0);
     private static final String SFF_NAME_PARAM = "sff-name";
 
-    private final DataBroker db;
-    private NeutronPortPairListener neutronPortPairListener;
-    private final SfcMdsalHelper sfcMdsalHelper;
-    private final NeutronMdsalHelper neutronMdsalHelper;
-    private final OvsdbMdsalHelper ovsdbMdsalHelper;
-
-    public PortPairTranslator(DataBroker db) {
-        this.db = db;
-        sfcMdsalHelper = new SfcMdsalHelper(db);
-        neutronMdsalHelper = new NeutronMdsalHelper(db);
-        ovsdbMdsalHelper = new OvsdbMdsalHelper(db);
-    }
-
-    public void start() {
-        LOG.info("Port Pair Translator Initialized.");
-        if(neutronPortPairListener == null) {
-            neutronPortPairListener = new NeutronPortPairListener(db, this);
-        }
-    }
-
-    /**
-     * Method removes PortPair which is identified by InstanceIdentifier.
-     *
-     * @param path - the whole path to PortPair
-     * @param deletedPortPair        - PortPair for removing
-     */
-    @Override
-    public void remove(InstanceIdentifier<PortPair> path, PortPair deletedPortPair) {
-        sfcMdsalHelper.removeServiceFunction(getSFKey(deletedPortPair));
-    }
-
-    /**
-     * Method updates the original PortPair to the update PortPair.
-     * Both are identified by same InstanceIdentifier.
-     *
-     * @param path - the whole path to PortPair
-     * @param originalPortPair   - original PortPair (for update)
-     * @param updatePortPair     - changed PortPair (contain updates)
-     */
-    @Override
-    public void update(InstanceIdentifier<PortPair> path, PortPair originalPortPair, PortPair updatePortPair) {
-        ServiceFunction sf = buildServiceFunction(updatePortPair);
-        sfcMdsalHelper.updateServiceFunction(sf);
-    }
-
-    /**
-     * Method adds the PortPair which is identified by InstanceIdentifier
-     * to device.
-     *
-     * @param path - the whole path to new PortPair
-     * @param newPortPair        - new PortPair
-     */
-    @Override
-    public void add(InstanceIdentifier<PortPair> path, PortPair newPortPair) {
-        ServiceFunction sf = buildServiceFunction(newPortPair);
-        sfcMdsalHelper.addServiceFunction(sf);
-    }
-
-    private ServiceFunction buildServiceFunction(PortPair portPair) {
+    public static ServiceFunctionBuilder buildServiceFunction(
+            PortPair portPair,
+            PortPairGroup portPairGroup,
+            Port neutronPort,
+            OvsdbPortMetadata ovsdbPortMetadata,
+            ServiceFunctionForwarder sff) {
+        Preconditions.checkNotNull(portPair, "Port pair must not be null");
+        Preconditions.checkNotNull(portPairGroup, "Port pair group must not be null");
+        Preconditions.checkNotNull(neutronPort, "Neutron Port related to port pair must not be null");
         LOG.info("Port pair received : {}", portPair);
 
         ServiceFunctionBuilder serviceFunctionBuilder = new ServiceFunctionBuilder();
@@ -134,29 +81,28 @@ public class PortPairTranslator implements INeutronSfcDataProcessor<PortPair> {
         IpBuilder sfLocator = new IpBuilder();
 
         List<ServiceFunctionParameters> sfParams = portPair.getServiceFunctionParameters();
-
+        //Set SF name, key and tenant-id
         serviceFunctionBuilder.setName(new SfName(portPair.getName()));
         serviceFunctionBuilder.setKey(new ServiceFunctionKey(serviceFunctionBuilder.getName()));
-
         serviceFunctionBuilder.setTenantId(new TenantId(portPair.getTenantId().getValue()));
-        //By default set it to true
+
+        //Set SF Type. Setting it to PortPairGroup Type, this will be overridden if user pass
+        //it through service_function_params
+        serviceFunctionBuilder.setType(SftTypeName.getDefaultInstance(portPairGroup.getName()));
+
+        //Set NSH Aware to true, later it will be overridden if user specified otherwise
+        //in service_function_parameters
         serviceFunctionBuilder.setNshAware(true);
 
-        //Set data path locator
+        //Set data path locator name and key
         sfDataPlaneLocatorBuilder.setName(new SfDataPlaneLocatorName(portPair.getName() + DPL_SUFFIX_PARAM));
         sfDataPlaneLocatorBuilder.setKey(new SfDataPlaneLocatorKey(sfDataPlaneLocatorBuilder.getName()));
 
         //Set vxlan-gpe as a default transport type, unless user pass specific transport in
-        //service_function_params
+        //service_function_parameters
         sfDataPlaneLocatorBuilder.setTransport(VxlanGpe.class);
 
         //Set locator type
-        Port neutronPort = neutronMdsalHelper.getNeutronPort(portPair.getIngress());
-        if (neutronPort == null) {
-            //Try to get the neutron port for egress node. Currently assuming that
-            //ingress port and egress port will be same.
-            neutronPort = neutronMdsalHelper.getNeutronPort(portPair.getEgress());
-        }
         if (neutronPort != null) {
             List<AllowedAddressPairs> attachedIpAddresses = neutronPort.getAllowedAddressPairs();
             //Pick up the first ip address
@@ -176,25 +122,24 @@ public class PortPairTranslator implements INeutronSfcDataProcessor<PortPair> {
             LOG.warn("Neutron port mapped to Port pair ingress/egress port is not found : {}", portPair);
         }
 
-        //Set OVS_Port
-        //This call is very costly call, as it reads ovsdb:1 topology from the operational data store.
-        // Need to think of caching to optimize it further.
-        OvsdbPortMetadata ovsdbPortMetadata = ovsdbMdsalHelper.getOvsdbPortMetadata(portPair.getIngress());
         if (ovsdbPortMetadata.getOvsdbPort() != null ) {
-            String ovsdbPortName = ovsdbMdsalHelper.getOvsdbPortName(ovsdbPortMetadata.getOvsdbPort());
+            String ovsdbPortName = OvsdbMdsalHelper.getOvsdbPortName(ovsdbPortMetadata.getOvsdbPort());
             SfDplOvsAugmentationBuilder sfDplOvsAugmentationBuilder = new SfDplOvsAugmentationBuilder();
             OvsPortBuilder ovsPortBuilder = new OvsPortBuilder();
             ovsPortBuilder.setPortId(ovsdbPortName);
             sfDplOvsAugmentationBuilder.setOvsPort(ovsPortBuilder.build());
             sfDataPlaneLocatorBuilder.addAugmentation(SfDplOvsAugmentation.class, sfDplOvsAugmentationBuilder.build());
+        } else {
+            LOG.warn("No OVSDB Port found for the port pair {}. Lack of ovs-port information might not configure SF " +
+                    "properly", portPair);
         }
 
-        //But if user pass specific param using service_function_parameters, set it accordingly
+        //But if user pass specific param using service_function_parameters, set/override it accordingly
         for(ServiceFunctionParameters sfParam : sfParams) {
             if (sfParam.getServiceFunctionParameter().equals(NSH_AWARE_PARAM)) {
                 serviceFunctionBuilder.setNshAware(new Boolean(sfParam.getServiceFunctionParameterValue()));
             }
-            //There is not default type set, user MUST pass it through service_function_parameters
+            //There is by default type set to port pair group name, override it if user pass it specific type
             if (sfParam.getServiceFunctionParameter().equals(SF_TYPE_PARAM)) {
                 serviceFunctionBuilder.setType(new SftTypeName(sfParam.getServiceFunctionParameterValue()));
             }
@@ -219,8 +164,7 @@ public class PortPairTranslator implements INeutronSfcDataProcessor<PortPair> {
         //Set service_function_forwarder
         if (sfDataPlaneLocatorBuilder.getServiceFunctionForwarder() == null
                 && ovsdbPortMetadata.getOvsdbNode() != null) {
-            String ipAddress = ovsdbMdsalHelper.getNodeIpAddress(ovsdbPortMetadata.getOvsdbNode());
-            SffName sffName = sfcMdsalHelper.getExistingSFF(ipAddress);
+            SffName sffName = sff.getName();
             if(sffName != null ) {
                 sfDataPlaneLocatorBuilder.setServiceFunctionForwarder(sffName);
             } else {
@@ -237,11 +181,10 @@ public class PortPairTranslator implements INeutronSfcDataProcessor<PortPair> {
         //Set all data plane locator
         serviceFunctionBuilder.setSfDataPlaneLocator(sfDataPlaneLocatorList);
         LOG.info("Port Pair translated to Service Function: {}", serviceFunctionBuilder);
-        return serviceFunctionBuilder.build();
+        return serviceFunctionBuilder;
     }
 
-    private ServiceFunctionKey getSFKey(PortPair portPair) {
+    public static ServiceFunctionKey getSFKey(PortPair portPair) {
         return new ServiceFunctionKey(new SfName(portPair.getName()));
     }
-
 }
index 267e5147fd68fdc9fd312ba150123bc29c47bc39..abfde8529e6dd7bbc2de084ed4235d914fd82e7f 100644 (file)
@@ -12,6 +12,9 @@
 
   <reference id="dataBroker"
     interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" />
+  <reference id="rspService"
+             interface="org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePathService"
+             availability="optional"/>
 
   <odl:clustered-app-config id="openstackSfcTranslatorConfig"
     binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.openstack.sfc.translator.config.rev160720.OpenstackSfcTranslatorConfig">
@@ -21,6 +24,7 @@
     class="org.opendaylight.netvirt.openstack.sfc.translator.OpenStackSFCTranslatorProvider"
     init-method="start" destroy-method="close">
     <argument ref="dataBroker" />
+    <argument ref="rspService" />
     <argument ref="openstackSfcTranslatorConfig" />
     <argument ref="blueprintBundleContext" />
   </bean>
index 2d1d6a45e583dd82e7c57079c1b7755cf8c7c1b0..97b37f6910887a8912b6580b70f899957eca7322 100644 (file)
@@ -52,6 +52,8 @@ public final class AclConstants {
     public static final int TRACKED_NEW_CT_STATE_MASK = 0x21;
     public static final int TRACKED_INV_CT_STATE_MASK = 0x30;
 
+    public static final String IPV4_ALL_NETWORK = "0.0.0.0/0";
+
     private AclConstants() {
     }
 }
index 957ab0f8529ec03d3d8d22020532589af9bba4cb..9e8b4a6f49be97d49d70d73b9031f35c024a4b16 100644 (file)
@@ -260,7 +260,7 @@ public class AclServiceOFFlowBuilder {
             flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
                 new long[] { NwConstants.ETHTYPE_IPV4 }));
             Ipv4Prefix srcNetwork = ((AceIpv4)acl.getAceIpVersion()).getSourceIpv4Network();
-            if (null != srcNetwork) {
+            if (null != srcNetwork && !srcNetwork.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
                 String[] ipaddressValues = srcNetwork.getValue().split("/");
                 flowMatches.add(new MatchInfo(MatchFieldType.ipv4_source,
                     new String[] {ipaddressValues[0], ipaddressValues[1]}));
@@ -287,7 +287,7 @@ public class AclServiceOFFlowBuilder {
             flowMatches.add(new MatchInfo(MatchFieldType.eth_type,
                 new long[] { NwConstants.ETHTYPE_IPV4 }));
             Ipv4Prefix dstNetwork = ((AceIpv4)acl.getAceIpVersion()).getDestinationIpv4Network();
-            if (null != dstNetwork) {
+            if (null != dstNetwork && !dstNetwork.getValue().equals(AclConstants.IPV4_ALL_NETWORK)) {
                 String[] ipaddressValues = dstNetwork.getValue().split("/");
                 flowMatches.add(new MatchInfo(MatchFieldType.ipv4_destination,
                     new String[] {ipaddressValues[0], ipaddressValues[1]}));
diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/config/default-config.xml b/vpnservice/dhcpservice/dhcpservice-impl/src/main/config/default-config.xml
deleted file mode 100644 (file)
index 905338d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
-Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
-
-This program and the accompanying materials are made available under the
-terms of the Eclipse Public License v1.0 which accompanies this distribution,
-and is available at http://www.eclipse.org/legal/epl-v10.html
--->
-<snapshot>
-  <required-capabilities>
-      <capability>urn:opendaylight:params:xml:ns:yang:dhcpservice:impl?module=dhcpservice-impl&amp;revision=2015-07-10</capability>
-      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
-      <capability>urn:opendaylight:genius:mdsalutil?module=odl-mdsalutil&amp;revision=2016-04-06</capability>
-      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service?module=opendaylight-entity-ownership-service&amp;revision=2015-08-10</capability>
-      <capability>urn:opendaylight:genius:interfacemanager?module=odl-interface&amp;revision=2016-04-06</capability>
-  </required-capabilities>
-  <configuration>
-
-    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-        <module>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:dhcpservice:impl">prefix:dhcpservice-impl</type>
-          <name>dhcpservice-default</name>
-          <controller-dhcp-enabled>true</controller-dhcp-enabled>
-          <broker>
-            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
-            <name>binding-osgi-broker</name>
-          </broker>
-          <rpcregistry>
-            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
-            <name>binding-rpc-broker</name>
-          </rpcregistry>
-          <notification-service>
-             <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
-             <name>binding-notification-broker</name>
-          </notification-service>
-          <mdsalutil>
-            <type xmlns:mdsalutil="urn:opendaylight:genius:mdsalutil">mdsalutil:odl-mdsalutil</type>
-            <name>mdsalutil-service</name>
-          </mdsalutil>
-          <entity-ownership-service>
-            <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
-            <name>entity-ownership-service</name>
-          </entity-ownership-service>
-          <odlinterface>
-            <type xmlns:odlif="urn:opendaylight:genius:interfacemanager">odlif:odl-interface</type>
-            <name>interfacemgr-service</name>
-          </odlinterface>
-        </module>
-      </modules>
-    </data>
-  </configuration>
-</snapshot>
index 367c21ad56e64c6382744f92bedd2956f2a1a920..5e88af2c892a3825a04a62b26a4240fe0d95470c 100644 (file)
@@ -13,8 +13,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DhcpConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dhcp.config.Configs;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -26,39 +26,27 @@ public class DhcpConfigListener extends AsyncClusteredDataChangeListenerBase<Dhc
 
     private static final Logger LOG = LoggerFactory.getLogger(DhcpConfigListener.class);
 
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private DhcpManager dhcpManager;
+    private final DhcpManager dhcpManager;
+    private final DataBroker dataBroker;
 
     public DhcpConfigListener(final DataBroker db, final DhcpManager dhcpMgr) {
         super(DhcpConfig.class, DhcpConfigListener.class);
         dhcpManager = dhcpMgr;
-        registerListener(db);
+        this.dataBroker = db;
     }
 
-    private void registerListener(final DataBroker db) {
-        try {
-            listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
-                    getWildCardPath(), DhcpConfigListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
-        } catch (final Exception e) {
-            LOG.error("NodeListener: DataChange listener registration fail!", e);
-            throw new IllegalStateException("NodeListener: registration Listener failed.", e);
-        }
+    public void init() {
+        registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
     }
 
+    @Override
     protected InstanceIdentifier<DhcpConfig> getWildCardPath() {
         return InstanceIdentifier.create(DhcpConfig.class);
     }
 
     @Override
     public void close() throws Exception {
-        if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                LOG.error("Error when cleaning up DhcpConfigListener.", e);
-            }
-            listenerRegistration = null;
-        }
+        super.close();
         LOG.debug("DhcpConfig Listener Closed");
     }
 
index 8aab262cb3767dc996654422063ccc3fecb88603..51fc9cb33dbf710d2e8ef133251526d68d02a91d 100644 (file)
@@ -9,12 +9,12 @@ package org.opendaylight.netvirt.dhcpservice;
 
 import java.math.BigInteger;
 import java.util.List;
-
 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.DesignatedSwitchesForExternalTunnels;
@@ -27,9 +27,9 @@ import org.slf4j.LoggerFactory;
 public class DhcpDesignatedDpnListener extends AsyncClusteredDataChangeListenerBase<DesignatedSwitchForTunnel, DhcpDesignatedDpnListener> implements AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(DhcpDesignatedDpnListener.class);
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
-    private DataBroker broker;
+
+    private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
+    private final DataBroker broker;
 
     public DhcpDesignatedDpnListener(final DhcpExternalTunnelManager dhcpExternalTunnelManager, final DataBroker broker) {
         super(DesignatedSwitchForTunnel.class, DhcpDesignatedDpnListener.class);
@@ -37,16 +37,13 @@ public class DhcpDesignatedDpnListener extends AsyncClusteredDataChangeListenerB
         this.broker = broker;
     }
 
+    public void init() {
+        registerListener(LogicalDatastoreType.CONFIGURATION, broker);
+    }
+
     @Override
     public void close() throws Exception {
-        if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                LOG.error("Error when cleaning up DhcpDesignatedDpnListener.", e);
-            }
-            listenerRegistration = null;
-        }
+        super.close();
         LOG.debug("DhcpDesignatedDpnListener Listener Closed");
     }
 
index 64a5b3e0a4a31b4fc1e9f9bf403b287b6dc7602a..c31b54a4ea3950739339d2f20feb8e138a1ddad8 100644 (file)
@@ -7,6 +7,10 @@
  */
 package org.opendaylight.netvirt.dhcpservice;
 
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -18,7 +22,6 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
-
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -71,30 +74,32 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-
 public class DhcpExternalTunnelManager {
 
     private static final Logger logger = LoggerFactory.getLogger(DhcpExternalTunnelManager.class);
     public static final String UNKNOWN_DMAC = "00:00:00:00:00:00";
+
     private final DataBroker broker;
-    private IMdsalApiManager mdsalUtil;
+    private final IMdsalApiManager mdsalUtil;
+    private final ItmRpcService itmRpcService;
+    private final EntityOwnershipService entityOwnershipService;
 
     private ConcurrentMap<BigInteger, Set<Pair<IpAddress, String>>> designatedDpnsToTunnelIpElanNameCache = new ConcurrentHashMap<>();
     private ConcurrentMap<Pair<IpAddress, String>, Set<String>> tunnelIpElanNameToVmMacCache = new ConcurrentHashMap<>();
     private ConcurrentMap<Pair<IpAddress, String>, Set<String>> availableVMCache = new ConcurrentHashMap<>();
     private ConcurrentMap<Pair<BigInteger, String>, Port> vniMacAddressToPortCache = new ConcurrentHashMap<>();
-    private ItmRpcService itmRpcService;
-    private EntityOwnershipService entityOwnershipService;
 
-    public DhcpExternalTunnelManager(DataBroker broker, IMdsalApiManager mdsalUtil, ItmRpcService itmRpcService, EntityOwnershipService entityOwnershipService) {
+
+    public DhcpExternalTunnelManager(final DataBroker broker,
+            final IMdsalApiManager mdsalUtil, final ItmRpcService itmRpcService,
+            final EntityOwnershipService entityOwnershipService) {
         this.broker = broker;
         this.mdsalUtil = mdsalUtil;
         this.itmRpcService = itmRpcService;
         this.entityOwnershipService = entityOwnershipService;
+    }
+
+    public void init() {
         initilizeCaches();
     }
 
index 110082ebb522fc725d0f8fb71d8a758d0ab367c9..60f70b58d91ee078e0f18aab4e5cd20532942d60 100644 (file)
@@ -26,14 +26,19 @@ import org.slf4j.LoggerFactory;
 public class DhcpInterfaceConfigListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
 
     private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceConfigListener.class);
+
     private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private DataBroker dataBroker;
-    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
+    private final DataBroker dataBroker;
+    private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
 
     public DhcpInterfaceConfigListener(DataBroker dataBroker, DhcpExternalTunnelManager dhcpExternalTunnelManager) {
         super(Interface.class);
         this.dataBroker = dataBroker;
         this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+    }
+
+    public void init() {
         registerListener();
     }
 
@@ -54,15 +59,11 @@ public class DhcpInterfaceConfigListener extends AbstractDataChangeListener<Inte
     @Override
     public void close() throws Exception {
         if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                logger.error("Error when cleaning up DataChangeListener.", e);
-            }
-            listenerRegistration = null;
+            listenerRegistration.close();
         }
         logger.info("DhcpInterfaceConfigListener Closed");
     }
+
     @Override
     protected void remove(InstanceIdentifier<Interface> identifier, Interface del) {
         IfTunnel tunnelInterface = del.getAugmentation(IfTunnel.class);
index 62896fb2d2d86a16abe7f158c2d5d6f391db7ae9..f454ef2d5e21a65c15845f694daae218b28169f4 100644 (file)
@@ -7,9 +7,10 @@
  */
 package org.opendaylight.netvirt.dhcpservice;
 
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
 import java.math.BigInteger;
 import java.util.List;
-
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
@@ -37,15 +38,16 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-
 public class DhcpInterfaceEventListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
 
     private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceEventListener.class);
-    private DhcpManager dhcpManager;
+
     private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private DataBroker dataBroker;
+
+    private final DataBroker dataBroker;
+    private final DhcpManager dhcpManager;
+    private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
     private static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
         @Override
         public void onSuccess(Void result) {
@@ -57,7 +59,6 @@ public class DhcpInterfaceEventListener extends AbstractDataChangeListener<Inter
             logger.error("Error in Datastore write operation", error);
         }
     };
-    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
 
     public DhcpInterfaceEventListener(DhcpManager dhcpManager, DataBroker dataBroker, DhcpExternalTunnelManager dhcpExternalTunnelManager) {
         super(Interface.class);
@@ -84,12 +85,7 @@ public class DhcpInterfaceEventListener extends AbstractDataChangeListener<Inter
     @Override
     public void close() throws Exception {
         if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                logger.error("Error when cleaning up DataChangeListener.", e);
-            }
-            listenerRegistration = null;
+            listenerRegistration.close();
         }
         logger.info("Interface Manager Closed");
     }
index 8907f505f1073c6a8dbdf74ec72bf35b04d6b887..93818af81ed2154366c85b29a51a4b0d7d1b5e5c 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.netvirt.dhcpservice;
 import java.math.BigInteger;
 import java.util.List;
 import java.util.concurrent.ConcurrentMap;
-
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
@@ -40,14 +39,19 @@ import com.google.common.base.Optional;
 public class DhcpLogicalSwitchListener extends AbstractDataChangeListener<LogicalSwitches> implements AutoCloseable {
 
     private static final Logger logger = LoggerFactory.getLogger(DhcpLogicalSwitchListener.class);
-    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
     private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private DataBroker dataBroker;
+
+    private final DataBroker dataBroker;
+    private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
 
     public DhcpLogicalSwitchListener(DhcpExternalTunnelManager dhcpManager, DataBroker dataBroker) {
         super(LogicalSwitches.class);
         this.dhcpExternalTunnelManager = dhcpManager;
         this.dataBroker = dataBroker;
+    }
+
+    public void init() {
         registerListener();
     }
 
@@ -71,12 +75,7 @@ public class DhcpLogicalSwitchListener extends AbstractDataChangeListener<Logica
     @Override
     public void close() throws Exception {
         if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                logger.error("Error when cleaning up DataChangeListener.", e);
-            }
-            listenerRegistration = null;
+            listenerRegistration.close();
         }
         logger.info("DhcpLogicalSwitchListener Closed");
     }
index 79b2855b49cf72e624259c54c24d76b17b119217..c019792a888ac8f4ae760e612575728e7eae8155 100644 (file)
@@ -9,12 +9,13 @@ package org.opendaylight.netvirt.dhcpservice;
 
 import java.math.BigInteger;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
-
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.ActionType;
+import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.InstructionType;
@@ -38,41 +39,54 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.ser
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.config.rev150710.DhcpserviceConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class DhcpManager implements AutoCloseable {
+public class DhcpManager {
 
     private static final Logger logger = LoggerFactory.getLogger(DhcpManager.class);
+    private final IMdsalApiManager mdsalUtil;
+    private final INeutronVpnManager neutronVpnService;
+    private final DhcpserviceConfig config;
     private final DataBroker broker;
-    IMdsalApiManager mdsalUtil;
+    private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
 
     private int dhcpOptLeaseTime = 0;
-    private int dhcpOptRenewalTime = 0;
-    private int dhcpOptRebindingTime = 0;
     private String dhcpOptDefDomainName;
-    private INeutronVpnManager neutronVpnService;
+    private DhcpInterfaceEventListener dhcpInterfaceEventListener;
+    private DhcpInterfaceConfigListener dhcpInterfaceConfigListener;
+
+    // cache used to maintain DpnId and physical address for each interface.
+    private static HashMap<String, ImmutablePair<BigInteger, String>> interfaceToDpnIdMacAddress = new HashMap<>();
+
+    public DhcpManager(final IMdsalApiManager mdsalApiManager,
+            final INeutronVpnManager neutronVpnManager,
+            DhcpserviceConfig config, final DataBroker dataBroker,
+            final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+        this.mdsalUtil = mdsalApiManager;
+        this.neutronVpnService = neutronVpnManager;
+        this.config = config;
+        this.broker = dataBroker;
+        this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
 
-    /**
-    * @param db - dataBroker reference
-    */
-    public DhcpManager(final DataBroker db) {
-        broker = db;
         configureLeaseDuration(DHCPMConstants.DEFAULT_LEASE_TIME);
     }
 
-    public void setMdsalManager(IMdsalApiManager mdsalManager) {
-        this.mdsalUtil = mdsalManager;
-    }
-
-    public void setNeutronVpnService(INeutronVpnManager neutronVpnService) {
-        logger.debug("Setting NeutronVpn dependency");
-        this.neutronVpnService = neutronVpnService;
+    public void init() {
+        if (config.isControllerDhcpEnabled()) {
+            dhcpInterfaceEventListener = new DhcpInterfaceEventListener(this, broker, dhcpExternalTunnelManager);
+            dhcpInterfaceConfigListener = new DhcpInterfaceConfigListener(broker, dhcpExternalTunnelManager);
+        }
     }
 
-    @Override
     public void close() throws Exception {
-        logger.info("DHCP Manager Closed");
+        if (dhcpInterfaceEventListener != null) {
+            dhcpInterfaceEventListener.close();
+        }
+        if (dhcpInterfaceConfigListener != null) {
+            dhcpInterfaceConfigListener.close();
+        }
     }
 
     public int setLeaseDuration(int leaseDuration) {
@@ -103,13 +117,6 @@ public class DhcpManager implements AutoCloseable {
 
     private void configureLeaseDuration(int leaseTime) {
         this.dhcpOptLeaseTime = leaseTime;
-        if(leaseTime > 0) {
-            this.dhcpOptRenewalTime = this.dhcpOptLeaseTime/2;
-            this.dhcpOptRebindingTime = (this.dhcpOptLeaseTime*7)/8;
-        } else {
-            this.dhcpOptRenewalTime = -1;
-            this.dhcpOptRebindingTime = -1;
-        }
     }
 
     public Subnet getNeutronSubnet(Port nPort) {
index 6e830e6cf9e1baba746f48776bd546530bf43592..332c98c5f3a64cdcd93004a3cb2482727b80d405 100644 (file)
@@ -9,12 +9,12 @@ package org.opendaylight.netvirt.dhcpservice;
 
 import java.math.BigInteger;
 import java.util.List;
-
 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -31,9 +31,8 @@ public class DhcpNeutronPortListener extends AsyncClusteredDataChangeListenerBas
 
     private static final Logger LOG = LoggerFactory.getLogger(DhcpNeutronPortListener.class);
 
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
-    private DataBroker broker;
+    private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
+    private final DataBroker broker;
 
     public DhcpNeutronPortListener(final DataBroker db, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
         super(Port.class, DhcpNeutronPortListener.class);
@@ -41,6 +40,10 @@ public class DhcpNeutronPortListener extends AsyncClusteredDataChangeListenerBas
         this.broker = db;
     }
 
+    public void init() {
+        registerListener(LogicalDatastoreType.CONFIGURATION, broker);
+    }
+
     @Override
     protected InstanceIdentifier<Port> getWildCardPath() {
         return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
@@ -48,14 +51,7 @@ public class DhcpNeutronPortListener extends AsyncClusteredDataChangeListenerBas
 
     @Override
     public void close() throws Exception {
-        if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                LOG.error("Error when cleaning up DhcpNeutronPortListener.", e);
-            }
-            listenerRegistration = null;
-        }
+        super.close();
         LOG.debug("DhcpNeutronPortListener Listener Closed");
     }
 
index b77f21cbf549f50b4eab62df3a6c6a211a89a2d4..a010357ad7a40b0df4c475ed8e60d21a30ceddc2 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.netvirt.dhcpservice;
 
+import com.google.common.base.Optional;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.math.BigInteger;
@@ -17,7 +18,6 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
-
 import org.apache.commons.net.util.SubnetUtils;
 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
 import org.opendaylight.controller.liblldp.EtherTypes;
@@ -59,21 +59,31 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
+public class DhcpPktHandler implements PacketProcessingListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(DhcpPktHandler.class);
+
     private final DataBroker dataBroker;
     private final DhcpManager dhcpMgr;
-    private OdlInterfaceRpcService interfaceManagerRpc;
+    private final OdlInterfaceRpcService interfaceManagerRpc;
+    private final PacketProcessingService pktService;
+    private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
+    private final IInterfaceManager interfaceManager;
+
     private boolean computeUdpChecksum = true;
-    private PacketProcessingService pktService;
-    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
-    private IInterfaceManager interfaceManager;
 
-    public DhcpPktHandler(final DataBroker broker, final DhcpManager dhcpManager, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+    public DhcpPktHandler(final DataBroker broker,
+                          final DhcpManager dhcpManager,
+                          final DhcpExternalTunnelManager dhcpExternalTunnelManager,
+                          final OdlInterfaceRpcService interfaceManagerRpc,
+                          final PacketProcessingService pktService,
+                          final IInterfaceManager interfaceManager) {
+        this.interfaceManagerRpc = interfaceManagerRpc;
+        this.pktService = pktService;
         this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
         this.dataBroker = broker;
-        dhcpMgr = dhcpManager;
+        this.dhcpMgr = dhcpManager;
+        this.interfaceManager = interfaceManager;
     }
 
     //TODO: Handle this in a separate thread
@@ -526,20 +536,6 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
         return (pktInReason == SendToController.class);
     }
 
-    @Override
-    public void close() throws Exception {
-        // TODO Auto-generated method stub
-    }
-
-    public void setPacketProcessingService(PacketProcessingService packetService) {
-        this.pktService = packetService;
-    }
-
-    public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
-        LOG.trace("Registered interfaceManager successfully");
-        this.interfaceManagerRpc = interfaceManagerRpc;
-    }
-
     private String getInterfaceNameFromTag(long portTag) {
         String interfaceName = null;
         GetInterfaceFromIfIndexInput input = new GetInterfaceFromIfIndexInputBuilder().setIfIndex(new Integer((int)portTag)).build();
@@ -574,8 +570,4 @@ public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
         }
         return actions;
     }
-
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
-        this.interfaceManager = interfaceManager;
-    }
 }
diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpProvider.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/netvirt/dhcpservice/DhcpProvider.java
deleted file mode 100644 (file)
index 7496b31..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netvirt.dhcpservice;
-
-import io.netty.util.concurrent.GlobalEventExecutor;
-import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DhcpProvider implements BindingAwareProvider, AutoCloseable {
-
-    private static final Logger LOG = LoggerFactory.getLogger(DhcpProvider.class);
-    private IMdsalApiManager mdsalManager;
-    private DhcpPktHandler dhcpPktHandler;
-    private Registration packetListener = null;
-    private NotificationProviderService notificationService;
-    private DhcpManager dhcpManager;
-    private NodeListener dhcpNodeListener;
-    private INeutronVpnManager neutronVpnManager;
-    private DhcpConfigListener dhcpConfigListener;
-    private OdlInterfaceRpcService interfaceManagerRpc;
-    private DhcpInterfaceEventListener dhcpInterfaceEventListener;
-    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
-    private DhcpNeutronPortListener dhcpNeutronPortListener;
-    private DhcpLogicalSwitchListener dhcpLogicalSwitchListener;
-    private DhcpUCastMacListener dhcpUCastMacListener;
-    private ItmRpcService itmRpcService;
-    private DhcpInterfaceConfigListener dhcpInterfaceConfigListener;
-    private EntityOwnershipService entityOwnershipService;
-    private DhcpDesignatedDpnListener dhcpDesignatedDpnListener;
-    private boolean controllerDhcpEnabled = true;
-    private DhcpSubnetListener dhcpSubnetListener;
-    private DhcpHwvtepListener dhcpHwvtepListener;
-    private IInterfaceManager interfaceManager;
-
-    @Override
-    public void onSessionInitiated(ProviderContext session) {
-        LOG.info("DhcpProvider Session Initiated");
-        try {
-            final DataBroker dataBroker = session.getSALService(DataBroker.class);
-            final PacketProcessingService pktProcessingService = session.getRpcService(PacketProcessingService.class);
-            dhcpManager = new DhcpManager(dataBroker);
-            dhcpManager.setMdsalManager(mdsalManager);
-            dhcpExternalTunnelManager = new DhcpExternalTunnelManager(dataBroker, mdsalManager, itmRpcService, entityOwnershipService);
-            dhcpPktHandler = new DhcpPktHandler(dataBroker, dhcpManager, dhcpExternalTunnelManager);
-            dhcpPktHandler.setPacketProcessingService(pktProcessingService);
-            dhcpPktHandler.setInterfaceManagerRpc(interfaceManagerRpc);
-            dhcpPktHandler.setInterfaceManager(interfaceManager);
-            packetListener = notificationService.registerNotificationListener(dhcpPktHandler);
-            dhcpNodeListener = new NodeListener(dataBroker, dhcpManager, dhcpExternalTunnelManager);
-            dhcpConfigListener = new DhcpConfigListener(dataBroker, dhcpManager);
-            dhcpLogicalSwitchListener = new DhcpLogicalSwitchListener(dhcpExternalTunnelManager, dataBroker);
-            dhcpUCastMacListener = new DhcpUCastMacListener(dhcpManager,dhcpExternalTunnelManager, dataBroker);
-            dhcpUCastMacListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
-            dhcpNeutronPortListener = new DhcpNeutronPortListener(dataBroker, dhcpExternalTunnelManager);
-            dhcpNeutronPortListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
-            dhcpDesignatedDpnListener = new DhcpDesignatedDpnListener(dhcpExternalTunnelManager, dataBroker);
-            dhcpDesignatedDpnListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
-            if (controllerDhcpEnabled) {
-                dhcpInterfaceEventListener = new DhcpInterfaceEventListener(dhcpManager, dataBroker, dhcpExternalTunnelManager);
-                dhcpInterfaceConfigListener = new DhcpInterfaceConfigListener(dataBroker, dhcpExternalTunnelManager);
-            }
-            dhcpSubnetListener = new DhcpSubnetListener(dhcpManager,dhcpExternalTunnelManager,dataBroker);
-            dhcpSubnetListener.registerListener(LogicalDatastoreType.CONFIGURATION,dataBroker);
-            dhcpHwvtepListener = new DhcpHwvtepListener(dataBroker, dhcpExternalTunnelManager);
-        } catch (Exception e) {
-            LOG.error("Error initializing services {}", e);
-        }
-
-        // TODO: Remove as part of blueprint fix.
-        // This is simply here to get the INeutronVPNManager service which is already
-        // moved to blueprint.
-        GlobalEventExecutor.INSTANCE.execute(new Runnable() {
-            @Override
-            public void run() {
-                Bundle b = FrameworkUtil.getBundle(DhcpProvider.class);
-                if (b == null) {
-                    return;
-                }
-                BundleContext bundleContext = b.getBundleContext();
-                if (bundleContext == null) {
-                    return;
-                }
-                final WaitingServiceTracker<INeutronVpnManager> tracker = WaitingServiceTracker.create(
-                        INeutronVpnManager.class, bundleContext);
-                INeutronVpnManager neutronVpnManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
-                LOG.info("DhcpProvider initialized. INeutronVpnManager={}", neutronVpnManager);
-                dhcpManager.setNeutronVpnService(neutronVpnManager);
-            }
-        });
-    }
-
-    public void setMdsalManager(IMdsalApiManager mdsalManager) {
-        this.mdsalManager = mdsalManager;
-    }
-
-    public void setNeutronVpnManager(INeutronVpnManager neutronVpnManager) {
-        this.neutronVpnManager = neutronVpnManager;
-    }
-
-    @Override
-    public void close() throws Exception {
-        if(packetListener != null) {
-            packetListener.close();
-        }
-        if(dhcpPktHandler != null) {
-            dhcpPktHandler.close();
-        }
-        if(dhcpNodeListener != null) {
-            dhcpNodeListener.close();
-        }
-        LOG.info("DhcpProvider closed");
-    }
-
-    public void setNotificationProviderService(NotificationProviderService notificationServiceDependency) {
-        this.notificationService = notificationServiceDependency;
-    }
-
-    public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
-        this.interfaceManagerRpc = interfaceManagerRpc;
-    }
-
-    public void setItmRpcService(ItmRpcService itmRpcService) {
-        this.itmRpcService = itmRpcService;
-    }
-
-    public void setEntityOwnershipService(EntityOwnershipService entityOwnershipService) {
-        this.entityOwnershipService = entityOwnershipService;
-    }
-
-    public void setControllerDhcpEnabled(boolean controllerDhcpEnabled) {
-        this.controllerDhcpEnabled = controllerDhcpEnabled;
-    }
-
-    public void setInterfaceManager(IInterfaceManager interfaceManager) {
-        this.interfaceManager = interfaceManager;
-    }
-}
index 10df69dbe2ccec707e03320f465cf516d883af76..d4dc80f01fb96ec9cc956cd6d6f362b7b6f695ef 100644 (file)
@@ -7,21 +7,19 @@
  */
 package org.opendaylight.netvirt.dhcpservice;
 
-import java.math.BigInteger;
-
 import com.google.common.base.Optional;
+import java.math.BigInteger;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
-import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
-import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
@@ -32,20 +30,17 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-
 public class DhcpUCastMacListener extends AsyncClusteredDataChangeListenerBase<LocalUcastMacs, DhcpUCastMacListener> implements AutoCloseable {
 
     private static final Logger logger = LoggerFactory.getLogger(DhcpUCastMacListener.class);
-    private DataBroker broker;
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
+    private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
     private DhcpManager dhcpManager;
+    private final DataBroker broker;
 
     public DhcpUCastMacListener(DhcpManager dhcpManager,DhcpExternalTunnelManager dhcpExtTunnelMgr, DataBroker dataBroker) {
         super(LocalUcastMacs.class, DhcpUCastMacListener.class);
@@ -54,6 +49,10 @@ public class DhcpUCastMacListener extends AsyncClusteredDataChangeListenerBase<L
         this.dhcpManager = dhcpManager;
     }
 
+    public void init() {
+        registerListener(LogicalDatastoreType.OPERATIONAL, broker);
+    }
+
     @Override
     protected InstanceIdentifier<LocalUcastMacs> getWildCardPath() {
         return InstanceIdentifier.create(NetworkTopology.class).child(Topology.class).child(Node.class)
@@ -62,14 +61,7 @@ public class DhcpUCastMacListener extends AsyncClusteredDataChangeListenerBase<L
 
     @Override
     public void close() throws Exception {
-        if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                logger.error("Error when cleaning up DataChangeListener.", e);
-            }
-            listenerRegistration = null;
-        }
+        super.close();
         logger.info("DhcpUCastMacListener Closed");
     }
 
index c9b17f7a1d3ad7b0c78353e0673086c8131bf8cb..ff40e92395426218e4ee72a6f8ea61d0bb876f2e 100644 (file)
@@ -9,14 +9,13 @@ package org.opendaylight.netvirt.dhcpservice;
 
 import java.math.BigInteger;
 import java.util.List;
-
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
@@ -30,16 +29,21 @@ public class NodeListener extends AbstractDataChangeListener<Node> implements Au
     private static final Logger LOG = LoggerFactory.getLogger(NodeListener.class);
 
     private ListenerRegistration<DataChangeListener> listenerRegistration;
+
     private final DataBroker broker;
-    private DhcpManager dhcpManager;
-    private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+    private final DhcpManager dhcpManager;
+    private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
 
-    public NodeListener(final DataBroker db, final DhcpManager dhcpMgr, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+    public NodeListener(final DataBroker db, final DhcpManager dhcpMgr,
+            final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
         super(Node.class);
-        broker = db;
-        dhcpManager = dhcpMgr;
+        this.broker = db;
+        this.dhcpManager = dhcpMgr;
         this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
-        registerListener(db);
+    }
+
+    public void init() {
+        registerListener(broker);
     }
 
     private void registerListener(final DataBroker db) {
@@ -87,13 +91,7 @@ public class NodeListener extends AbstractDataChangeListener<Node> implements Au
     @Override
     public void close() throws Exception {
         if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            } catch (final Exception e) {
-                LOG.error("Error when cleaning up NodeListener.", e);
-            }
-            listenerRegistration = null;
-            //ToDo: Should we delete DHCP flows when we are closed?
+            listenerRegistration.close();
         }
         LOG.debug("Node Listener Closed");
     }
diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModule.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModule.java
deleted file mode 100644 (file)
index 773e66c..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710;
-
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.netvirt.dhcpservice.DhcpProvider;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
-
-public class DhcpServiceImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710.AbstractDhcpServiceImplModule {
-    public DhcpServiceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-        super(identifier, dependencyResolver);
-    }
-
-    public DhcpServiceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710.DhcpServiceImplModule oldModule, java.lang.AutoCloseable oldInstance) {
-        super(identifier, dependencyResolver, oldModule, oldInstance);
-    }
-
-    @Override
-    public void customValidation() {
-        // add custom validation form module attributes here.
-    }
-
-    @Override
-    public java.lang.AutoCloseable createInstance() {
-        RpcProviderRegistry rpcregistryDependency = getRpcregistryDependency();
-        DhcpProvider dhcpProvider = new DhcpProvider();
-        dhcpProvider.setControllerDhcpEnabled(getControllerDhcpEnabled());
-        dhcpProvider.setNotificationProviderService(getNotificationServiceDependency());
-        dhcpProvider.setMdsalManager(getMdsalutilDependency());
-        //dhcpProvider.setNeutronVpnManager(getNeutronvpnDependency());
-        dhcpProvider.setInterfaceManagerRpc(rpcregistryDependency.getRpcService(OdlInterfaceRpcService.class));
-        dhcpProvider.setItmRpcService(rpcregistryDependency.getRpcService(ItmRpcService.class));
-        dhcpProvider.setEntityOwnershipService(getEntityOwnershipServiceDependency());
-        dhcpProvider.setInterfaceManager(getOdlinterfaceDependency());
-        getBrokerDependency().registerProvider(dhcpProvider);
-        return dhcpProvider;
-    }
-
-}
diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModuleFactory.java b/vpnservice/dhcpservice/dhcpservice-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/dhcpservice/impl/rev150710/DhcpServiceImplModuleFactory.java
deleted file mode 100644 (file)
index 09562b0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
-* Generated file
-*
-* Generated from: yang module name: dhcpservice-impl yang module local name: dhcpservice-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Sat Jul 11 21:38:25 IST 2015
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710;
-public class DhcpServiceImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710.AbstractDhcpServiceImplModuleFactory {
-
-}
diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/resources/org/opendaylight/blueprint/dhcpservice-impl.xml b/vpnservice/dhcpservice/dhcpservice-impl/src/main/resources/org/opendaylight/blueprint/dhcpservice-impl.xml
new file mode 100644 (file)
index 0000000..5bb30bc
--- /dev/null
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+  xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+  odl:use-default-for-reference-types="true">
+
+  <reference id="dataBroker"
+    interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
+    odl:type="default" />
+  <reference id="rpcRegistry"
+    interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry" />
+  <reference id="entityOwnershipService"
+    interface="org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService" />
+  <reference id="mdsalUtils"
+    interface="org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager" />
+  <reference id="neutronVpnMapper"
+    interface="org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager" />
+  <reference id="interfaceManager"
+    interface="org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager" />
+
+  <odl:rpc-service id="odlInterfaceRpcService"
+    interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService" />
+  <odl:rpc-service id="itmRpcService"
+    interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService" />
+  <odl:rpc-service id="packetProcessingService"
+    interface="org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService" />
+
+  <odl:clustered-app-config id="dhcpServiceConfig"
+    binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.config.rev150710.DhcpserviceConfig">
+  </odl:clustered-app-config>
+
+  <bean id="dhcpManager" class="org.opendaylight.netvirt.dhcpservice.DhcpManager"
+    init-method="init" destroy-method="close">
+    <argument ref="mdsalUtils" />
+    <argument ref="neutronVpnMapper" />
+    <argument ref="dhcpServiceConfig" />
+    <argument ref="dataBroker" />
+    <argument ref="dhcpExternalTunnelManager" />
+  </bean>
+
+  <bean id="dhcpExternalTunnelManager" class="org.opendaylight.netvirt.dhcpservice.DhcpExternalTunnelManager"
+    init-method="init">
+    <argument ref="dataBroker" />
+    <argument ref="mdsalUtils" />
+    <argument ref="itmRpcService" />
+    <argument ref="entityOwnershipService" />
+  </bean>
+
+  <bean id="dhcpPktHandler" class="org.opendaylight.netvirt.dhcpservice.DhcpPktHandler">
+    <argument ref="dataBroker" />
+    <argument ref="dhcpManager" />
+    <argument ref="dhcpExternalTunnelManager" />
+    <argument ref="odlInterfaceRpcService" />
+    <argument ref="packetProcessingService" />
+    <argument ref="interfaceManager" />
+  </bean>
+  <odl:notification-listener ref="dhcpPktHandler" />
+
+  <bean id="nodeListener" class="org.opendaylight.netvirt.dhcpservice.NodeListener"
+    init-method="init" destroy-method="close">
+    <argument ref="dataBroker" />
+    <argument ref="dhcpManager" />
+    <argument ref="dhcpExternalTunnelManager" />
+  </bean>
+
+  <bean id="dhcpConfigListener" class="org.opendaylight.netvirt.dhcpservice.DhcpConfigListener"
+    init-method="init" destroy-method="close">
+    <argument ref="dataBroker" />
+    <argument ref="dhcpManager" />
+  </bean>
+
+  <bean id="dhcpLogicalSwitchListener" class="org.opendaylight.netvirt.dhcpservice.DhcpLogicalSwitchListener"
+    init-method="init" destroy-method="close">
+    <argument ref="dhcpExternalTunnelManager" />
+    <argument ref="dataBroker" />
+  </bean>
+
+  <bean id="dhcpUCastMacListener" class="org.opendaylight.netvirt.dhcpservice.DhcpUCastMacListener"
+    init-method="init" destroy-method="close">
+    <argument ref="dhcpManager" />
+    <argument ref="dhcpExternalTunnelManager" />
+    <argument ref="dataBroker" />
+  </bean>
+
+  <bean id="dhcpNeutronPortListener" class="org.opendaylight.netvirt.dhcpservice.DhcpNeutronPortListener"
+    init-method="init" destroy-method="close">
+    <argument ref="dataBroker" />
+    <argument ref="dhcpExternalTunnelManager" />
+  </bean>
+
+  <bean id="dhcpDesignatedDpnListener" class="org.opendaylight.netvirt.dhcpservice.DhcpDesignatedDpnListener"
+    init-method="init" destroy-method="close">
+    <argument ref="dhcpExternalTunnelManager" />
+    <argument ref="dataBroker" />
+  </bean>
+</blueprint>
\ No newline at end of file
diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/yang/dhcpservice-config.yang b/vpnservice/dhcpservice/dhcpservice-impl/src/main/yang/dhcpservice-config.yang
new file mode 100644 (file)
index 0000000..a87135e
--- /dev/null
@@ -0,0 +1,21 @@
+module dhcpservice-config {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:dhcpservice:config";
+    prefix "dhcpservice-config";
+
+    description
+        "Service definition for dhcpservice project";
+
+    revision "2015-07-10" {
+        description
+                "Initial revision";
+    }
+
+    container dhcpservice-config {
+        leaf controller-dhcp-enabled {
+            description "Enable the dhcpservice on the controller";
+            type boolean;
+            default true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/vpnservice/dhcpservice/dhcpservice-impl/src/main/yang/dhcpservice-impl.yang b/vpnservice/dhcpservice/dhcpservice-impl/src/main/yang/dhcpservice-impl.yang
deleted file mode 100644 (file)
index aa4d2eb..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-module dhcpservice-impl {
-    yang-version 1;
-    namespace "urn:opendaylight:params:xml:ns:yang:dhcpservice:impl";
-    prefix "dhcpservice-impl";
-
-    import config { prefix config; revision-date 2013-04-05; }
-    import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
-    import odl-mdsalutil { prefix odl-mdsal; revision-date 2016-04-06;}
-    //import neutronvpn-api { prefix nvpn; revision-date 2015-08-12;}
-    import opendaylight-entity-ownership-service { prefix eos; revision-date 2015-08-10;}
-    import odl-interface {prefix odlif; revision-date 2016-04-06;}
-
-    description
-        "Service definition for dhcpservice project";
-
-    revision "2015-07-10" {
-        description
-            "Initial revision";
-    }
-
-    identity dhcpservice-impl {
-        base config:module-type;
-        config:java-name-prefix DhcpServiceImpl;
-    }
-
-    augment "/config:modules/config:module/config:configuration" {
-        case dhcpservice-impl {
-            when "/config:modules/config:module/config:type = 'dhcpservice-impl'";
-            container broker {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
-                    }
-                }
-            }
-            container rpcregistry {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity md-sal-binding:binding-rpc-registry;
-                    }
-                }
-            }
-            container notification-service {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity md-sal-binding:binding-notification-service;
-                    }
-                }
-            }
-
-            container mdsalutil {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity odl-mdsal:odl-mdsalutil;
-                    }
-                }
-            }
-
-            /*container neutronvpn {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity nvpn:neutronvpn-api;
-                    }
-                }
-            }*/
-
-            container entity-ownership-service {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity eos:entity-ownership-service;
-                    }
-                }
-            }
-
-            container odlinterface {
-                uses config:service-ref {
-                    refine type {
-                        mandatory true;
-                        config:required-identity odlif:odl-interface;
-                    }
-                }
-            }
-
-            leaf controller-dhcp-enabled {
-                description "Enable the dhcpservice on the controller";
-                type boolean;
-            }
-        }
-    }
-}
index 4be832fd4cfb29893a66b860f57cafd6dc91a9d8..8c2a650be3f307fbbacd6ca300d17702725bde0e 100644 (file)
@@ -256,13 +256,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <artifactId>dhcpservice-impl</artifactId>
       <version>${vpnservices.version}</version>
     </dependency>
-    <dependency>
-      <groupId>${project.groupId}</groupId>
-      <artifactId>dhcpservice-impl</artifactId>
-      <version>${vpnservices.version}</version>
-      <classifier>config</classifier>
-      <type>xml</type>
-    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>dhcpservice-api</artifactId>
index 0996c3daf633a6670ff12f2b43dd006b52b65872..a2416fb5da09bfa4176f09df985548dfc50e2be2 100644 (file)
@@ -78,7 +78,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <!--<bundle>wrap:mvn:javax.servlet/servlet-api/2.5</bundle>-->
     <configfile finalname="${configfile.directory}/bgpmanager-impl-default-config.xml">mvn:org.opendaylight.netvirt/bgpmanager-impl/{{VERSION}}/xml/config</configfile>
     <configfile finalname="${configfile.directory}/vpnmanager-impl-default-config.xml">mvn:org.opendaylight.netvirt/vpnmanager-impl/{{VERSION}}/xml/config</configfile>
-    <configfile finalname="${configfile.directory}/dhcpservice-impl-default-config.xml">mvn:org.opendaylight.netvirt/dhcpservice-impl/{{VERSION}}/xml/config</configfile>
     <configfile finalname="${configfile.directory}/elanmanager-impl-default-config.xml">mvn:org.opendaylight.netvirt/elanmanager-impl/{{VERSION}}/xml/config</configfile>
     <configfile finalname="${configfile.directory}/natservice-impl-default-config.xml">mvn:org.opendaylight.netvirt/natservice-impl/{{VERSION}}/xml/config</configfile>
     <!--<configfile finalname="${configfile.directory}/cloud-servicechain-impl-default-config.xml">mvn:org.opendaylight.netvirt/cloud-servicechain-impl/{{VERSION}}/xml/config</configfile>-->
index d140ea02f66593b73c2327621c2577324f0af8a4..ddb02d013c5adaee7568d959ea720d043fd42010 100644 (file)
@@ -28,6 +28,8 @@ import org.junit.runner.RunWith;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
+import org.opendaylight.netvirt.it.NetvirtITConstants.DefaultFlow;
+import org.opendaylight.netvirt.utils.netvirt.it.utils.FlowITUtil;
 import org.opendaylight.netvirt.utils.netvirt.it.utils.NetITUtil;
 import org.opendaylight.netvirt.vpnmanager.VpnserviceProvider;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
@@ -66,6 +68,7 @@ public class NetvirtIT extends AbstractMdsalTestBase {
     private static OvsdbItUtils itUtils;
     private static MdsalUtils mdsalUtils = null;
     private static SouthboundUtils southboundUtils;
+    private static FlowITUtil flowITUtil;
     private static String addressStr;
     private static String portStr;
     private static String connectionType;
@@ -175,8 +178,7 @@ public class NetvirtIT extends AbstractMdsalTestBase {
         assertNotNull("mdsalUtils should not be null", mdsalUtils);
         southboundUtils = new SouthboundUtils(mdsalUtils);
         assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, this.getNetvirtTopology());
-
-//      TODO: need to implement new pipelineOrchestrator for the vpnservice pipeline
+        flowITUtil = new FlowITUtil(dataBroker);
 
         setup.set(true);
     }
@@ -219,6 +221,17 @@ public class NetvirtIT extends AbstractMdsalTestBase {
         return found;
     }
 
+    private void validateDefaultFlows(long datapathId, int timeout){
+        LOG.info("Validating default flows");
+        for (DefaultFlow defaultFlow : DefaultFlow.values()){
+            try {
+                flowITUtil.verifyFlowByFields(datapathId, defaultFlow.getFlowId(), defaultFlow.getTableId(), timeout);
+            } catch (Exception e){
+                LOG.error("Failed to verify flow id : {}", defaultFlow.getFlowId());
+                fail();
+            }
+        }
+    }
 
     /**
      * Test for basic southbound events to netvirt.
@@ -239,6 +252,9 @@ public class NetvirtIT extends AbstractMdsalTestBase {
             NodeInfo nodeInfo = itUtils.createNodeInfo(connectionInfo, null);
             nodeInfo.connect();
 
+            //validate default flows
+            validateDefaultFlows(nodeInfo.datapathId, 60*1000);
+
             LOG.info("testNetVirt: should be connected: {}", nodeInfo.ovsdbNode.getNodeId());
 
             southboundUtils.addTerminationPoint(nodeInfo.bridgeNode, NetvirtITConstants.PORT_NAME,
@@ -271,8 +287,8 @@ public class NetvirtIT extends AbstractMdsalTestBase {
             NodeInfo nodeInfo = itUtils.createNodeInfo(connectionInfo, null);
             nodeInfo.connect();
 
-            // waiting for the default flows to be installed before adding the ports
-            Thread.sleep(20*100);
+            //validate default flows
+            validateDefaultFlows(nodeInfo.datapathId, 60*1000);
 
             //create the neutron objects
             NetITUtil net = new NetITUtil(ovs, southboundUtils, mdsalUtils);
@@ -280,8 +296,6 @@ public class NetvirtIT extends AbstractMdsalTestBase {
             String port1 = net.createPort(nodeInfo.bridgeNode);
             String port2 = net.createPort(nodeInfo.bridgeNode);
 
-//          TODO - need to add pipeline validation
-
             Thread.sleep(1000);
 
             //ovs interface configuration for running the ping test
index 8a941589f341702c79a79b016be9d9d295e5daf3..6cba47b9554ca8b2f44c6c6cd89b1a727c1524ab 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.netvirt.it;
 
+import org.opendaylight.genius.mdsalutil.NwConstants;
+
 /**
  * Constants for NetvirtIT
  */
@@ -34,4 +36,29 @@ public final class NetvirtITConstants {
     public static final String PORT_NAME = "porttest";
     public static final String INTEGRATION_BRIDGE_NAME = "br-int";
     public static final String OPENFLOW_CONNECTION_PROTOCOL = "tcp";
+
+
+    public enum DefaultFlow {
+
+        DHCP("DHCPTableMissFlow", NwConstants.DHCP_TABLE),
+        IPV6("IPv6TableMissFlow", NwConstants.IPV6_TABLE),
+        ELAN_SMAC(""+NwConstants.ELAN_SMAC_TABLE, NwConstants.ELAN_SMAC_TABLE),
+        ELAN_DMAC(""+NwConstants.ELAN_DMAC_TABLE, NwConstants.ELAN_DMAC_TABLE);
+
+        String flowId;
+        short tableId;
+
+        DefaultFlow(String flowId, short tableId){
+            this.flowId = flowId;
+            this.tableId = tableId;
+        }
+
+        public String getFlowId() {
+            return flowId;
+        }
+
+        public short getTableId() {
+            return tableId;
+        }
+    }
 }
index acb92c98e3102e1a74573dec3ddb5ad21c951571..0f4b939ad5193422ef3494d69b0d2e9e736443eb 100644 (file)
@@ -63,6 +63,7 @@ import java.util.List;
  */
 public class FloatingIPListener extends AbstractDataChangeListener<IpMapping> implements AutoCloseable{
     private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
+    private static final long FIXED_DELAY_IN_MILLISECONDS = 4000;
     private ListenerRegistration<DataChangeListener> listenerRegistration;
     private final DataBroker broker;
     private OdlInterfaceRpcService interfaceManager;
@@ -308,7 +309,7 @@ public class FloatingIPListener extends AbstractDataChangeListener<IpMapping> im
         }
 
         actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
-        instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
+        instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfo));
 
         String flowRef = NatUtil.getFlowRef(dpId, NwConstants.SNAT_TABLE, vpnId, internalIp);
 
@@ -338,23 +339,25 @@ public class FloatingIPListener extends AbstractDataChangeListener<IpMapping> im
             return 0;
         }
 
-        List<ActionInfo> actionList = NatUtil.getEgressActionsForInterface(interfaceManager, extInterface, null);
-        if (actionList == null || actionList.isEmpty()) {
-            LOG.warn("No actions found for interface {} vpn id {}", extInterface, vpnId);
+        List<ActionInfo> egressActionList = NatUtil.getEgressActionsForInterface(interfaceManager, extInterface, null);
+        if (egressActionList == null || egressActionList.isEmpty()) {
+            LOG.warn("No Egress actions found for interface {} vpn id {}", extInterface, vpnId);
             return 0;
         }
 
-        if(!Strings.isNullOrEmpty(macAddress)) {
-            actionList.add(new ActionInfo(ActionType.set_field_eth_dest, new String[]{ macAddress }));
+        List<ActionInfo> actionList = new ArrayList<>();
+        if (!Strings.isNullOrEmpty(macAddress)) {
+            actionList.add(new ActionInfo(ActionType.set_field_eth_dest, new String[] { macAddress }));
         }
 
+        actionList.addAll(egressActionList);
         List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
         listBucketInfo.add(new BucketInfo(actionList));
         long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerId), idManager);
         GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpId, groupId, routerId, GroupTypes.GroupIndirect,
                 listBucketInfo);
         LOG.trace("Install ext-net Group: id {} gw mac address {} vpn id {}", groupId, macAddress, vpnId);
-        mdsalManager.installGroup(groupEntity);
+        mdsalManager.syncInstallGroup(groupEntity, FIXED_DELAY_IN_MILLISECONDS);
         return groupId;
     }
 
index 6bbfdcf1df28bdf02e5d214952a784e5054080d9..d594078ad3a892f0f86f2448b5b90a756feb5704 100644 (file)
@@ -88,7 +88,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
     @Override
     public void onAddFloatingIp(final BigInteger dpnId, final String routerId,
                                 Uuid networkId, final String interfaceName, final String externalIp, final String internalIp) {
-        final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+        final String vpnName = getAssociatedVPN(networkId, routerId);
         if(vpnName == null) {
             LOG.info("No VPN associated with ext nw {} to handle add floating ip configuration {} in router {}",
                     networkId, externalIp, routerId);
@@ -159,7 +159,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
     @Override
     public void onRemoveFloatingIp(final BigInteger dpnId, String routerId, Uuid networkId, final String externalIp,
                                    String internalIp, final long label) {
-        final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+        final String vpnName = getAssociatedVPN(networkId, routerId);
         if(vpnName == null) {
             LOG.info("No VPN associated with ext nw {} to handle remove floating ip configuration {} in router {}",
                     networkId, externalIp, routerId);
@@ -222,7 +222,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp + "/32").setServiceId(label).build();
         Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
 
-        ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), 
+        ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future),
             new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
 
             @Override
@@ -337,4 +337,8 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         LOG.debug("LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
     }
 
-}
\ No newline at end of file
+    private String getAssociatedVPN(Uuid networkId, String routerId) {
+        String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+        return vpnName != null ? vpnName : routerId;
+    }
+}
index 55c60c37c99fe26bdefadb9a4f2efad18db34d73..8ad7b44d71927517ff60ef28ae7b085ffff3e145 100644 (file)
@@ -29,6 +29,9 @@ public final class NeutronSecurityRuleConstants {
 
     public static final Class ETHERTYPE_IPV4 = EthertypeV4.class;
 
+    public static final String IPV4_ALL_NETWORK = "0.0.0.0/0";
+    public static final String IPV6_ALL_NETWORK = "::/0";
+
     // default acp type
     public static final Class<? extends AclBase> ACLTYPE = Ipv4Acl.class;
 
index ed2005a6bbf78178c9feed1108faefaa6493e95e..e9ceaaedd3a4b94741b8d76e2a5db210dfba1d35 100644 (file)
@@ -52,7 +52,8 @@ public class NeutronSecurityRuleListener
         extends AsyncDataTreeChangeListenerBase<SecurityRule, NeutronSecurityRuleListener> {
     private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleListener.class);
     private final DataBroker dataBroker;
-    private static final ImmutableBiMap<Class<? extends DirectionBase>, Class<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase>> DIRECTION_MAP = ImmutableBiMap.of(
+    private static final ImmutableBiMap<Class<? extends DirectionBase>, Class<? extends org.opendaylight.yang.gen.
+            v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase>> DIRECTION_MAP = ImmutableBiMap.of(
             DirectionEgress.class, NeutronSecurityRuleConstants.DIRECTION_EGRESS,
             DirectionIngress.class, NeutronSecurityRuleConstants.DIRECTION_INGRESS);
     private static final ImmutableBiMap<Class<? extends ProtocolBase>, Short> PROTOCOL_MAP = ImmutableBiMap.of(
@@ -129,12 +130,7 @@ public class NeutronSecurityRuleListener
                 aceIpBuilder.setDestinationPortRange(destinationPortRangeBuilder.build());
             }
         }
-        if (securityRule.getEthertype() != null) {
-            aceIpBuilder = handleEtherType(securityRule, aceIpBuilder);
-        }
-        if (securityRule.getRemoteIpPrefix() != null) {
-            aceIpBuilder = handleRemoteIpPrefix(securityRule, aceIpBuilder, isDirectionIngress);
-        }
+        aceIpBuilder = handleRemoteIpPrefix(securityRule, aceIpBuilder, isDirectionIngress);
         if (securityRule.getRemoteGroupId() != null) {
             securityRuleAttrBuilder.setRemoteGroupId(securityRule.getRemoteGroupId());
         }
@@ -167,33 +163,53 @@ public class NeutronSecurityRuleListener
     private AceIpBuilder handleEtherType(SecurityRule securityRule, AceIpBuilder aceIpBuilder) {
         if (NeutronSecurityRuleConstants.ETHERTYPE_IPV4.equals(securityRule.getEthertype())) {
             AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
+            aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(
+                NeutronSecurityRuleConstants.IPV4_ALL_NETWORK));
+            aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(
+                NeutronSecurityRuleConstants.IPV4_ALL_NETWORK));
             aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
         } else {
             AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
+            aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(
+                NeutronSecurityRuleConstants.IPV6_ALL_NETWORK));
+            aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(
+                NeutronSecurityRuleConstants.IPV6_ALL_NETWORK));
             aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
+
         }
         return aceIpBuilder;
     }
 
-    private AceIpBuilder handleRemoteIpPrefix(SecurityRule securityRule, AceIpBuilder aceIpBuilder, boolean isDirectionIngress) {
-        if (securityRule.getRemoteIpPrefix().getIpv4Prefix() != null) {
-            AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
-            if (isDirectionIngress) {
-                aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(securityRule.getRemoteIpPrefix().getIpv4Prefix().getValue()));
+    private AceIpBuilder handleRemoteIpPrefix(SecurityRule securityRule, AceIpBuilder aceIpBuilder,
+                                              boolean isDirectionIngress) {
+        if (securityRule.getRemoteIpPrefix() != null) {
+            if (securityRule.getRemoteIpPrefix().getIpv4Prefix() != null) {
+                AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
+                if (isDirectionIngress) {
+                    aceIpv4Builder.setSourceIpv4Network(new Ipv4Prefix(securityRule
+                        .getRemoteIpPrefix().getIpv4Prefix().getValue()));
+                } else {
+                    aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(securityRule
+                        .getRemoteIpPrefix().getIpv4Prefix().getValue()));
+                }
+                aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
             } else {
-                aceIpv4Builder.setDestinationIpv4Network(new Ipv4Prefix(securityRule.getRemoteIpPrefix().getIpv4Prefix().getValue()));
+                AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
+                if (isDirectionIngress) {
+                    aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(
+                        securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
+                } else {
+                    aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(
+                        securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
+                }
+                aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
             }
-            aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
         } else {
-            AceIpv6Builder aceIpv6Builder = new AceIpv6Builder();
-            if (isDirectionIngress) {
-                aceIpv6Builder.setSourceIpv6Network(new Ipv6Prefix(securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
-            } else {
-                aceIpv6Builder.setDestinationIpv6Network(new Ipv6Prefix(securityRule.getRemoteIpPrefix().getIpv6Prefix().getValue()));
-
+            if (securityRule.getEthertype() != null) {
+                handleEtherType( securityRule, aceIpBuilder);
             }
-            aceIpBuilder.setAceIpVersion(aceIpv6Builder.build());
         }
+
         return aceIpBuilder;
     }
 
diff --git a/vpnservice/utils/netvirt-it-utils/src/main/java/org/opendaylight/netvirt/utils/netvirt/it/utils/FlowITUtil.java b/vpnservice/utils/netvirt-it-utils/src/main/java/org/opendaylight/netvirt/utils/netvirt/it/utils/FlowITUtil.java
new file mode 100644 (file)
index 0000000..67813d4
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.utils.netvirt.it.utils;
+
+import static org.junit.Assert.assertNotNull;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import org.junit.Assert;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.utils.mdsal.utils.NotifyingDataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifPacketIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifSwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifUpdateFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcAddFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcRemoveFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcUpdateFlowOriginal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcUpdateFlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionListGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.AllMatchesGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNotifPacketIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNotifSwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNotifUpdateFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchRpcAddFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchRpcRemoveFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchRpcUpdateFlowOriginal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchRpcUpdateFlowUpdated;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Flow utils for NetvirtIT
+ */
+public class FlowITUtil {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FlowITUtil.class);
+    private static final String OPENFLOW = "openflow";
+
+    private DataBroker dataBroker;
+
+    public FlowITUtil(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+    }
+
+    private final static Class[] MATCH_AUGMENTATIONS = {GeneralAugMatchNodesNodeTableFlow.class,
+            GeneralAugMatchNotifUpdateFlowStats.class,
+            GeneralAugMatchNotifPacketIn.class,
+            GeneralAugMatchNotifSwitchFlowRemoved.class,
+            GeneralAugMatchRpcAddFlow.class,
+            GeneralAugMatchRpcRemoveFlow.class,
+            GeneralAugMatchRpcUpdateFlowOriginal.class,
+            GeneralAugMatchRpcUpdateFlowUpdated.class};
+
+    private final static Class[] EXT_LIST_AUGMENTATIONS = {NxAugMatchNodesNodeTableFlow.class,
+            NxAugMatchNotifUpdateFlowStats.class,
+            NxAugMatchNotifPacketIn.class,
+            NxAugMatchNotifSwitchFlowRemoved.class,
+            NxAugMatchRpcAddFlow.class,
+            NxAugMatchRpcRemoveFlow.class,
+            NxAugMatchRpcUpdateFlowOriginal.class,
+            NxAugMatchRpcUpdateFlowUpdated.class};
+
+    private static Integer DEFAULT_PRIORITY = new Integer(32768);
+
+    private String getNodeName(long dpidLong) {
+        return OPENFLOW + ":" + dpidLong;
+    }
+
+    private NodeBuilder createNodeBuilder(String nodeId) {
+        NodeBuilder builder = new NodeBuilder();
+        builder.setId(new NodeId(nodeId));
+        builder.setKey(new NodeKey(builder.getId()));
+        return builder;
+    }
+
+    private NodeBuilder createNodeBuilder(long dpidLong) {
+        return createNodeBuilder(getNodeName(dpidLong));
+    }
+
+    private InstanceIdentifier<Flow> createFlowPath(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+        return InstanceIdentifier.builder(Nodes.class)
+                .child(Node.class, nodeBuilder.getKey())
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(flowBuilder.getTableId()))
+                .child(Flow.class, flowBuilder.getKey()).build();
+    }
+
+    private InstanceIdentifier<Table> createTablePath(NodeBuilder nodeBuilder, short table) {
+        return InstanceIdentifier.builder(Nodes.class)
+                .child(Node.class, nodeBuilder.getKey())
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(table)).build();
+    }
+
+    private Flow getFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder,
+                               ReadOnlyTransaction readTx, final LogicalDatastoreType store) {
+        try {
+            Optional<Flow> data = readTx.read(store, createFlowPath(flowBuilder, nodeBuilder)).get();
+            if (data.isPresent()) {
+                return data.get();
+            }
+        } catch (InterruptedException|ExecutionException e) {
+            LOG.error("Failed to get flow {}", flowBuilder.getFlowName(), e);
+        }
+
+        LOG.info("Cannot find data for Flow {} in {}", flowBuilder.getFlowName(), store);
+        return null;
+    }
+
+
+    /**
+     * Sets up common defaults for the given flow builder: a flow identifier and key based on the given flow name,
+     * strict, no barrier, the given table identifier, no hard timeout and no idle timeout.
+     *
+     * @param flowBuilder The flow builder.
+     * @param flowName The flow name.
+     * @param table The table.
+     * @return The flow builder.
+     */
+    private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table) {
+        final FlowId flowId = new FlowId(flowName);
+        flowBuilder
+                .setId(flowId)
+                .setStrict(true)
+                .setBarrier(false)
+                .setTableId(table)
+                .setKey(new FlowKey(flowId))
+                .setFlowName(flowName)
+                .setHardTimeout(0)
+                .setIdleTimeout(0);
+        return flowBuilder;
+    }
+
+    private Table getTable(NodeBuilder nodeBuilder, short table,
+                                 ReadOnlyTransaction readTx, final LogicalDatastoreType store) {
+        try {
+            Optional<Table> data = readTx.read(store, this.createTablePath(nodeBuilder, table)).get();
+            if (data.isPresent()) {
+                return data.get();
+            }
+        } catch (InterruptedException|ExecutionException e) {
+            LOG.error("Failed to get table {}", table, e);
+        }
+
+        LOG.info("Cannot find data for table {} in {}", table, store);
+        return null;
+    }
+
+    /**
+     * Verify <strong>by flow id</strong> that the given flow was installed in a table. This method will wait 10
+     * seconds for the flows to appear in each of the md-sal CONFIGURATION and OPERATIONAL data stores
+     * @param datapathId dpid where flow is installed
+     * @param flowId The "name" of the flow, e.g., "TunnelFloodOut_100"
+     * @param table integer value of table
+     * @throws InterruptedException if interrupted while waiting for flow to appear in mdsal
+     */
+    public void verifyFlowById(long datapathId, String flowId, short table) throws InterruptedException {
+        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
+                this.createNodeBuilder(datapathId);
+        FlowBuilder flowBuilder =
+                this.initFlowBuilder(new FlowBuilder(), flowId, table);
+
+        InstanceIdentifier<Flow> iid = this.createFlowPath(flowBuilder, nodeBuilder);
+
+        NotifyingDataChangeListener waitForIt = new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                iid, null);
+        waitForIt.registerDataChangeListener(dataBroker);
+        waitForIt.waitForCreation(10000);
+
+        Flow flow = this.getFlow(flowBuilder, nodeBuilder,
+                dataBroker.newReadOnlyTransaction(), LogicalDatastoreType.CONFIGURATION);
+        assertNotNull("Could not find flow in config: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
+
+        waitForIt = new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid, null);
+        waitForIt.registerDataChangeListener(dataBroker);
+        waitForIt.waitForCreation(10000);
+
+        flow = this.getFlow(flowBuilder, nodeBuilder,
+                dataBroker.newReadOnlyTransaction(), LogicalDatastoreType.OPERATIONAL);
+        assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(),
+                flow);
+    }
+
+    /**
+     * Verify that a flow in CONFIGURATION exists also in OPERATIONAL. This is done by looking up the flow in
+     * CONFIGURATION by flowId and searching the flow's priority and matches in the OPERATIONAL.
+     * @param datapathId dpid where flow is installed
+     * @param flowId The "name" of the flow, e.g., "TunnelFloodOut_100"
+     * @param tableId integer value of table
+     * @param waitFor Retry every second for waitFor milliseconds
+     * @throws InterruptedException if interrupted while waiting for flow to appear in mdsal
+     */
+    public void verifyFlowByFields(long datapathId, String flowId, short tableId, int waitFor) throws InterruptedException {
+        long start = System.currentTimeMillis();
+        int i = 0;
+        do {
+            try {
+                i++;
+                LOG.warn("DEBUG ODED : VERIFY FLOW {}", i);
+                verifyFlowByFields(datapathId, flowId, tableId);
+                return;
+            } catch (AssertionError e) {
+                if((System.currentTimeMillis() - start) >= waitFor) {
+                    throw e;
+                }
+                Thread.sleep(1000);
+            }
+        } while (true);
+    }
+
+    /**
+     * Verify that a flow in CONFIGURATION exists also in OPERATIONAL. This is done by looking up the flow in
+     * CONFIGURATION by flowId and searching the flow's priority and matches in the OPERATIONAL.
+     * @param datapathId dpid where flow is installed
+     * @param flowId The "name" of the flow, e.g., "TunnelFloodOut_100"
+     * @param tableId integer value of table
+     * @throws InterruptedException if interrupted while waiting for flow to appear in mdsal
+     */
+    public void verifyFlowByFields(long datapathId, String flowId, short tableId) throws InterruptedException {
+        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
+                this.createNodeBuilder(datapathId);
+        FlowBuilder flowBuilder =
+                this.initFlowBuilder(new FlowBuilder(), flowId, tableId);
+
+        InstanceIdentifier<Flow> iid = this.createFlowPath(flowBuilder, nodeBuilder);
+
+        NotifyingDataChangeListener waitForIt = new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+                iid, null);
+        waitForIt.registerDataChangeListener(dataBroker);
+        waitForIt.waitForCreation(10000);
+
+        Flow configFlow = this.getFlow(flowBuilder, nodeBuilder,
+                dataBroker.newReadOnlyTransaction(), LogicalDatastoreType.CONFIGURATION);
+        assertNotNull("Could not read flow " + flowId + " from configuration", configFlow);
+
+        Table table = this.getTable(nodeBuilder, tableId, dataBroker.newReadOnlyTransaction(),
+                LogicalDatastoreType.OPERATIONAL);
+        assertNotNull("Could not read table " + tableId + " from operational", table);
+
+        List<Flow> flows = table.getFlow();
+        Assert.assertNotNull("No flows found for table", flows);
+
+
+        for(Flow opFlow : flows) {
+            if (checkFlowsEqual(configFlow, opFlow)) {
+                return;
+            }
+        }
+        Assert.fail("Could not find matching flow in operational for " + flowId);
+    }
+
+    private boolean isMatchInList(AllMatchesGrouping match, List<AllMatchesGrouping> matchList) {
+        for (AllMatchesGrouping match2 : matchList) {
+            if (areMatchAugmentationsEqual(match, match2)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private boolean checkFlowsEqual(Flow configFlow, Flow opFlow) {
+        Integer configPrio = configFlow.getPriority();
+        Integer opPrio = opFlow.getPriority();
+        if (!Objects.equals(configPrio == null ? DEFAULT_PRIORITY : configPrio,
+                opPrio == null ? DEFAULT_PRIORITY : opPrio)) {
+            return false;
+        }
+        return areMatchesEqual(configFlow.getMatch(), opFlow.getMatch());
+    }
+
+    private boolean areMatchesEqual(Match m1, Match m2) {
+        if (m1 == null && m2 == null) {
+            return true;
+        }
+
+        if (m1 == null || m2 == null) {
+            return false;
+        }
+
+        if (!Objects.equals(m1.getInPort(), m2.getInPort())) { return false; }
+        if (!Objects.equals(m1.getInPhyPort(), m2.getInPhyPort())) { return false; }
+        if (!Objects.equals(m1.getMetadata(), m2.getMetadata())) { return false; }
+        if (!Objects.equals(m1.getTunnel(), m2.getTunnel())) { return false; }
+        if (!Objects.equals(m1.getEthernetMatch(), m2.getEthernetMatch())) { return false; }
+        if (!Objects.equals(m1.getVlanMatch(), m2.getVlanMatch())) { return false; }
+        if (!Objects.equals(m1.getIpMatch(), m2.getIpMatch())) { return false; }
+        if (!Objects.equals(m1.getLayer3Match(), m2.getLayer3Match())) { return false; }
+        if (!Objects.equals(m1.getLayer4Match(), m2.getLayer4Match())) { return false; }
+        if (!Objects.equals(m1.getIcmpv4Match(), m2.getIcmpv4Match())) { return false; }
+        if (!Objects.equals(m1.getIcmpv6Match(), m2.getIcmpv6Match())) { return false; }
+        if (!Objects.equals(m1.getProtocolMatchFields(), m2.getProtocolMatchFields())) { return false; }
+        if (!Objects.equals(m1.getTcpFlagsMatch(), m2.getTcpFlagsMatch())) { return false; }
+
+        MatchAugmentationIterator it = new MatchAugmentationIterator(m1);
+        List<AllMatchesGrouping> side1Matches = Lists.newArrayList();
+        AllMatchesGrouping aug;
+        while (null != (aug = it.next())) {
+            side1Matches.add(aug);
+        }
+
+        it = new MatchAugmentationIterator(m2);
+        while(null != (aug = it.next())) {
+            if (!isMatchInList(aug, side1Matches)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private boolean areMatchAugmentationsEqual(AllMatchesGrouping obj1, AllMatchesGrouping obj2) {
+        if (obj1 == null && obj2 == null) {
+            return true;
+        }
+
+        if (obj1 == null || obj2 == null) {
+            return false;
+        }
+        if (!Objects.equals(obj1.getNxmOfEthSrc(), obj2.getNxmOfEthSrc())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfArpOp(), obj2.getNxmOfArpOp())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfUdpDst(), obj2.getNxmOfUdpDst())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxNshc3(), obj2.getNxmNxNshc3())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxCtZone(), obj2.getNxmNxCtZone())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxArpSha(), obj2.getNxmNxArpSha())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfIcmpType(), obj2.getNxmOfIcmpType())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxNshc1(), obj2.getNxmNxNshc1())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfArpSpa(), obj2.getNxmOfArpSpa())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxTunIpv4Dst(), obj2.getNxmNxTunIpv4Dst())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfTcpSrc(), obj2.getNxmOfTcpSrc())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxNshc4(), obj2.getNxmNxNshc4())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfArpTpa(), obj2.getNxmOfArpTpa())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfTcpDst(), obj2.getNxmOfTcpDst())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxNsi(), obj2.getNxmNxNsi())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxNshc2(), obj2.getNxmNxNshc2())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxArpTha(), obj2.getNxmNxArpTha())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxReg(), obj2.getNxmNxReg())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfIpSrc(), obj2.getNxmOfIpSrc())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfEthType(), obj2.getNxmOfEthType())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfEthDst(), obj2.getNxmOfEthDst())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfUdpSrc(), obj2.getNxmOfUdpSrc())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxCtState(), obj2.getNxmNxCtState())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxTunIpv4Src(), obj2.getNxmNxTunIpv4Src())) { return false; }
+        if (!Objects.equals(obj1.getNxmOfIpDst(), obj2.getNxmOfIpDst())) { return false; }
+        if (!Objects.equals(obj1.getNxmNxNsp(), obj2.getNxmNxNsp())) { return false; }
+
+        return true;
+    }
+
+    class MatchAugmentationIterator {
+
+        Match myMatch;
+
+        public MatchAugmentationIterator(Match match) {
+            this.myMatch = match;
+        }
+
+        private int matchAugmentationIdx = 0;
+        private int extListListIdx = 0;
+        private int extListAugmentationIdx = 0;
+
+        public AllMatchesGrouping next() {
+
+            while (matchAugmentationIdx < MATCH_AUGMENTATIONS.length) {
+                GeneralExtensionListGrouping extensionListGrouping = (GeneralExtensionListGrouping)
+                        myMatch.getAugmentation(MATCH_AUGMENTATIONS[matchAugmentationIdx]);
+
+                if (null != extensionListGrouping) {
+                    List<ExtensionList> extListList = extensionListGrouping.getExtensionList();
+
+                    while (extListListIdx < extListList.size()) {
+
+                        ExtensionList extList = extListList.get(extListListIdx);
+
+                        while(extListAugmentationIdx < EXT_LIST_AUGMENTATIONS.length) {
+                            Augmentation res = extList.getExtension().getAugmentation(
+                                    EXT_LIST_AUGMENTATIONS[extListAugmentationIdx]);
+                            ++extListAugmentationIdx;
+                            if (res != null) {
+                                return (AllMatchesGrouping) res;
+                            }
+                        }
+                        extListAugmentationIdx = 0;
+                        ++extListListIdx;
+                    }
+                    extListListIdx = 0;
+                }
+                ++matchAugmentationIdx;
+
+            }
+
+            return null;
+        }
+
+    }
+
+}