Fix netvirtsfc flows 18/28918/3
authorSam Hague <shague@redhat.com>
Thu, 29 Oct 2015 01:49:16 +0000 (21:49 -0400)
committerSam Hague <shague@redhat.com>
Thu, 29 Oct 2015 02:27:25 +0000 (22:27 -0400)
Change-Id: Ife49b9150dcb99fb3097b0fe175d8e9355bdf527
Signed-off-by: Sam Hague <shague@redhat.com>
13 files changed:
openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/ClassifierService.java
openstack/net-virt-sfc/api/src/main/yang/netvirt-acl.yang
openstack/net-virt-sfc/api/src/main/yang/netvirt-classifier.yang
openstack/net-virt-sfc/impl/pom.xml
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcAclListener.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcClassifierListener.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/INetvirtSfcOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/NetvirtSfcOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/NshUtils.java [new file with mode: 0644]
openstack/net-virt-sfc/it/pom.xml
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcIT.java
southbound/southbound-impl/pom.xml
utils/southbound-utils/src/main/java/org/opendaylight/ovsdb/utils/southbound/utils/SouthboundUtils.java

index 126db01610f634c0e3c93be3623879994811f292..e9ee40045016ddc607b1401ebda15c14553178c9 100644 (file)
@@ -108,6 +108,7 @@ public class ClassifierService extends AbstractServiceInstance implements Classi
                     BigInteger.valueOf(REG_VALUE_FROM_LOCAL)));
             ab.setOrder(1);
             ab.setKey(new ActionKey(1));
+
             actionList.add(ab.build());
 
             ib.setOrder(0);
index 3d1a813e155f39a79751643c8c000736e2441921..31d1e1d867e9b727f259cb1daab7ae3e9269056e 100644 (file)
@@ -14,6 +14,7 @@ module netvirt-sfc-acl {
   //augment "/ietf-acl:access-lists/ietf-acl:access-list/ietf-acl:access-list-entries/ietf-acl:access-list-entry/ietf-acl:matches" {
     augment "/ietf-acl:access-lists/ietf-acl:acl/ietf-acl:access-list-entries/ietf-acl:ace/ietf-acl:matches" {
         description "Neutron network uuid";
+        ext:augment-identifier "neutron-network";
         leaf network-uuid {
             type string;
         }
@@ -22,6 +23,7 @@ module netvirt-sfc-acl {
     // TODO: Add choice for Neutron and add fields there instead of at the root of matches
     augment "/ietf-acl:access-lists/ietf-acl:acl/ietf-acl:access-list-entries/ietf-acl:ace/ietf-acl:actions" {
         description "Redirect traffic to SFC identified by SFC Path ID";
+        ext:augment-identifier "redirect-to-sfc";
         leaf redirect-sfc {
             type string;
         }
index c0aec3a3698c1e7c8b6d242b21ac235c47f18ac5..df4dd39e8d6351807116f2baf8a56bd54702960b 100644 (file)
@@ -32,6 +32,14 @@ module netvirt-sfc-classifier {
                     }
                 }
             }
+            container bridges {
+                list bridge {
+                    key "name";
+                    leaf name {
+                        type string;
+                    }
+                }
+            }
         }
     }
 }
index 80f9a173c98dee73663f28263858bb078b49d53e..690626c9b060fb9350f9e07a8474b08e0f79b320 100644 (file)
@@ -46,6 +46,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <groupId>${project.groupId}</groupId>
       <artifactId>openstack.net-virt-providers</artifactId>
       <version>${project.version}</version>
+    </dependency>
+       <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>southbound-api</artifactId>
+      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
@@ -158,9 +163,9 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
-        <configuration>
+        <!--<configuration>
           <propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
