Add back the proper NetvirtSfc flows
authorSam Hague <shague@redhat.com>
Sun, 1 Nov 2015 14:33:16 +0000 (09:33 -0500)
committerSam Hague <shague@redhat.com>
Sun, 1 Nov 2015 14:58:19 +0000 (09:58 -0500)
Change-Id: I26fe692c95b14c8b4baa7aa575a233feb4337914
Signed-off-by: Sam Hague <shague@redhat.com>
openstack/net-virt-sfc/features/production/pom.xml
openstack/net-virt-sfc/features/production/src/main/features/features.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
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/SfcClassifier.java [new file with mode: 0644]
utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/ActionUtils.java

index 01fb239e0a0b09ca4db7f278c487135641b09322..ba405df726bf5fa56275456d900688f4c5268b6d 100644 (file)
@@ -115,6 +115,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <classifier>features</classifier>
       <type>xml</type>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.openflowplugin</groupId>
+      <artifactId>features-openflowplugin-extension</artifactId>
+      <version>${openflowplugin.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.sfc</groupId>
       <artifactId>features-sfc</artifactId>
@@ -131,6 +138,14 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <type>xml</type>
       <scope>runtime</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.sfc</groupId>
+      <artifactId>features-sfcofl2</artifactId>
+      <version>${sfc.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>openstack.net-virt-sfc-impl</artifactId>
index 1b4ca16239b492ef20782f1e8df8308edc3bf561..54ee4236138f176d3f62b35b4e809e5f67ae6f41 100644 (file)
@@ -15,10 +15,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/${openflowplugin.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.ovsdb/features-ovsdb/${project.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.ovsdb/southbound-features/${project.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.sfc/features-sfc/${sfc.version}/xml/features</repository>
-  <repository>mvn:org.opendaylight.sfc/features-sfc-ovs/${sfc.version}/xml/features</repository>
+  <!--<repository>mvn:org.opendaylight.sfc/features-sfc-ovs/${sfc.version}/xml/features</repository>-->
+  <repository>mvn:org.opendaylight.sfc/features-sfcofl2/${sfc.version}/xml/features</repository>
   <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
   <feature name='odl-ovsdb-sfc-api' version='${project.version}' description='OpenDaylight :: ovsdb-sfc :: api'>
     <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
@@ -27,10 +29,13 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <feature name='odl-ovsdb-sfc' version='${project.version}' description='OpenDaylight :: ovsdb-sfc'>
     <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
     <feature version="${openflowplugin.version}">odl-openflowplugin-nsf-model</feature>
+    <feature version="${openflowplugin.version}">odl-openflowplugin-flow-services</feature>
+    <feature version='${openflowplugin.version}'>odl-openflowplugin-nxm-extensions</feature>
     <feature version='${project.version}'>odl-ovsdb-southbound-impl</feature>
     <feature version='${project.version}'>odl-ovsdb-openstack</feature>
     <feature version='${sfc.version}'>odl-sfc-core</feature>
-    <feature version='${sfc.version}'>odl-sfc-ovs</feature>
+    <!--<feature version='${sfc.version}'>odl-sfc-ovs</feature>-->
+    <feature version='${sfc.version}'>odl-sfcofl2</feature>
     <feature version="${openflowplugin.version}">odl-openflowplugin-flow-services</feature>
     <feature version='${project.version}'>odl-ovsdb-sfc-api</feature>
     <bundle>mvn:org.opendaylight.ovsdb/utils.mdsal-utils/${project.version}</bundle>
index b3e50bd6d68131572ed0d55af13e7bbed07e3403..139add1676b2e62d3d7496464a41816f50691aaf 100644 (file)
@@ -22,6 +22,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.acl.access.list.entries.AceKey;
 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,19 +108,20 @@ public class NetvirtSfcAclListener extends AbstractDataTreeListener<Acl> {
         String aclName = addDataObj.getAclName();
         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) {
-                        for (Sff sff : classifier.getSffs().getSff()) {
-                            provider.addClassifierRules(sff, addDataObj);
-                        }
+        if (classifiers == null) {
+            LOG.debug("add: No Classifiers found");
+            return;
+        }
+
+        LOG.debug("add: Classifiers: {}", classifiers);
+        for (Classifier classifier : classifiers.getClassifier()) {
+            if (classifier.getAcl().equals(aclName)) {
+                if (classifier.getBridges() != null) {
+                    for (Bridge bridge : classifier.getBridges().getBridge()) {
+                        provider.addClassifierRules(bridge, addDataObj);
                     }
                 }
             }
-        } else {
-            LOG.debug("add: No Classifiers found");
         }
     }
 
index b3d770f1c636d480ffbb8555b007c745a233757e..078b64b5e49447b623a498404ebf731fcca9cc89 100644 (file)
@@ -110,7 +110,7 @@ public class NetvirtSfcClassifierListener extends AbstractDataTreeListener<Class
         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));
+        Acl acl = dbutils.read(LogicalDatastoreType.CONFIGURATION, getIetfAclIid(aclName));
         if (acl == null) {
             LOG.debug("IETF ACL with name ={} is not yet configured. skip this operation", aclName);
             return;
@@ -118,9 +118,6 @@ public class NetvirtSfcClassifierListener extends AbstractDataTreeListener<Class
 
         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(bridge, acl);
             }
         }
index 270a1d0689872152e67594814afacb466cc1d1af..02f4471aa71dc35a24f84f6a29678148182b5ece 100644 (file)
@@ -22,10 +22,9 @@ public interface INetvirtSfcOF13Provider {
      * Method installs the OF rules corresponding to rules within ACL
      * on a given Service Function Forwarder. DataObject which is identified by InstanceIdentifier.
      *
-     * @param sff - Service Function Forwarder
+     * @param bridge - Service Function Forwarder
      * @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);
 
     /**
index acebecbdbc420b3378f282cdebc0a10153f52fe4..d3c14bf9778a77e649327f7d462c8084f141d89a 100644 (file)
@@ -8,27 +8,22 @@
 
 package org.opendaylight.ovsdb.openstack.netvirt.sfc.openflow13;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.net.InetAddresses;
 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.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.ovsdb.openstack.netvirt.api.NodeCacheManager;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
 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;
@@ -56,11 +51,9 @@ 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.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;
@@ -70,7 +63,6 @@ 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;
@@ -80,7 +72,8 @@ 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.openflowjava.nx.match.rev140421.NxmNxReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
 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;
@@ -92,19 +85,16 @@ 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
  */
 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;
@@ -113,13 +103,16 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
     private volatile Southbound southbound;
     private MdsalUtils mdsalUtils;
     private DataBroker dataBroker;
+    private SfcClassifier sfcClassifier;
 
     // 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 TUNNEL_DST = "192.168.50.75";
+    private static final String TUNNEL_VNID = "10";
+    private static final String CLIENT_PORT_NAME = "vethl-h35_2";
+    private static final String SERVER_PORT_NAME = "vethl-h35_4";
+    private static final String CLIENT_GPE_PORT_NAME = "sw1-vxlangpe-0";
+    private static final String SERVER_GPE_PORT_NAME = "sw6-vxlangpe-0";
     private static final String INTERFACE_TYPE_VXLAN_GPE = "vxlangpe";
-    private static final String GPE_IFACE_ID = "sw1-vxlangpe-0";
 
     /**
      * {@link NetvirtSfcOF13Provider} constructor.
@@ -130,52 +123,11 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
         this.dataBroker = dataBroker;
         mdsalUtils = new MdsalUtils(dataBroker);
         this.setDependencies(null);
+        sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
     }
 
-    @Override
-    public void addClassifierRules(Sff sff, Acl acl) {
-        Preconditions.checkNotNull(sff, "Input service function forwarder cannot be NULL!");
-        Preconditions.checkNotNull(acl, "Input accesslist cannot be NULL!");
-
-        // Validate if any service function forwarder exists by the name, using SFC provider APIs.
-        ServiceFunctionForwarder serviceForwarder =
-                SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(new SffName(sff.getName()));
-        if (serviceForwarder == null) {
-            LOG.debug("Service Function Forwarder = {} not yet configured. Skip processing !!", sff.getName());
-            return;
-        }
-
-        // 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 = 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 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.
-
-        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();
-                processAclEntry(entry, node, true);
-            }
-        } else {
-            LOG.warn("Skipping ACL processing on Node={} as DatapathID is NULL!!", sff.getName());
-        }
+    public void removeClassifierRules(Sff sff, Acl acl) {
+        // TODO Auto-generated method stub
     }
 
     @Override
@@ -189,571 +141,216 @@ public class NetvirtSfcOF13Provider implements INetvirtSfcOF13Provider{
             return;
         }
 
-        // Program the OF flow on the corresponding open flow node.
+        // TODO: Find all nodes needing the classifier and add classifier to them
         for (Ace ace : acl.getAccessListEntries().getAce()) {
             processAclEntry(ace, bridgeNode, true);
         }
     }
 
     private void processAclEntry(Ace entry, Node srcNode, boolean write) {
+        Matches matches = entry.getMatches();
+        if (matches == null) {
+            LOG.warn("processAclEntry: matches not found");
+            return;
+        }
+
         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 (sfcRedirect == null) {
+            LOG.warn("processAClEntry: sfcRedirect is null");
+            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);
+        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;
+        }
 
-            // Find the first Hop within a RSP.
-            List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
-            if (pathHopList.isEmpty()) {
-                LOG.info("Service Path = {} has empty hops!!", sfpName);
+        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);
+            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;
             }
 
-            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;
+            // 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);
+                    if (rspReverse == null) {
+                        LOG.warn("failed to add reverse RSP");
+                        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.info("processAclEntry: RSP: {}", rsp);
 
-            LOG.debug("The Nsh Header = {}", header);
-            OvsdbTerminationPointAugmentation localPort = getTerminationPoint(srcNode, LOCAL_TP_ID);
+        // Find the first Hop within an RSP.
+        // The classifier flow needs to send all matched traffic to this first hop SFF.
+        List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
+        if (pathHopList.isEmpty()) {
+            LOG.warn("Service Path = {} has empty hops!!", sfpName);
+            return;
+        }
 
-           /* 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.
+        RenderedServicePathFirstHop firstRspHop = SfcProviderRenderedPathAPI
+                .readRenderedServicePathFirstHop(new RspName(rspName));
 
+        LOG.debug("First Hop IPAddress = {}, Port = {}", firstRspHop.getIp().getIpv4Address().getValue(),
+                firstRspHop.getPort().getValue().intValue());
+        long tunnelOfPort = southbound.getOFPort(srcNode, CLIENT_GPE_PORT_NAME);
+        if (tunnelOfPort == 0L) {
+            LOG.error("programAclEntry: Could not identify tunnel port {} -> OF ({}) on {}",
+                    CLIENT_GPE_PORT_NAME, tunnelOfPort, srcNode);
+            return;
         }
-    }
 
-    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;
-                }
-            }
+        long localOfPort = southbound.getOFPort(srcNode, CLIENT_PORT_NAME);
+        if (localOfPort == 0L) {
+            LOG.error("programAclEntry: Could not identify local port {} -> OF ({}) on {}",
+                    CLIENT_GPE_PORT_NAME, localOfPort, srcNode);
+            return;
         }
-        return null;
-    }
 
-    private String getTunnelName(String networkTypeVxlan, Ipv4Address ipv4Address) {
-        return networkTypeVxlan + "-" + ipv4Address.getValue();
-    }
+        NshUtils nshHeader = new NshUtils();
+        // C1 is the normal overlay dest ip and c2 is the vnid
+        // Hardcoded for now, netvirt integration will have those values
+        nshHeader.setNshMetaC1(NshUtils.convertIpAddressToLong(new Ipv4Address(TUNNEL_DST)));
+        nshHeader.setNshMetaC2(Long.parseLong(TUNNEL_VNID));
+        nshHeader.setNshNsp(rsp.getPathId());
 
-    /*
-     * (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));
-
-        MatchBuilder mb = buildMatch(match);
-        flowBuilder.setMatch(mb.build());
-        flowBuilder.setPriority(DEFAULT_FLOW_PRIORITY);
-        flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(table3IngrAcl);
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
-
-        flowBuilder.setInstructions(isb.build());
-
-        if (write) {
-            writeFlow(flowBuilder, createNodeBuilder(node.getNodeId().getValue()));
-        } else {
-            removeFlow(flowBuilder, createNodeBuilder(node.getNodeId().getValue()));
-        }
-    }
+        RenderedServicePathHop firstHop = pathHopList.get(0);
+        nshHeader.setNshNsi(firstHop.getServiceIndex());
+        nshHeader.setNshTunIpDst(firstRspHop.getIp().getIpv4Address());
+        nshHeader.setNshTunUdpPort(firstRspHop.getPort());
+        LOG.debug("The Nsh Header = {}", nshHeader);
 
-    /*
-     * (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);
-    }
+        handleLocalInPort(southbound.getDataPathId(srcNode), rsp.getPathId().toString(), localOfPort,
+                TABLE_0_CLASSIFIER, TABLE_3_INGR_ACL, true);
 
-    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;
+        handleSfcClassiferFlows(southbound.getDataPathId(srcNode), TABLE_3_INGR_ACL, entry.getRuleName(),
+                matches, nshHeader, tunnelOfPort, true);
     }
 
-    private long convertToLongIp(String ipaddr) {
-        LOG.debug("Converting String={} to Long", ipaddr);
-        return InetAddresses.coerceToInteger(InetAddresses.forString(ipaddr)) & 0xFFFFFFFFL;
+    private void handleSfcClassiferFlows(long dataPathId, short writeTable, String ruleName,
+                                         Matches matches, NshUtils nshHeader, long tunnelOfPort,
+                                         boolean write) {
+        sfcClassifier.programSfcClassiferFlows(dataPathId, writeTable, ruleName, matches, nshHeader,
+                tunnelOfPort, write);
     }
 
-    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);
-        }
+    private InstanceIdentifier<RenderedServicePaths> getRspsId() {
+        return InstanceIdentifier.builder(RenderedServicePaths.class).build();
     }
 
-    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 {
-            removeFlow(flowBuilder, nodeBuilder);
-        }
+    private InstanceIdentifier<RenderedServicePath> getRspId(String rspName) {
+        return InstanceIdentifier.builder(RenderedServicePaths.class)
+                .child(RenderedServicePath.class, new RenderedServicePathKey(new RspName(rspName))).build();
     }
 
-    private Node getBridgeNode(String bridgeName) {
-        //SffOvsBridgeAugmentation sffBridge = sff.getAugmentation(SffOvsBridgeAugmentation.class);
-        //String brName = sffBridge.getOvsBridge().getBridgeName();
-
+    public Node getBridgeNode(String bridgeName) {
+        Node nodeFound = null;
         final List<Node> nodes = nodeCacheManager.getBridgeNodes();
-        if (nodes.isEmpty()) {
-            LOG.debug("Noop with Classifier Creation on SFF={}. No Bridges configured YET!!", bridgeName);
-        } else {
+        if (nodes != null && !nodes.isEmpty()) {
             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;
-                    }
+                if (southbound.getBridge(node, bridgeName) != null) {
+                    nodeFound = node;
+                    break;
                 }
             }
         }
-        return null;
+        return nodeFound;
     }
 
-/*
-    private InstructionsBuilder buildActions(String ruleName, Actions actions, String datapathId) {
-        InstructionBuilder ib = new InstructionBuilder();
-
-        if (actions.getPacketHandling() instanceof Deny) {
-            InstructionUtils.createDropInstructions(ib);
-        } else if (actions.getPacketHandling() instanceof Permit) {
-            //Permit actPermit = (Permit) actions.getPacketHandling();
-        } else {
-            InstructionUtils.createDropInstructions(ib);
+    public RenderedServicePath getRspforSfp(String sfpName) {
+        RenderedServicePath rspFound = null;
+        RenderedServicePaths rsps = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, this.getRspsId());
+        if (rsps != null) {
+            for (RenderedServicePath rsp : rsps.getRenderedServicePath()) {
+                if (rsp.getParentServiceFunctionPath() != null) {
+                    if (rsp.getParentServiceFunctionPath().getValue().equals(sfpName)) {
+                        rspFound = rsp;
+                    }
+                }
+            }
         }
+        return rspFound;
+    }
 
-        ib.setOrder(0);
-        ib.setKey(new InstructionKey(0));
-        // Instructions List Stores Individual Instructions
-        List<Instruction> instructions = Lists.newArrayList();
-        instructions.add(ib.build());
-
-        // Call the InstructionBuilder Methods Containing Actions
-        ib = this.getMutablePipelineInstructionBuilder();
-        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);
-        return isb;
-    }*/
-
-    private ServiceFunctionPath getSfp(String redirectSfc) {
+    public ServiceFunctionPath getSfp(String redirectSfc) {
+        ServiceFunctionPath sfpFound = null;
         ServiceFunctionPaths sfps = SfcProviderServicePathAPI.readAllServiceFunctionPaths();
         if (sfps != null) {
             for (ServiceFunctionPath sfp: sfps.getServiceFunctionPath()) {
                 if (sfp.getServiceChainName().getValue().equalsIgnoreCase(redirectSfc)) {
-                    return sfp;
+                    sfpFound = sfp;
                 }
             }
         }
-        return null;
+        return sfpFound;
     }
 
-    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;
+/*
+ * (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"
+ */
+    public 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 MatchBuilder buildMatch(Matches matches) {
-        MatchBuilder matchBuilder = new MatchBuilder();
-
-        if (matches.getAceType() instanceof AceIp) {
-            AceIp aceIp = (AceIp)matches.getAceType();
+    public String getSourceIp(Matches match) {
+        if (match.getAceType() instanceof AceIp) {
+            AceIp aceIp = (AceIp)match.getAceType();
             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.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(),
-                        0,
-                        aceIp.getDestinationPortRange().getLowerPort().getValue().intValue());
+                if (aceIpv4.getSourceIpv4Network() != null) {
+                    String ipAddrPrefix = aceIpv4.getSourceIpv4Network().getValue();
+                    //String ipAddr = new StringTokenizer(ipAddrPrefix, "/").nextToken();
+                    return ipAddrPrefix;
+                }
             }
-        } else if (matches.getAceType() instanceof AceEth) {
-            AceEth aceEth = (AceEth) matches.getAceType();
-            MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(aceEth.getSourceMacAddress().getValue()));
-            MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(aceEth.getDestinationMacAddress().getValue()),
-                    new MacAddress(aceEth.getDestinationMacAddressMask().getValue()));
-        }
-
-        //MatchUtils.createInPortMatch(matchBuilder, Long.getLong(dpId), Long.getLong(matches.getInputInterface()));
-        return matchBuilder;
-    }
-
-    @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());
-        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();
         }