-        </configuration>
+        </configuration>-->
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
index f263c0f5dfd45a559755163592c0297b2f9bab40..b3e50bd6d68131572ed0d55af13e7bbed07e3403 100644 (file)
@@ -105,9 +105,10 @@ public class NetvirtSfcAclListener extends AbstractDataTreeListener<Acl> {
                     final Acl addDataObj) {
         Preconditions.checkNotNull(addDataObj, "Added object can not be null!");
         String aclName = addDataObj.getAclName();
-        LOG.debug("Adding accesslist = {}", identifier);
+        LOG.debug("Adding accesslist iid = {}, dataObj = {}", identifier, addDataObj);
         Classifiers classifiers = dbutils.read(LogicalDatastoreType.CONFIGURATION, getClassifierIid());
         if (classifiers != null) {
+            LOG.debug("add: Classifiers: {}", classifiers);
             for (Classifier classifier : classifiers.getClassifier()) {
                 if (classifier.getAcl().equalsIgnoreCase(aclName)) {
                     if (classifier.getSffs() != null) {
@@ -117,6 +118,8 @@ public class NetvirtSfcAclListener extends AbstractDataTreeListener<Acl> {
                     }
                 }
             }
+        } else {
+            LOG.debug("add: No Classifiers found");
         }
     }
 
index af8c8968f335bd3f5fbc73dce5413efb0c5ad2f5..b3d770f1c636d480ffbb8555b007c745a233757e 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.AclKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.Classifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -107,6 +108,7 @@ public class NetvirtSfcClassifierListener extends AbstractDataTreeListener<Class
                     final Classifier addDataObj) {
         Preconditions.checkNotNull(addDataObj, "Added object can not be null!");
         String aclName = addDataObj.getAcl();
+        LOG.debug("Adding classifier iid = {}, dataObj = {}", identifier, addDataObj);
         // Read the ACL information from data store and make sure it exists.
         Acl acl = dbutils.read(LogicalDatastoreType.CONFIGURATION,getIetfAclIid(aclName));
         if (acl == null) {
@@ -114,12 +116,12 @@ public class NetvirtSfcClassifierListener extends AbstractDataTreeListener<Class
             return;
         }
 
-        if (addDataObj.getSffs() != null) {
-            for (Sff sff : addDataObj.getSffs().getSff()) {
+        if (addDataObj.getBridges() != null) {
+            for (Bridge bridge : addDataObj.getBridges().getBridge()) {
                 // Netvirt classifier binds an ACL with service function forwarder that is identified by SFF name.
                 // SFF validation can be done with SFC Provider APIs, as SFF is configured within SFC project.  
                 // Netvirt SFC provider will validate the SFF using SFC provider APIs.
-                provider.addClassifierRules(sff, acl);
+                provider.addClassifierRules(bridge, acl);
             }
         }
     }
index 43ff43f02175361e8c952bbcd11ff90302bc86d6..270a1d0689872152e67594814afacb466cc1d1af 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13;
 
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.Acl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
 
 /**
@@ -25,6 +26,7 @@ public interface INetvirtSfcOF13Provider {
      * @param acl - Access list includes rules that need to be installed in a SFF.
      */
     public void addClassifierRules(Sff sff, Acl acl);
+    public void addClassifierRules(Bridge bridge, Acl acl);
 
     /**
      * Method removes the OF rules corresponding to rules within ACL
index 0fabf9e6899dd21a93e23e1bb3d9a212b7acde6b..acebecbdbc420b3378f282cdebc0a10153f52fe4 100644 (file)
@@ -8,37 +8,59 @@
 
 package org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13;
 
+import com.google.common.util.concurrent.CheckedFuture;
+import java.math.BigInteger;
 import java.util.Iterator;
 import java.util.List;
+import java.util.StringTokenizer;
+
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
+import com.google.common.net.InetAddresses;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
-import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
+import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
 import org.opendaylight.sfc.sfc_ovs.provider.SfcOvsUtil;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
 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.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.rsp.rev140701.RenderedServicePaths;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.path.first.hop.info.RenderedServicePathFirstHop;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathKey;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
 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.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.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.Acl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.Ace;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Actions;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.Matches;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.actions.packet.handling.Deny;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEth;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
 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;
@@ -48,6 +70,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta
 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.InstructionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
@@ -55,13 +80,19 @@ 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.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
+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.classifier.rev150105.classifiers.classifier.bridges.Bridge;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.Sff;
+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.OvsdbTerminationPointAugmentation;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 /**
  * Open vSwitch OpenFlow 1.3 Networking Provider for Netvirt SFC
  * @author Arun Yerra
@@ -69,10 +100,26 @@ import org.slf4j.LoggerFactory;
 public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
     private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcOF13Provider.class);
     private static final int DEFAULT_FLOW_PRIORITY = 32768;
+    private static final short TABLE_0_CLASSIFIER = 0;
+    //private static final short TABLE_1_L2FORWARD = 30;
+    //private static final short TABLE_2_L3FORWARD = 40;
+    private static final short TABLE_3_INGR_ACL = 50;
+    private static final String OPENFLOW = "openflow:";
+
+    public static final long REG_VALUE_FROM_LOCAL = 0x1L;
+    public static final long REG_VALUE_FROM_REMOTE = 0x2L;
+    public static final Class<? extends NxmNxReg> REG_FIELD = NxmNxReg0.class;
     private volatile NodeCacheManager nodeCacheManager;
     private volatile Southbound southbound;
-    private MdsalUtils dbutils;
-    private PipelineOrchestrator orchestrator;
+    private MdsalUtils mdsalUtils;
+    private DataBroker dataBroker;
+
+    // TBD:: Remove these constants after integrating with openstack.
+    //private static final String NETWORK_TYPE_VXLAN = "vxlan";
+    private static final String NETWORK_SEGMENT_ID = "10";
+    private static final String LOCAL_TP_ID = "vethl-h35_2";
+    private static final String INTERFACE_TYPE_VXLAN_GPE = "vxlangpe";
+    private static final String GPE_IFACE_ID = "sw1-vxlangpe-0";
 
     /**
      * {@link NetvirtSfcOF13Provider} constructor.
@@ -80,10 +127,8 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
      */
     public NetvirtSfcOF13Provider(final DataBroker dataBroker) {
         Preconditions.checkNotNull(dataBroker, "Input dataBroker cannot be NULL!");
-
-        //this.dataService = dataBroker;
-        dbutils = new MdsalUtils(dataBroker);
-
+        this.dataBroker = dataBroker;
+        mdsalUtils = new MdsalUtils(dataBroker);
         this.setDependencies(null);
     }
 
@@ -102,62 +147,248 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
 
         // If a service function forwarder exists, then get the corresponding OVS Bridge details and Openflow NodeId.
         // If OVS Bridge augmentation is configured, the following API returns NULL.
-        String datapathId = SfcOvsUtil.getOpenFlowNodeIdForSff(serviceForwarder);
+        String datapathId = null;
+        Node node = null;
+        // TODO: Replace with OVSDB methods and not use the SFC API
+        datapathId = SfcOvsUtil.getOpenFlowNodeIdForSff(serviceForwarder);
         if (datapathId == null) {
-            LOG.debug("Service Function Forwarder = {} is not augemented with "
+            LOG.debug("Service Function Forwarder = {} is not augmented with "
                     + "OVS Bridge Information. Skip processing!!", sff.getName());
         }
         // If openflow Node Id is NULL, get all the bridge nodes using southbound apis and fetch
         // SFF with matching name. From this bridge name, get the openflow data path ID.
-        if (datapathId == null) {
-            Node node = null;
-            final List<Node> nodes = nodeCacheManager.getBridgeNodes();
-            if (nodes.isEmpty()) {
-                LOG.debug("Noop with Classifier Creation on SFF={}. No Bridges configured YET!!", sff.getName());
-            } else {
-                for (Node dstNode : nodes) {
-                    LOG.debug("Processing Node={}, sff={}", dstNode.getNodeId().getValue(), sff.getName());
-                    if (dstNode.getNodeId().getValue().equalsIgnoreCase(sff.getName())) {
-                        LOG.debug("Found matching OVSDB Bridge Name!!= {}", dstNode.getNodeId().getValue());
-                        node = dstNode;
-                        break;
-                    }
-                }
-            }
+
+        node = getBridgeNode(serviceForwarder.getName().toString());
+        if (node == null) {
+            LOG.warn("Node doesn't exist for corresponding SFF={}", sff.getName());
+            return;
         }
 
+        datapathId = getDpid(node);
         LOG.debug("Processing the Classifier rules on Node={}", datapathId);
         if (datapathId != null) {
             // Program the OF flow on the corresponding open flow node.
             Iterator<Ace> itr = acl.getAccessListEntries().getAce().iterator();
             while (itr.hasNext()) {
                 Ace entry = itr.next();
-                programOfRules(entry, datapathId, true);
+                processAclEntry(entry, node, true);
             }
+        } else {
+            LOG.warn("Skipping ACL processing on Node={} as DatapathID is NULL!!", sff.getName());
         }
     }
 
-    private void programOfRules(Ace entry, String datapathId, boolean write) {
-        NodeBuilder nodeBuilder = new NodeBuilder();
-        nodeBuilder.setId(new NodeId(Constants.OPENFLOW_NODE_PREFIX + datapathId));
-        nodeBuilder.setKey(new NodeKey(nodeBuilder.getId()));
+    @Override
+    public void addClassifierRules(Bridge bridge, Acl acl) {
+        Preconditions.checkNotNull(bridge, "Input bridge cannot be NULL!");
+        Preconditions.checkNotNull(acl, "Input accesslist cannot be NULL!");
 
-        //Create the match using match builder, by parsing the Accesslist Entry Match.
-        MatchBuilder matchBuilder = null;
-        matchBuilder = buildMatch(entry.getRuleName(), entry.getMatches(), datapathId);
+        Node bridgeNode = getBridgeNode(bridge.getName());
+        if (bridgeNode == null) {
+            LOG.debug("bridge {} not yet configured. Skip processing !!", bridge.getName());
+            return;
+        }
 
-        InstructionsBuilder isb = null;
-        isb = buildActions(entry.getRuleName(), entry.getActions(), datapathId);
+        // Program the OF flow on the corresponding open flow node.
+        for (Ace ace : acl.getAccessListEntries().getAce()) {
+            processAclEntry(ace, bridgeNode, true);
+        }
+    }
 
-        String flowId = "NETVIRT_SFC_FLOW" + "_" + entry.getRuleName();
+    private void processAclEntry(Ace entry, Node srcNode, boolean write) {
+        RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
+        LOG.debug("Processing ACL entry = {} on Node = {} sfcRedirect = {}", entry.getRuleName(),
+                srcNode.getNodeId(), sfcRedirect);
+        if (sfcRedirect != null) {
+            // Given SFP find the corresponding RSP.
+            String sfcName = sfcRedirect.getRedirectSfc();
+            LOG.debug("Processing Redirect to SFC = {}", sfcRedirect.getRedirectSfc());
+            ServiceFunctionPath sfp = getSfp(sfcName);
+            if (sfp == null || sfp.getName() == null) {
+                LOG.warn("There is no configured SFP with sfcName = {}; so skip installing the ACL entry!!", sfcName);
+                return;
+            }
 
+            LOG.debug("Processing Redirect to SFC = {}, SFP = {}", sfcRedirect.getRedirectSfc(), sfp);
+            // If RSP doesn't exist, create an RSP.
+            String sfpName = sfp.getName().getValue();
+            RenderedServicePath rsp = getRspforSfp(sfpName);
+            String rspName = sfp.getName().getValue() + "_rsp";
+            if (rsp == null) {
+                LOG.info("No configured RSP corresponding to SFP = {}, Creating new RSP = {}!!", sfpName, rspName);
+                // Create RSP.
+                CreateRenderedPathInput rspInput = new CreateRenderedPathInputBuilder()
+                        .setParentServiceFunctionPath(sfpName)
+                        .setName(rspName)
+                        .setSymmetric(sfp.isSymmetric())
+                        .build();
+                rsp = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, rspInput);
+                if (rsp == null) {
+                    LOG.warn("failed to add RSP");
+                    return;
+                }
+
+                // If SFP is symmetric, create RSP in the reverse direction.
+                if (sfp.isSymmetric()) {
+                    LOG.info("SFP = {} is symmetric, installing RSP in the reverse direction!!", sfpName);
+                    String rspNameRev = rspName + "-Reverse";
+                    RenderedServicePath rspReverse = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
+                                                                 this.getRspId(rspNameRev));
+                    if (rspReverse == null) {
+                        rspReverse = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
+                    }
+                }
+            }
+            LOG.info("rsp: {}", rsp);
+
+            // Find the first Hop within a RSP.
+            List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
+            if (pathHopList.isEmpty()) {
+                LOG.info("Service Path = {} has empty hops!!", sfpName);
+                return;
+            }
+
+            RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
+                    .readRenderedServicePathFirstHop(new RspName(rspName));
+            //String firstSff = firstHop.getServiceFunctionForwarderLocator();
+
+            LOG.debug("First Hop IPAddress = {}, Port = {}", firstRspHop.getIp().getIpv4Address().getValue(),
+                    firstRspHop.getPort().getValue().intValue());
+            OvsdbTerminationPointAugmentation tunnelPort = southbound
+                    .getTerminationPointOfBridge(srcNode, GPE_IFACE_ID);
+            if (tunnelPort != null) {
+                long tunnelOfPort = southbound.getOFPort(tunnelPort);
+                LOG.debug("Tunnel Port = {}, OF Port Number = {}", tunnelPort.getName(), tunnelOfPort);
+                if (tunnelOfPort == 0) {
+                    LOG.error("programTunnelRules: Could not Identify Tunnel port {} -> OF ({}) on {}",
+                            tunnelPort.getName(), tunnelOfPort, srcNode);
+                    return;
+                }
+            }
+
+            Matches match = entry.getMatches();
+
+            NshUtils header = new NshUtils();
+            // C1 is the normal overlay dest ip
+            header.setNshMetaC1(convertToLongIp(getDestIp(match)));
+            header.setNshMetaC2(Long.parseLong(NETWORK_SEGMENT_ID));
+            header.setNshNsp(rsp.getPathId());
+
+            RenderedServicePathHop firstHop = pathHopList.get(0);
+            header.setNshNsi(firstHop.getServiceIndex());
+            header.setNshTunIpDst(firstRspHop.getIp().getIpv4Address());
+            header.setNshTunUdpPort(firstRspHop.getPort());
+
+            LOG.debug("The Nsh Header = {}", header);
+            OvsdbTerminationPointAugmentation localPort = getTerminationPoint(srcNode, LOCAL_TP_ID);
+
+           /* String attachedMac = southbound.getInterfaceExternalIdsValue(localPort, Constants.EXTERNAL_ID_VM_MAC);
+            if (attachedMac == null) {
+                LOG.warn("No AttachedMac seen in {}", localPort);
+                // return;
+            }
+            */
+            LOG.debug("LocalPort ID={}, IP Address = {}", localPort.getName(), getSourceIp(match));
+            handleLocalInPort(southbound.getDataPathId(srcNode), TABLE_0_CLASSIFIER, TABLE_3_INGR_ACL,
+                    NETWORK_SEGMENT_ID, localPort.getOfport(), getSourceIp(match), true);
+
+            // L2 Dst MAC forwarding flows.
+            // L2 Flood Flows.
+            // Set the Tunnel Destination IP, Dest MAC based on the destination IP address.
+            // Replace SMAC & decrement TTL.
+            // handleL3Flows(southbound.getDataPathId(srcNode), TABLE_1_ISOLATE_TENANT,
+            // TABLE_2_INGRESS_ACL, destIp, l3SegmentId, destMac);
+            // Set NSP & NSI values based on the Classifier Match actions.
+            OvsdbTerminationPointAugmentation outPort = getTerminationPoint(srcNode, INTERFACE_TYPE_VXLAN_GPE);
+            // TODO: commented out for test
+            //handleSfcClassiferFlows(entry.getRuleName(), srcNode, match,
+            //              TABLE_3_INGR_ACL, header, outPort.getOfport(), true);
+            // Set NSHC1, NSHC2, Tunnel DestIP, port toward SFF1, output to Tunnel Port.
+
+        }
+    }
+
+    private OvsdbTerminationPointAugmentation getTerminationPoint(Node srcNode, String localTpId) {
+        List<OvsdbTerminationPointAugmentation> ports = southbound.extractTerminationPointAugmentations(srcNode);
+        if (ports != null && !ports.isEmpty()) {
+            for (OvsdbTerminationPointAugmentation port : ports) {
+                // TBD :: For Demo, use the Tunnel ID as 10. Once openstack is integrated,
+                // tunnel ID is created through Network Creation.
+                if (port.getName().contains(localTpId)) {
+                    return port;
+                }
+            }
+        }
+        return null;
+    }
+
+    private String getTunnelName(String networkTypeVxlan, Ipv4Address ipv4Address) {
+        return networkTypeVxlan + "-" + ipv4Address.getValue();
+    }
+
+    /*
+     * (TABLE:50) EGRESS VM TRAFFIC TOWARDS TEP with NSH header
+     * MATCH: Match fields passed through ACL entry
+     * INSTRUCTION: SET TUNNELID AND GOTO TABLE TUNNEL TABLE (N)
+     * TABLE=0,IN_PORT=2,DL_SRC=00:00:00:00:00:01 \
+     * ACTIONS=SET_FIELD:5->TUN_ID,GOTO_TABLE=1"
+     */
+    private void handleSfcClassiferFlows(String ruleName, Node node, Matches match,
+                 short table3IngrAcl, NshUtils header, long ofPort, boolean write) {
+        // Build the Actions to Add the NSH Header
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC1Load =
+                        NshUtils.nxLoadNshc1RegAction(header.getNshMetaC1());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC2Load =
+                        NshUtils.nxLoadNshc2RegAction(header.getNshMetaC2());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nspLoad =
+                        NshUtils.nxSetNspAction(header.getNshNsp());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nsiLoad =
+                        NshUtils.nxSetNsiAction(header.getNshNsi());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunVnid =
+                        NshUtils.nxLoadTunIdAction(BigInteger.valueOf(header.getNshMetaC2()), false);
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunDest =
+                        NshUtils.nxLoadTunIPv4Action(header.getNshTunIpDst().getValue(), false);
+
+        int count = 0;
+        List<Action> actionList = Lists.newArrayList();
+        actionList.add(new ActionBuilder().setOrder(Integer.valueOf(count++)).setAction(nshC1Load).build());
+        actionList.add(new ActionBuilder().setOrder(Integer.valueOf(count++)).setAction(nshC2Load).build());
+        actionList.add(new ActionBuilder().setOrder(Integer.valueOf(count++)).setAction(nspLoad).build());
+        actionList.add(new ActionBuilder().setOrder(Integer.valueOf(count++)).setAction(nsiLoad).build());
+        actionList.add(new ActionBuilder().setOrder(Integer.valueOf(count++)).setAction(loadChainTunDest).build());
+        actionList.add(new ActionBuilder().setOrder(Integer.valueOf(count++)).setAction(loadChainTunVnid).build());
+
+        ApplyActionsBuilder aab = new ApplyActionsBuilder();
+        aab.setAction(actionList);
+
+        InstructionBuilder ib = new InstructionBuilder();
+        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+        ib.setOrder(0);
+        ib.setKey(new InstructionKey(0));
+
+        List<Instruction> instructions = Lists.newArrayList();
+        instructions.add(ib.build());
+
+     // Set the Output Port/Iface
+        InstructionUtils.createOutputPortInstructions(ib, southbound.getDataPathId(node), ofPort);
+        ib.setOrder(1);
+        ib.setKey(new InstructionKey(1));
+        instructions.add(ib.build());
+
+     // Add InstructionBuilder to the Instruction(s)Builder List
+        InstructionsBuilder isb = new InstructionsBuilder();
+        isb.setInstruction(instructions);
+
+        String flowId = "NETVIRT_SFC_FLOW" + "_" + ruleName + "_" + header.getNshNsp();
         FlowBuilder flowBuilder = new FlowBuilder();
         flowBuilder.setId(new FlowId(flowId));
         FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setMatch(matchBuilder.build());
+
+        MatchBuilder mb = buildMatch(match);
+        flowBuilder.setMatch(mb.build());
         flowBuilder.setPriority(DEFAULT_FLOW_PRIORITY);
         flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(this.getTable());
+        flowBuilder.setTableId(table3IngrAcl);
         flowBuilder.setKey(key);
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
@@ -165,6 +396,175 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
 
         flowBuilder.setInstructions(isb.build());
 
+        if (write) {
+            writeFlow(flowBuilder, createNodeBuilder(node.getNodeId().getValue()));
+        } else {
+            removeFlow(flowBuilder, createNodeBuilder(node.getNodeId().getValue()));
+        }
+    }
+
+    /*
+     * (TABLE:0) EGRESS VM TRAFFIC TOWARDS TEP
+     * MATCH: DESTINATION ETHERNET ADDR AND OPENFLOW INPORT
+     * INSTRUCTION: SET TUNNELID AND GOTO TABLE TUNNEL TABLE (N)
+     * TABLE=0,IN_PORT=2,DL_SRC=00:00:00:00:00:01 \
+     * ACTIONS=SET_FIELD:5->TUN_ID,GOTO_TABLE=1"
+     */
+    private void handleLocalInPort(long dpidLong, short writeTable, short goToTableId,
+            String segmentationId, Long inPort, String sourceIp,
+            boolean write) {
+        programDropSrcIface(dpidLong, inPort, true);
+        programLocalInPort(dpidLong, segmentationId, inPort, sourceIp, goToTableId, write);
+    }
+
+    private String getDestIp(Matches match) {
+        if (match.getAceType() instanceof AceIp) {
+            AceIp aceIp = (AceIp)match.getAceType();
+            if (aceIp.getAceIpVersion() instanceof AceIpv4) {
+                AceIpv4 aceIpv4 = (AceIpv4) aceIp.getAceIpVersion();
+                if (aceIpv4.getDestinationIpv4Network() != null) {
+                    String ipAddrPrefix = aceIpv4.getDestinationIpv4Network().getValue();
+                    String ipAddr = new StringTokenizer(ipAddrPrefix, "/").nextToken();
+                    return ipAddr;
+                }
+            }
+        }
+        return null;
+    }
+
+    private String getSourceIp(Matches match) {
+        if (match.getAceType() instanceof AceIp) {
+            AceIp aceIp = (AceIp)match.getAceType();
+            if (aceIp.getAceIpVersion() instanceof AceIpv4) {
+                AceIpv4 aceIpv4 = (AceIpv4) aceIp.getAceIpVersion();
+                if (aceIpv4.getSourceIpv4Network() != null) {
+                    String ipAddrPrefix = aceIpv4.getSourceIpv4Network().getValue();
+                    //String ipAddr = new StringTokenizer(ipAddrPrefix, "/").nextToken();
+                    return ipAddrPrefix;
+                }
+            }
+        }
+        return null;
+    }
+
+    private long convertToLongIp(String ipaddr) {
+        LOG.debug("Converting String={} to Long", ipaddr);
+        return InetAddresses.coerceToInteger(InetAddresses.forString(ipaddr)) & 0xFFFFFFFFL;
+    }
+
+    private void programLocalInPort(Long dpidLong, String segmentationId, Long inPort,
+                                    String ipAddr, short goToTableId, boolean write) {
+        String nodeName = OPENFLOW + dpidLong;
+
+        MatchBuilder matchBuilder = new MatchBuilder();
+        NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        // Create the OF Match using MatchBuilder
+        //flowBuilder.setMatch(MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
+        // TODO Broken In_Port Match
+        flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
+        //flowBuilder.setMatch(MatchUtils.createSrcL3IPv4Match(matchBuilder, new Ipv4Prefix(ipAddr)).build());
+        String flowId = "LocalSfc_" + segmentationId + "_" + inPort;// + "_" + ipAddr.split("/",2)[0];
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setStrict(true);
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId((short)0);//getTable());
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setPriority(8192);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+
+        if (write) {
+            // Instantiate the Builders for the OF Actions and Instructions
+            InstructionBuilder ib = new InstructionBuilder();
+            InstructionsBuilder isb = new InstructionsBuilder();
+
+            // Instructions List Stores Individual Instructions
+            List<Instruction> instructions = Lists.newArrayList();
+
+            // TODO Broken SetTunID
+            //InstructionUtils.createSetTunnelIdInstructions(ib, new BigInteger(segmentationId));
+            //ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
+            //List<Action> actionList = aac.getApplyActions().getAction();
+
+            //ActionBuilder ab = new ActionBuilder();
+            //ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD).build(),
+            //        BigInteger.valueOf(REG_VALUE_FROM_LOCAL)));
+            //ab.setOrder(1);
+            //ab.setKey(new ActionKey(1));
+
+            //actionList.add(ab.build());
+
+            //ib.setOrder(0);
+            //ib.setKey(new InstructionKey(0));
+            //instructions.add(ib.build());
+
+            // Next service GOTO Instructions Need to be appended to the List
+            ib = InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), goToTableId);
+            ib.setOrder(0);//1);
+            ib.setKey(new InstructionKey(0));//1));
+            instructions.add(ib.build());
+
+            // Add InstructionBuilder to the Instruction(s)Builder List
+            isb.setInstruction(instructions);
+
+            // Add InstructionsBuilder to FlowBuilder
+            flowBuilder.setInstructions(isb.build());
+
+            writeFlow(flowBuilder, nodeBuilder);
+        } else {
+            removeFlow(flowBuilder, nodeBuilder);
+        }
+    }
+
+    public void programDropSrcIface(Long dpidLong, Long inPort, boolean write) {
+
+        String nodeName = OPENFLOW + dpidLong;
+
+        MatchBuilder matchBuilder = new MatchBuilder();
+        NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        // Create the OF Match using MatchBuilder
+        flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
+
+        if (write) {
+            // Instantiate the Builders for the OF Actions and Instructions
+            InstructionBuilder ib = new InstructionBuilder();
+            InstructionsBuilder isb = new InstructionsBuilder();
+
+            // Instructions List Stores Individual Instructions
+            List<Instruction> instructions = Lists.newArrayList();
+
+            // Call the InstructionBuilder Methods Containing Actions
+            InstructionUtils.createDropInstructions(ib);
+            ib.setOrder(0);
+            ib.setKey(new InstructionKey(0));
+            instructions.add(ib.build());
+
+            // Add InstructionBuilder to the Instruction(s)Builder List
+            isb.setInstruction(instructions);
+
+            // Add InstructionsBuilder to FlowBuilder
+            flowBuilder.setInstructions(isb.build());
+        }
+
+        String flowId = "DropFilter_"+inPort;
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setStrict(true);
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId((short)50);//getTable());
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setPriority(8192);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
         if (write) {
             writeFlow(flowBuilder, nodeBuilder);
         } else {
@@ -172,6 +572,28 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
         }
     }
 