+        return null;
     }
 
-    protected void removeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
-        mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder));
-    }
-
-    private String getDpid(Node node) {
-        long dpid = southbound.getDataPathId(node);
-        if (dpid == 0) {
-            LOG.warn("getDpid: DPID could not be found for node: {}", node.getNodeId().getValue());
-        }
-        return String.valueOf(dpid);
-    }
-
-    private static InstanceIdentifier<Flow> createFlowPath(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
-        return InstanceIdentifier.builder(Nodes.class)
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
-                        nodeBuilder.getKey())
-                .augmentation(FlowCapableNode.class)
-                .child(Table.class, new TableKey(flowBuilder.getTableId()))
-                .child(Flow.class, flowBuilder.getKey()).build();
-    }
-
-    private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>
-        createNodePath(NodeBuilder nodeBuilder) {
-        return InstanceIdentifier.builder(Nodes.class)
-                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
-                        nodeBuilder.getKey()).build();
-    }
-
-    private NodeBuilder createNodeBuilder(String nodeId) {
-        NodeBuilder builder = new NodeBuilder();
-        builder.setId(new NodeId(nodeId));
-        builder.setKey(new NodeKey(builder.getId()));
-        return builder;
-    }
-
-    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();
+    public void handleLocalInPort(long dpidLong, String segmentationId, Long inPort,
+                                  short writeTable, short goToTableId, boolean write) {
+        sfcClassifier.programLocalInPort(dpidLong, segmentationId, inPort, writeTable, goToTableId, write);
     }
 
     private void setDependencies(ServiceReference serviceReference) {
index 5265235e0761c1bbccac2389644005193bec9842..e63461d3349292c72809399226cdf754a40a4deb 100644 (file)
@@ -170,6 +170,10 @@ public class NshUtils {
         this.nshMetaC2 = nshMetaC2;
     }
 
+    public static Long convertIpAddressToLong(Ipv4Address ipv4Address) {
+        return (InetAddresses.coerceToInteger(InetAddresses.forString(ipv4Address.getValue()))) & 0xFFFFFFFFL;
+    }
+
     /* (non-Javadoc)
      * @see java.lang.Object#toString()
      */
@@ -178,98 +182,4 @@ public class NshUtils {
         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());
-    }
 }