+    private Node getBridgeNode(String bridgeName) {
+        //SffOvsBridgeAugmentation sffBridge = sff.getAugmentation(SffOvsBridgeAugmentation.class);
+        //String brName = sffBridge.getOvsBridge().getBridgeName();
+
+        final List<Node> nodes = nodeCacheManager.getBridgeNodes();
+        if (nodes.isEmpty()) {
+            LOG.debug("Noop with Classifier Creation on SFF={}. No Bridges configured YET!!", bridgeName);
+        } else {
+            for (Node node : nodes) {
+                OvsdbBridgeAugmentation bridgeAugmentation = southbound.extractBridgeAugmentation(node);
+                if (bridgeAugmentation != null) {
+                    if (bridgeAugmentation.getBridgeName().getValue().equalsIgnoreCase(bridgeName)) {
+                        LOG.info("Found matching OVSDB Bridge Name {}", node.getNodeId().getValue());
+                        return node;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+/*
     private InstructionsBuilder buildActions(String ruleName, Actions actions, String datapathId) {
         InstructionBuilder ib = new InstructionBuilder();
 
@@ -199,9 +621,37 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
         InstructionsBuilder isb = new InstructionsBuilder();
         isb.setInstruction(instructions);
         return isb;
+    }*/
+
+    private ServiceFunctionPath getSfp(String redirectSfc) {
+        ServiceFunctionPaths sfps = SfcProviderServicePathAPI.readAllServiceFunctionPaths();
+        if (sfps != null) {
+            for (ServiceFunctionPath sfp: sfps.getServiceFunctionPath()) {
+                if (sfp.getServiceChainName().getValue().equalsIgnoreCase(redirectSfc)) {
+                    return sfp;
+                }
+            }
+        }
+        return null;
+    }
+
+    private RenderedServicePath getRspforSfp(String sfpName) {
+        RenderedServicePaths rsps = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, this.getRspsId());
+        if (rsps == null) {
+            LOG.debug("RSP has not been configured yet for SFP = {}", sfpName);
+            return null;
+        }
+        for (RenderedServicePath rsp : rsps.getRenderedServicePath()) {
+            if (rsp.getParentServiceFunctionPath() !=  null) {
+                if (rsp.getParentServiceFunctionPath().getValue().equalsIgnoreCase(sfpName)) {
+                    return rsp;
+                }
+            }
+        }
+        return null;
     }
 
-    private MatchBuilder buildMatch(String ruleName, Matches matches, String dpId) {
+    private MatchBuilder buildMatch(Matches matches) {
         MatchBuilder matchBuilder = new MatchBuilder();
 
         if (matches.getAceType() instanceof AceIp) {
@@ -209,10 +659,10 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
             if (aceIp.getAceIpVersion() instanceof AceIpv4) {
                 AceIpv4 aceIpv4 = (AceIpv4) aceIp.getAceIpVersion();
                 MatchUtils.createSrcL3IPv4Match(matchBuilder, aceIpv4.getSourceIpv4Network());
-                MatchUtils.createDstL3IPv4Match(matchBuilder, aceIpv4.getDestinationIpv4Network());
-                MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
+                //MatchUtils.createDstL3IPv4Match(matchBuilder, aceIpv4.getDestinationIpv4Network());
+                //MatchUtils.createIpProtocolMatch(matchBuilder, aceIp.getProtocol());
                 MatchUtils.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(),
-                        aceIp.getSourcePortRange().getLowerPort().getValue().intValue(),
+                        0,
                         aceIp.getDestinationPortRange().getLowerPort().getValue().intValue());
             }
         } else if (matches.getAceType() instanceof AceEth) {
@@ -229,19 +679,37 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
     @Override
     public void removeClassifierRules(Sff sff, Acl acl) {
         // TODO Auto-generated method stub
-
     }
 
-
+    /*
     protected void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
         LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}",
                 flowBuilder.build(), nodeBuilder.build());
-        dbutils.merge(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder), nodeBuilder.build());
-        dbutils.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder), flowBuilder.build());
+        mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder), nodeBuilder.build());
+        mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder), flowBuilder.build());
+    }
+*/
+    protected void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+        LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}",
+                flowBuilder.build(), nodeBuilder.build());
+        WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
+        modification.put(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder),
+                nodeBuilder.build(), true /*createMissingParents*/);
+        modification.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder),
+                flowBuilder.build(), true /*createMissingParents*/);
+
+        CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
+        try {
+            commitFuture.get();  // TODO: Make it async (See bug 1362)
+            LOG.debug("Transaction success for write of Flow {}", flowBuilder.getFlowName());
+        } catch (Exception e) {
+            LOG.error(e.getMessage(), e);
+            modification.cancel();
+        }
     }
 
     protected void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
-        dbutils.delete(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder));
+        mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder));
     }
 
     private String getDpid(Node node) {
@@ -268,22 +736,28 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
                         nodeBuilder.getKey()).build();
     }
 
-    private short getTable() {
-        return Service.INGRESS_ACL.getTable();
+    private NodeBuilder createNodeBuilder(String nodeId) {
+        NodeBuilder builder = new NodeBuilder();
+        builder.setId(new NodeId(nodeId));
+        builder.setKey(new NodeKey(builder.getId()));
+        return builder;
     }
 
-    private final InstructionBuilder getMutablePipelineInstructionBuilder() {
-        Service nextService = orchestrator.getNextServiceInPipeline(Service.INGRESS_ACL);
-        if (nextService != null) {
-            return InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), nextService.getTable());
-        } else {
-            return InstructionUtils.createDropInstructions(new InstructionBuilder());
-        }
+    private InstanceIdentifier<RenderedServicePaths> getRspsId() {
+        return InstanceIdentifier.builder(RenderedServicePaths.class).build();
+    }
+
+    private InstanceIdentifier<RenderedServicePath> getRspId(String rspName) {
+        return InstanceIdentifier.builder(RenderedServicePaths.class)
+                .child(RenderedServicePath.class, new RenderedServicePathKey(new RspName(rspName))).build();
+    }
+
+    private short getTable() {
+        return Service.INGRESS_ACL.getTable();
     }
 
     private void setDependencies(ServiceReference serviceReference) {
         nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
         southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
-        orchestrator = (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this);
     }
 }