diff --git a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/SfcClassifier.java b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/openflow13/SfcClassifier.java
new file mode 100644 (file)
index 0000000..7a5365b
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright © 2015 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.ovsdb.openstack.netvirt.sfc.openflow13;
+
+import com.google.common.collect.Lists;
+import java.math.BigInteger;
+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.ovsdb.openstack.netvirt.api.Southbound;
+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.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.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.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;
+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.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;
+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.openflowjava.nx.match.rev140421.NxmNxReg;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SfcClassifier {
+    private static final Logger LOG = LoggerFactory.getLogger(SfcClassifier.class);
+    private DataBroker dataBroker;
+    private Southbound southbound;
+    private MdsalUtils mdsalUtils;
+    public final static long REG_VALUE_FROM_LOCAL = 0x1L;
+    public final static long REG_VALUE_FROM_REMOTE = 0x2L;
+    public static final Class<? extends NxmNxReg> REG_FIELD = NxmNxReg0.class;
+    private static final String OPENFLOW = "openflow:";
+
+    SfcClassifier(DataBroker dataBroker, Southbound southbound, MdsalUtils mdsalUtils) {
+        this.dataBroker = dataBroker;
+        this.southbound = southbound;
+        this.mdsalUtils = mdsalUtils;
+    }
+
+    /*
+     * (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"
+     */
+    public void programSfcClassiferFlows(Long dpidLong, short writeTable, String ruleName, Matches match,
+                                         NshUtils nshHeader, long tunnelOfPort, boolean write) {
+        String nodeName = OPENFLOW + dpidLong;
+        NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        MatchBuilder matchBuilder = buildMatch(match);
+        flowBuilder.setMatch(matchBuilder.build());
+
+        String flowId = "sfcClass_" + ruleName + "_" + nshHeader.getNshNsp();
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setBarrier(true);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+
+        if (write) {
+            List<Action> actionList = getNshAction(nshHeader);
+            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());
+
+            InstructionUtils.createOutputPortInstructions(ib, dpidLong, tunnelOfPort);
+            ib.setOrder(1);
+            ib.setKey(new InstructionKey(1));
+            instructions.add(ib.build());
+
+            InstructionsBuilder isb = new InstructionsBuilder();
+            isb.setInstruction(instructions);
+            flowBuilder.setInstructions(isb.build());
+            writeFlow(flowBuilder, nodeBuilder);
+        } else {
+            removeFlow(flowBuilder, nodeBuilder);
+        }
+    }
+
+    private List<Action> getNshAction(NshUtils header) {
+        // Build the Actions to Add the NSH Header
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC1Load =
+                ActionUtils.nxLoadNshc1RegAction(header.getNshMetaC1());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nshC2Load =
+                ActionUtils.nxLoadNshc2RegAction(header.getNshMetaC2());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nspLoad =
+                ActionUtils.nxSetNspAction(header.getNshNsp());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nsiLoad =
+                ActionUtils.nxSetNsiAction(header.getNshNsi());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunVnid =
+                ActionUtils.nxLoadTunIdAction(BigInteger.valueOf(header.getNshNsp()), false);
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunDest =
+                ActionUtils.nxLoadTunIPv4Action(header.getNshTunIpDst().getValue(), false);
+
+        int count = 0;
+        List<Action> actionList = Lists.newArrayList();
+        actionList.add(new ActionBuilder().setOrder(count++).setAction(nshC1Load).build());
+        actionList.add(new ActionBuilder().setOrder(count++).setAction(nshC2Load).build());
+        actionList.add(new ActionBuilder().setOrder(count++).setAction(nspLoad).build());
+        actionList.add(new ActionBuilder().setOrder(count++).setAction(nsiLoad).build());
+        actionList.add(new ActionBuilder().setOrder(count++).setAction(loadChainTunDest).build());
+        actionList.add(new ActionBuilder().setOrder(count++).setAction(loadChainTunVnid).build());
+        return actionList;
+    }
+
+    public void programLocalInPort(Long dpidLong, String segmentationId, Long inPort,
+                                   short writeTable, short goToTableId, boolean write) {
+        String nodeName = OPENFLOW + dpidLong;
+
+        MatchBuilder matchBuilder = new MatchBuilder();
+        NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
+        FlowBuilder flowBuilder = new FlowBuilder();
+
+        flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
+        String flowId = "sfcIngress_" + segmentationId + "_" + inPort;
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setStrict(true);
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+
+        if (write) {
+            InstructionBuilder ib = new InstructionBuilder();
+            InstructionsBuilder isb = new InstructionsBuilder();
+            List<Instruction> instructions = Lists.newArrayList();
+
+            InstructionUtils.createSetTunnelIdInstructions(ib, new BigInteger(segmentationId));
+            ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
+            List<Action> actionList = aac.getApplyActions().getAction();
+
+            // TODO: Mark the packets as sfc classified?
+
+            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(1);
+            ib.setKey(new InstructionKey(1));
+            instructions.add(ib.build());
+
+            isb.setInstruction(instructions);
+            flowBuilder.setInstructions(isb.build());
+            writeFlow(flowBuilder, nodeBuilder);
+        } else {
+            removeFlow(flowBuilder, nodeBuilder);
+        }
+    }
+
+/*
+    public InstructionsBuilder buildActions(String ruleName, Actions actions, String datapathId) {
+        InstructionBuilder ib = new InstructionBuilder();
+
+        if (actions.getPacketHandling() instanceof Deny) {
+            InstructionUtils.createDropInstructions(ib);
+        } else if (actions.getPacketHandling() instanceof Permit) {
+            //Permit actPermit = (Permit) actions.getPacketHandling();
+        } else {
+            InstructionUtils.createDropInstructions(ib);
+        }
+
+        ib.setOrder(0);
+        ib.setKey(new InstructionKey(0));
+        // Instructions List Stores Individual Instructions
+        List<Instruction> instructions = Lists.newArrayList();
+        instructions.add(ib.build());
+
+        // Call the InstructionBuilder Methods Containing Actions
+        ib = this.getMutablePipelineInstructionBuilder();
+        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);
+        return isb;
+    }*/
+
+    public MatchBuilder buildMatch(Matches matches) {
+        MatchBuilder matchBuilder = new MatchBuilder();
+
+        if (matches.getAceType() instanceof AceIp) {
+            AceIp aceIp = (AceIp)matches.getAceType();
+            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.addLayer4Match(matchBuilder, aceIp.getProtocol().intValue(), 0,
+                        aceIp.getDestinationPortRange().getLowerPort().getValue().intValue());
+            }
+        } else if (matches.getAceType() instanceof AceEth) {
+            AceEth aceEth = (AceEth) matches.getAceType();
+            MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(aceEth.getSourceMacAddress().getValue()));
+            MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(aceEth.getDestinationMacAddress().getValue()),
+                    new MacAddress(aceEth.getDestinationMacAddressMask().getValue()));
+        }
+
+        return matchBuilder;
+    }
+
+    protected void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+        LOG.debug("writeFlow: flowBuilder: {}, nodeBuilder: {}", flowBuilder.build(), nodeBuilder.build());
+        mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, createNodePath(nodeBuilder), nodeBuilder.build());
+        mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder),
+                flowBuilder.build());
+    }
+
+    /*private 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);
+        modification.put(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder),
+                flowBuilder.build(), true);
+
+        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) {
+        mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, createFlowPath(flowBuilder, nodeBuilder));
+    }
+
+    private NodeBuilder createNodeBuilder(String nodeId) {
+        NodeBuilder builder = new NodeBuilder();
+        builder.setId(new NodeId(nodeId));
+        builder.setKey(new NodeKey(builder.getId()));
+        return builder;
+    }
+
+    private static InstanceIdentifier<Flow> createFlowPath(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+        return InstanceIdentifier.builder(Nodes.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+                        nodeBuilder.getKey())
+                .augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey(flowBuilder.getTableId()))
+                .child(Flow.class, flowBuilder.getKey()).build();
+    }
+
+    private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>
+    createNodePath(NodeBuilder nodeBuilder) {
+        return InstanceIdentifier.builder(Nodes.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
+                        nodeBuilder.getKey()).build();
+    }
+}
index 7469dff49118f9db6076a74f1e30aee94fe83669..12363f13cf2ada6da3f92ab3365f83a25ecb1e9f 100644 (file)
@@ -36,20 +36,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeCon
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
 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.DstNxArpShaCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxArpThaCaseBuilder;
-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.dst.choice.grouping.dst.choice.DstOfArpOpCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpSpaCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfArpTpaCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstOfEthDstCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.*;
 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.group.buckets.bucket.action.action.NxActionRegMoveNodesNodeGroupBucketsBucketActionsCaseBuilder;
-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.NxActionRegMoveNodesNodeTableFlowApplyActionsCaseBuilder;
+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.*;
 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;
@@ -58,17 +48,23 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMove;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMoveBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.SrcBuilder;
+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.src.choice.grouping.SrcChoice;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxArpShaCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIdCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIpv4DstCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfArpSpaCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfEthSrcCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxHashFields;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxMpAlgorithm;
-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.NxActionMultipathNodesNodeTableFlowApplyActionsCaseBuilder;
-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.NxActionResubmitNodesNodeTableFlowApplyActionsCaseBuilder;
-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.multipath.grouping.NxMultipath;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.multipath.grouping.NxMultipathBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.resubmit.grouping.NxResubmit;
@@ -333,15 +329,49 @@ public final class ActionUtils {
         return new NxActionSetNspNodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNsp(r).build();
     }
 
-    public static Action nxSetNsiAction(Short nsp) {
+    public static Action nxSetNsiAction(Short nsi) {
         NxSetNsiBuilder builder = new NxSetNsiBuilder();
-        if (nsp != null) {
-            builder.setNsi(nsp);
+        if (nsi != null) {
+            builder.setNsi(nsi);
         }
         NxSetNsi r = builder.build();
         return new NxActionSetNsiNodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNsi(r).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();
+    }
+
+    public static Action nxMoveRegTunDstToNshc1() {
+        return nxMoveRegAction(new SrcNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),
+                new DstNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(), 31, false);
+    }
+
+    public static Action nxMoveTunIdtoNshc2() {
+        return nxMoveRegAction(new SrcNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(),
+                new DstNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(), 31, false);
+    }
+
+    public static Action nxLoadTunIdAction(BigInteger tunnelId, boolean groupBucket) {
+        return nxLoadRegAction(new DstNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(), tunnelId, 31, groupBucket);
+    }
+
     public static Action nxMultipathAction(OfjNxHashFields fields, Integer basis,
             OfjNxMpAlgorithm algorithm, Integer maxLink, Long arg, DstChoice dstChoice,
             Integer start, Integer end) {