diff --git a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/NshUtils.java b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/NshUtils.java
new file mode 100644 (file)
index 0000000..5265235
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2015 Dell, 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.ovsdb.openstack.netvirt.sfc.openflow13;
+
+import java.math.BigInteger;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
+
+import com.google.common.net.InetAddresses;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.DstChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIpv4DstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionOutputRegNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNshc1NodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNshc2NodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNshc3NodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNshc4NodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNsiNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionSetNspNodesNodeTableFlowApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputRegBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoadBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.nx.reg.load.DstBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._1.grouping.NxSetNshc1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._1.grouping.NxSetNshc1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._2.grouping.NxSetNshc2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._2.grouping.NxSetNshc2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._3.grouping.NxSetNshc3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._3.grouping.NxSetNshc3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._4.grouping.NxSetNshc4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nshc._4.grouping.NxSetNshc4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsi.grouping.NxSetNsi;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsi.grouping.NxSetNsiBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsp.grouping.NxSetNsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.set.nsp.grouping.NxSetNspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.SrcChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCaseBuilder;
+
+/**
+ * Open Vswitch DB OpenFlow 1.3 Networking Provider for Netvirt SFC Utilities.
+ * @author Arun Yerra
+ */
+public class NshUtils {
+    private Ipv4Address nshTunIpDst;
+    private PortNumber nshTunUdpPort;
+    private long nshNsp;
+    private short nshNsi;
+    private long nshMetaC1;
+    private long nshMetaC2;
+
+    public NshUtils() {
+        super();
+    }
+
+    /**
+     * {@link NshUtils} constructor.
+     * @param nshTunIpDst Tunnel Destination IP
+     * @param nshTunUdpPort Tunnel Transport Port
+     * @param nshNsp Service Path Id
+     * @param nshNsi Service Path Index
+     * @param nshMetaC1 End point ID
+     * @param nshMetaC2 Tunnel Id.
+     */
+    public NshUtils(Ipv4Address nshTunIpDst, PortNumber nshTunUdpPort,
+            long nshNsp, short nshNsi, long nshMetaC1,
+            long nshMetaC2) {
+        super();
+        this.nshTunIpDst = nshTunIpDst;
+        this.nshTunUdpPort = nshTunUdpPort;
+        this.nshNsp = nshNsp;
+        this.nshNsi = nshNsi;
+        this.nshMetaC1 = nshMetaC1;
+        this.nshMetaC2 = nshMetaC2;
+    }
+
+    /*
+     * @return the nshTunIpDst
+     */
+    public Ipv4Address getNshTunIpDst() {
+        return nshTunIpDst;
+    }
+
+    /*
+     * @param nshTunIpDst the nshTunIpDst to set
+     */
+    public void setNshTunIpDst(Ipv4Address nshTunIpDst) {
+        this.nshTunIpDst = nshTunIpDst;
+    }
+
+    /*
+     * @return the nshTunUdpPort
+     */
+    public PortNumber getNshTunUdpPort() {
+        return nshTunUdpPort;
+    }
+
+    /*
+     * @param nshTunUdpPort the nshTunUdpPort to set
+     */
+    public void setNshTunUdpPort(PortNumber nshTunUdpPort) {
+        this.nshTunUdpPort = nshTunUdpPort;
+    }
+
+    /*
+     * @return the nshNsp
+     */
+    public long getNshNsp() {
+        return nshNsp;
+    }
+
+    /*
+     * @param nshNsp the nshNsp to set
+     */
+    public void setNshNsp(long nshNsp) {
+        this.nshNsp = nshNsp;
+    }
+
+    /*
+     * @return the nshNsi
+     */
+    public short getNshNsi() {
+        return nshNsi;
+    }
+
+    /*
+     * @param nshNsi the nshNsi to set
+     */
+    public void setNshNsi(short nshNsi) {
+        this.nshNsi = nshNsi;
+    }
+
+    /*
+     * @return the nshMetaC1
+     */
+    public long getNshMetaC1() {
+        return nshMetaC1;
+    }
+
+    /*
+     * @param nshMetaC1 the nshMetaC1 to set
+     */
+    public void setNshMetaC1(long nshMetaC1) {
+        this.nshMetaC1 = nshMetaC1;
+    }
+
+    /*
+     * @return the nshMetaC2
+     */
+    public long getNshMetaC2() {
+        return nshMetaC2;
+    }
+
+    /*
+     * @param nshMetaC2 the nshMetaC2 to set
+     */
+    public void setNshMetaC2(long nshMetaC2) {
+        this.nshMetaC2 = nshMetaC2;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "NshUtils [nshTunIpDst=" + nshTunIpDst + ", nshTunUdpPort=" + nshTunUdpPort + ", nshNsp=" + nshNsp
+                + ", nshNsi=" + nshNsi + ", nshMetaC1=" + nshMetaC1 + ", nshMetaC2=" + nshMetaC2 + "]";
+    }
+
+    /**
+     * This method loads the action into NX register.
+     *{@link NshUtils} Loading Register
+     * @param dstChoice destination
+     * @param value value
+     * @param endOffset Offset
+     * @param groupBucket Identifies the group
+     */
+    public static Action nxLoadRegAction(DstChoice dstChoice, BigInteger value, int endOffset, boolean groupBucket) {
+        NxRegLoad reg = new NxRegLoadBuilder().setDst(
+                new DstBuilder().setDstChoice(dstChoice)
+                    .setStart(Integer.valueOf(0))
+                    .setEnd(Integer.valueOf(endOffset))
+                    .build())
+            .setValue(value)
+            .build();
+        if (groupBucket) {
+            return new NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder().setNxRegLoad(reg).build();
+        } else {
+            return new NxActionRegLoadNodesNodeTableFlowApplyActionsCaseBuilder().setNxRegLoad(reg).build();
+        }
+    }
+
+    public static Action nxLoadRegAction(DstChoice dstChoice, BigInteger value) {
+        return nxLoadRegAction(dstChoice, value, 31, false);
+    }
+
+    public static Action nxLoadRegAction(Class<? extends NxmNxReg> reg, BigInteger value) {
+        return nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(reg).build(), value);
+    }
+
+    public static Action nxSetNsiAction(Short nsi) {
+        NxSetNsi newNsi = new NxSetNsiBuilder().setNsi(nsi).build();
+        return new NxActionSetNsiNodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNsi(newNsi).build();
+    }
+
+    public static Action nxSetNspAction(Long nsp) {
+        NxSetNsp newNsp = new NxSetNspBuilder().setNsp(nsp).build();
+        return new NxActionSetNspNodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNsp(newNsp).build();
+    }
+
+    public static Action nxLoadNshc1RegAction(Long value) {
+        NxSetNshc1 newNshc1 = new NxSetNshc1Builder().setNshc(value).build();
+        return new NxActionSetNshc1NodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNshc1(newNshc1).build();
+    }
+
+    public static Action nxLoadNshc2RegAction(Long value) {
+        NxSetNshc2 newNshc2 = new NxSetNshc2Builder().setNshc(value).build();
+        return new NxActionSetNshc2NodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNshc2(newNshc2).build();
+    }
+
+    public static Action nxLoadNshc3RegAction(Long value) {
+        NxSetNshc3 newNshc3 = new NxSetNshc3Builder().setNshc(value).build();
+        return new NxActionSetNshc3NodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNshc3(newNshc3).build();
+    }
+
+    public static Action nxLoadNshc4RegAction(Long value) {
+        NxSetNshc4 newNshc4 = new NxSetNshc4Builder().setNshc(value).build();
+        return new NxActionSetNshc4NodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNshc4(newNshc4).build();
+    }
+
+    /**
+     * This method loads Destination IPv4 address of Tunnel.
+     */
+    public static Action nxLoadTunIPv4Action(String ipAddress, boolean groupBucket) {
+        int ip = InetAddresses.coerceToInteger(InetAddresses.forString(ipAddress));
+        long ipl = ip & 0xffffffffL;
+        return nxLoadRegAction(new DstNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),
+                BigInteger.valueOf(ipl), 31, groupBucket);
+    }
+
+    public static Action nxLoadTunIdAction(BigInteger tunnelId, boolean groupBucket) {
+        return nxLoadRegAction(new DstNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(), tunnelId, 31, groupBucket);
+    }
+
+    /**
+     * This method loads output port.
+     */
+    public static Action nxOutputRegAction(SrcChoice srcChoice) {
+        NxOutputReg reg = new NxOutputRegBuilder().setSrc(
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension
+                    .nicira.action.rev140714.nx.action.output.reg.grouping.nx.output.reg
+                    .SrcBuilder().setSrcChoice(srcChoice)
+                    .setOfsNbits(Integer.valueOf(31))
+                    .build())
+            .setMaxLen(Integer.valueOf(0xffff))
+            .build();
+        return new NxActionOutputRegNodesNodeTableFlowApplyActionsCaseBuilder().setNxOutputReg(reg).build();
+    }
+
+    public static Action nxOutputRegAction(Class<? extends NxmNxReg> reg) {
+        return nxOutputRegAction(new SrcNxRegCaseBuilder().setNxReg(reg).build());
+    }
+}
index a9dc254eb8da3537d5e12d93021c33bd993593fc..441bcf8beea3f61f4eb9f909dd52e731e7c9e172 100644 (file)
@@ -88,11 +88,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       </plugin>
       <plugin>
         <artifactId>maven-failsafe-plugin</artifactId>
-        <!--<configuration>
+        <configuration>
           <excludes>
             <exclude>**/NetvirtSfcIT.java</exclude>
           </excludes>
-        </configuration>-->
+        </configuration>
       </plugin>
     </plugins>
   </build>
index 443656e68e4c4597f8de2452a3b35aff4e52c868..c39bf63bfdd6ed55f9456abdd69002fb42c6aca6 100644 (file)
@@ -35,6 +35,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.AclUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ClassifierUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
+import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
@@ -159,7 +160,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
                         LogLevel.INFO.name()),
                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
                         "log4j.logger.org.opendaylight.ovsdb.openstack.netvirt.sfc",
-                        LogLevel.INFO.name()),
+                        LogLevel.TRACE.name()),
                 /*editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
                         "log4j.logger.org.opendaylight.ovsdb",
                         LogLevelOption.LogLevel.TRACE.name()),*/
@@ -364,4 +365,58 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         Thread.sleep(1000);
         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
     }
+
+    @Test
+    public void testDemo() throws InterruptedException {
+        for (DemoVm vm : demoVms){
+            ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(vm.ipAddr, vm.ipPort);
+            assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
+            Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
+            assertNotNull("node is not connected", ovsdbNode);
+            String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
+            assertNotNull("Failed to get controller target", controllerTarget);
+            List<ControllerEntry> setControllerEntry = southboundUtils.createControllerEntry(controllerTarget);
+            Uri setUri = new Uri(controllerTarget);
+            assertTrue(southboundUtils.addBridge(connectionInfo, null, vm.name, null, true,
+                    SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
+                    setControllerEntry, null));
+
+            for (int i = 0; i < 10; i++) {
+                OvsdbBridgeAugmentation bridge = southboundUtils.getBridge(connectionInfo, vm.name);
+                assertNotNull("bridge was not found: " + vm.name, bridge);
+                assertNotNull("ControllerEntry was not found: "
+                                + southboundUtils.createControllerEntry(controllerTarget),
+                        bridge.getControllerEntry());
+                List<ControllerEntry> getControllerEntries = bridge.getControllerEntry();
+                for (ControllerEntry entry : getControllerEntries) {
+                    if (entry.isIsConnected()) {
+                        assertTrue(entry.isIsConnected());
+                        break;
+                    }
+                }
+                Thread.sleep(1000);
+            }
+
+            assertTrue(southboundUtils.deleteBridge(connectionInfo, vm.name));
+            Thread.sleep(1000);
+            assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
+        }
+    }
+
+    private class DemoVm {
+        String name;
+        String ipAddr;
+        String ipPort;
+
+        DemoVm(String name, String ipAddr, String ipPort) {
+            this.name = name;
+            this.ipAddr = ipAddr;
+            this.ipPort = ipPort;
+        }
+    }
+
+    private DemoVm[] demoVms = {
+            new DemoVm("sw1", "192.168.50.70", "6640"),
+            //new DemoVm("sw2", "192.168.50.71", "6640"),
+    };
 }
index 13d215cf9612a1d0130e11b275bc782561bbfe86..88f72412370d848dced908e007415556efb184d7 100644 (file)
@@ -108,6 +108,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <configuration>
           <instructions>
             <Export-Package>
+              org.opendaylight.ovsdb.southbound,
               org.opendaylight.ovsdb.southbound.*,
               org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.southbound.impl.rev141210.*</Export-Package>
           </instructions>
index 7ac9a396bb8c244232eb5788dd3aab3b48ffda90..76c90549d84ec86a5e7b86d0dfb9ec43b197e03a 100644 (file)
@@ -317,6 +317,13 @@ public class SouthboundUtils {
         return result;
     }
 
+    public boolean addBridge(final ConnectionInfo connectionInfo, final String bridgeName)
+            throws InterruptedException {
+
+        return addBridge(connectionInfo, null, bridgeName, null, true,
+                SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null);
+    }
+
     private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
                               final ConnectionInfo connectionInfo) {
         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);