Merge "Bug 4996 - Wrong flows when using SFC coexistence"
authorSam Hague <shague@redhat.com>
Tue, 19 Jan 2016 00:40:04 +0000 (00:40 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 19 Jan 2016 00:40:04 +0000 (00:40 +0000)
15 files changed:
openstack/net-virt-providers/pom.xml
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-classifier.yang
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/INetvirtSfcOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcProvider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/RspListener.java [new file with mode: 0644]
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/SfcUtils.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/standalone/openflow13/NetvirtSfcStandaloneOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/NetvirtSfcWorkaroundOF13Provider.java
openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/workaround/services/SfcClassifierService.java
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/NetvirtSfcIT.java
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/AbstractUtils.java
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/ClassifierUtils.java
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/NetvirtConfigUtils.java [new file with mode: 0644]
openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/SfcConfigUtils.java [new file with mode: 0644]

index fc101e3ee235a702eb67af2fcd4b80b0a83d61bd..6b51fe93171185835afcce47a88fcbc8cbf2261b 100644 (file)
@@ -201,7 +201,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
             <Embed-Transitive>true</Embed-Transitive>
             <Export-Package>
               org.opendaylight.ovsdb.openstack.netvirt.providers,
-              org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13
+              org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13,
+              org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109
             </Export-Package>
           </instructions>
         </configuration>
index b0b84209e33310883fa56df11458d8355d6261c5..ce30c0136615750e9717664f250ec94e0ac29f27 100644 (file)
@@ -368,7 +368,7 @@ public class ClassifierService extends AbstractServiceInstance implements Classi
         FlowBuilder flowBuilder = new FlowBuilder();
         String flowName = "TableOffset_" + getTable();
         FlowUtils.initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable())
-                .setPriority(0);
+                .setPriority(6);
 
         MatchBuilder matchBuilder = new MatchBuilder();
         flowBuilder.setMatch(matchBuilder.build());
index 5e01309128afde1990aa54d2e891ba0da8875c7a..fa2067d3550ff67031e6dd577d87930c9f571773 100644 (file)
@@ -12,7 +12,7 @@ module netvirt-sfc-classifier {
 
     container classifiers {
         description "Classifier container which represents the ACL being applied,
-                     atachment point and the associated chain";
+                     attachment point and the associated chain";
 
         list classifier {
             description "A list of SFC classifiers";
index 1853f8a4daee1746cd4e6f76b1c2c4bc4a41bbc3..984ac47ee0bacff54e354670bedc503cdbe959cd 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.ovsdb.openstack.netvirt.sfc;
 
+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.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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.bridges.Bridge;
@@ -41,7 +42,8 @@ public interface INetvirtSfcOF13Provider {
 
     void addClassifierRules(Acl acl);
     void removeClassifierRules(Acl acl);
-
     void setSfcClassifierService(ISfcClassifierService sfcClassifierService);
     public void setDependencies(ServiceReference serviceReference);
+    void updateRsp(RenderedServicePath change);
+    void removeRsp(RenderedServicePath change);
 }
index a77b8cf560f795bb44a5567279ec320160569cee..7b7c8baf2281d054e91794bdac3dfadd553bcb92 100644 (file)
@@ -30,6 +30,7 @@ public class NetvirtSfcProvider implements BindingAwareProvider, AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcProvider.class);
     private NetvirtSfcAclListener aclListener;
     private NetvirtSfcClassifierListener classifierListener;
+    private RspListener rspListener;
 
     public void setOf13Provider(String of13Provider) {
         LOG.info("of13Provider is: {}", of13Provider);
@@ -67,6 +68,7 @@ public class NetvirtSfcProvider implements BindingAwareProvider, AutoCloseable {
         }
         aclListener = new NetvirtSfcAclListener(provider, dataBroker);
         classifierListener = new NetvirtSfcClassifierListener(provider, dataBroker);
+        rspListener = new RspListener(provider, dataBroker);
 
         addToPipeline(provider);
         provider.setDependencies(null);
diff --git a/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/RspListener.java b/openstack/net-virt-sfc/impl/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/RspListener.java
new file mode 100644 (file)
index 0000000..f238f42
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.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.paths.RenderedServicePath;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Data tree listener for {@link RenderedServicePath}
+ */
+public class RspListener extends AbstractDataTreeListener<RenderedServicePath> {
+    private static final Logger LOG = LoggerFactory.getLogger(RspListener.class);
+
+    public RspListener(final INetvirtSfcOF13Provider provider, final DataBroker db) {
+        super(provider, RenderedServicePath.class);
+        Preconditions.checkNotNull(db, "DataBroker can not be null!");
+
+        registrationListener(db);
+    }
+
+    public InstanceIdentifier<RenderedServicePath> getRspIid() {
+        return InstanceIdentifier.create(RenderedServicePaths.class).child(RenderedServicePath.class);
+    }
+
+    private void registrationListener(final DataBroker db) {
+        final DataTreeIdentifier<RenderedServicePath> treeId =
+                new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getRspIid());
+        try {
+            LOG.info("Registering Data Change Listener for NetvirtSfc RenderedServicePath configuration.");
+            ListenerRegistration<RspListener> listenerRegistration = db.registerDataTreeChangeListener(treeId, this);
+        } catch (final Exception e) {
+            LOG.warn("Netvirt RenderedServicePath DataChange listener registration failed!");
+            throw new IllegalStateException("NetvirtSfcAccessListListener startup failed! System needs restart.", e);
+        }
+    }
+
+    @Override
+    public void remove(InstanceIdentifier<RenderedServicePath> identifier, RenderedServicePath change) {
+        Preconditions.checkNotNull(change, "Object can not be null!");
+        LOG.debug("remove RenderedServicePath iid = {}, change = {}", identifier, change);
+        provider.removeRsp(change);
+    }
+
+    @Override
+    public void update(InstanceIdentifier<RenderedServicePath> identifier, RenderedServicePath original,
+                       RenderedServicePath change) {
+        Preconditions.checkNotNull(change, "Object can not be null!");
+        LOG.debug("Update RenderedServicePath iid = {}, change = {}", identifier, change);
+        //provider.addClassifierRules(update);
+    }
+
+    @Override
+    public void add(InstanceIdentifier<RenderedServicePath> identifier, RenderedServicePath change) {
+        Preconditions.checkNotNull(change, "Object can not be null!");
+        LOG.debug("Add RenderedServicePath iid = {}, change = {}", identifier, change);
+    }
+
+    @Override
+    public void close() throws Exception {
+
+    }
+}
index 40b8172393e41608418dae976913283d6b736b11..ccd8832cf385f26eeb717599e8cfeda9bcdf9324 100644 (file)
@@ -8,8 +8,10 @@
 
 package org.opendaylight.ovsdb.openstack.netvirt.sfc;
 
+import java.util.List;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.sfc.provider.api.SfcProviderAclAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServiceFunctionAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
@@ -24,8 +26,13 @@ import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev1407
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Ip;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
+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.AccessListEntries;
+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.inet.types.rev100924.IpAddress;
 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.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;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -76,12 +83,12 @@ public class SfcUtils {
         return rspFound;
     }
 
-    public ServiceFunctionPath getSfp(String redirectSfc) {
+    public ServiceFunctionPath getSfp(String sfcName) {
         ServiceFunctionPath sfpFound = null;
         ServiceFunctionPaths sfps = SfcProviderServicePathAPI.readAllServiceFunctionPaths();
         if (sfps != null) {
             for (ServiceFunctionPath sfp: sfps.getServiceFunctionPath()) {
-                if (sfp.getServiceChainName().getValue().equalsIgnoreCase(redirectSfc)) {
+                if (sfp.getServiceChainName().getValue().equalsIgnoreCase(sfcName)) {
                     sfpFound = sfp;
                 }
             }
@@ -89,6 +96,39 @@ public class SfcUtils {
         return sfpFound;
     }
 
+    private AccessLists readAccessLists() {
+        InstanceIdentifier<AccessLists> path = InstanceIdentifier.create(AccessLists.class);
+        return mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
+    }
+
+    public Ace getAce(String name) {
+        Ace aceFound = null;
+        AccessLists accessLists = readAccessLists();
+        if (accessLists != null) {
+            List<Acl> acls = accessLists.getAcl();
+            if (acls != null) {
+                for (Acl acl :acls) {
+                    AccessListEntries accessListEntries = acl.getAccessListEntries();
+                    if (accessListEntries != null) {
+                        List<Ace> aces = accessListEntries.getAce();
+                        for (Ace ace : aces) {
+                            RedirectToSfc sfcRedirect = ace.getActions().getAugmentation(RedirectToSfc.class);
+                            if ((sfcRedirect != null && sfcRedirect.getRspName().equals(name)) ||
+                                    (sfcRedirect != null && sfcRedirect.getSfcName().equals(name)) ||
+                                    (sfcRedirect != null && sfcRedirect.getSfpName().equals(name))) {
+                                aceFound = ace;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        LOG.info("getAce: {}", aceFound);
+        return aceFound;
+    }
+
     public IpAddress getSfIpAddress(String sfname) {
         ServiceFunction serviceFunction =
                 SfcProviderServiceFunctionAPI.readServiceFunction(SfName.getDefaultInstance(sfname));
index 77ec178f65f50b943b8b98c53a8c5e1d588e3c64..4f79f3f86aa0b0ecccc91d65eb9f046933ad5c5f 100644 (file)
@@ -450,4 +450,13 @@ public class NetvirtSfcStandaloneOF13Provider implements INetvirtSfcOF13Provider
         nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
         southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
     }
+
+    @Override
+    public void removeRsp(RenderedServicePath change) {
+
+    }
+    @Override
+    public void updateRsp(RenderedServicePath change) {
+
+    }
 }
index 43f0e4a1774f79766ef1d60c08f72bf8cc3b0ac5..e8123401617153c3267734006555387bcc058048 100644 (file)
@@ -118,7 +118,7 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
 
     private void processAclEntry(Ace entry) {
         Matches matches = entry.getMatches();
-        Preconditions.checkNotNull(matches, "Input bridges cannot be NULL!");
+        Preconditions.checkNotNull(matches, "ACL Entry cannot be null!");
 
         RenderedServicePath rsp = getRenderedServicePath(entry);
         if (rsp == null) {
@@ -129,8 +129,19 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
         handleRenderedServicePath(rsp, entry);
     }
 
-    private void handleRenderedServicePath(RenderedServicePath rsp, Ace entry) {
+    private void handleRenderedServicePath(RenderedServicePath rsp) {
         LOG.info("handleRenderedServicePath: RSP: {}", rsp);
+        Ace entry = getAceFromRenderedServicePath(rsp);
+        if (entry == null) {
+            LOG.warn("handleRenderedServicePath: failed to get acl entry");
+            return;
+        }
+
+        handleRenderedServicePath(rsp, entry);
+    }
+
+    private void handleRenderedServicePath(RenderedServicePath rsp, Ace entry) {
+        LOG.info("handleRenderedServicePath: RSP: {}, Ace: {}", rsp, entry);
 
         Matches matches = entry.getMatches();
         if (matches == null) {
@@ -214,19 +225,19 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
 
         if (hop == firstHop) {
             LOG.info("handleSff: first hop processing {} - {}",
-                    bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+                    bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
             NshUtils nshHeader = new NshUtils();
             nshHeader.setNshNsp(rsp.getPathId());
             nshHeader.setNshNsi(firstHop.getServiceIndex());
             if (isSffOnBridge(bridgeNode, serviceFunctionForwarder)) {
                 LOG.info("handleSff: sff and bridge are the same: {} - {}, skipping first sff",
-                        bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+                        bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
                 Ip ip = sfcUtils.getSfIp(serviceFunction);
                 nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
                 nshHeader.setNshTunUdpPort(ip.getPort());
             } else {
                 LOG.info("handleSff: sff and bridge are not the same: {} - {}, sending to first sff",
-                        bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+                        bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
                 Ip ip = sfcUtils.getSffIp(serviceFunctionForwarder);
                 nshHeader.setNshTunIpDst(ip.getIp().getIpv4Address());
                 nshHeader.setNshTunUdpPort(ip.getPort());
@@ -235,25 +246,28 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
                     nshHeader, vxGpeOfPort, true);
         } else if (hop == lastHop) {
             LOG.info("handleSff: last hop processing {} - {}",
-                    bridgeNode.getNodeId(), serviceFunctionForwarder.getName());
+                    bridgeNode.getNodeId().getValue(), serviceFunctionForwarder.getName().getValue());
             short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
             String sfDplName = sfcUtils.getSfDplName(serviceFunction);
             long sfOfPort = getSfPort(bridgeNode, sfDplName);
+            // TODO: Coexistence: SFC flows should take this using new egressTable REST
             sfcClassifierService.programEgressClassifier(dataPathId, vxGpeOfPort, rsp.getPathId(),
                     lastServiceindex, sfOfPort, 0, true);
+            // TODO: Coexistence: This flow should like like one above, change port, add reg0=1, resubmit
             sfcClassifierService.programEgressClassifierBypass(dataPathId, vxGpeOfPort, rsp.getPathId(),
                     lastServiceindex, sfOfPort, 0, true);
         } else {
             // add typical sff flows
         }
 
-        sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
+        // TODO: Coexistence: SFC flows should take this using new tableOffset REST
+        //sfcClassifierService.programSfcTable(dataPathId, vxGpeOfPort, SFC_TABLE, true);
     }
 
     void handleSf(Node bridgeNode, ServiceFunction serviceFunction) {
         if (isSfOnBridge(bridgeNode, serviceFunction)) {
             LOG.info("handleSf: sf and bridge are on the same node: {} - {}, adding workaround and arp",
-                    bridgeNode.getNodeId(), serviceFunction.getName());
+                    bridgeNode.getNodeId().getValue(), serviceFunction.getName().getValue());
             long dataPathId = southbound.getDataPathId(bridgeNode);
             Ip ip = sfcUtils.getSfIp(serviceFunction);
             String sfIpAddr = String.valueOf(ip.getIp().getValue());
@@ -266,12 +280,13 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
                 return;
             }
             //should be sffdplport, but they should all be the same 6633/4790
-            sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, true);
-            sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplName, true);
+            // TODO: Coexistence: SFC flows should take this using new sf dpl augmentation
+            //sfcClassifierService.program_sfEgress(dataPathId, sfIpPort, true);
+            //sfcClassifierService.program_sfIngress(dataPathId, sfIpPort, sfOfPort, sfIpAddr, sfDplName, true);
             sfcClassifierService.programStaticArpEntry(dataPathId, 0L, sfMac, sfIpAddr, true);
         } else {
             LOG.info("handleSf: sf and bridge are not on the same node: {} - {}, do nothing",
-            bridgeNode.getNodeId(), serviceFunction.getName());
+                    bridgeNode.getNodeId().getValue(), serviceFunction.getName().getValue());
         }
     }
 
@@ -282,11 +297,15 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
         if (ovsdbNode != null) {
             localIp = getLocalip(ovsdbNode);
         }
+        LOG.info("isSffOnBridge: {}: {}, localIp: {}, sff ip: {}",
+                bridgeNode.getNodeId().getValue(),
+                localIp.equals(String.valueOf(ip.getIp().getValue())),
+                localIp, ip.getIp().getValue());
         return localIp.equals(String.valueOf(ip.getIp().getValue()));
     }
 
     private String getLocalip(Node ovsdbNode) {
-        Preconditions.checkNotNull("The ovsdbNode was null", ovsdbNode);
+        Preconditions.checkNotNull(ovsdbNode, "The ovsdbNode was null");
         String localIp = null;
         if (ovsdbNode != null) {
             OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
@@ -304,9 +323,21 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
     private boolean isSfOnBridge(Node bridgeNode, ServiceFunction serviceFunction) {
         String sfDplName = sfcUtils.getSfDplName(serviceFunction);
         long sfOfPort = getSfPort(bridgeNode, sfDplName);
+        LOG.info("isSfOnBridge: {}: {}, sfOfPort: {}", bridgeNode.getNodeId().getValue(), sfOfPort != 0L, sfOfPort);
         return sfOfPort != 0L;
     }
 
+    private Ace getAceFromRenderedServicePath(RenderedServicePath rsp) {
+        Preconditions.checkNotNull(rsp, "RSP cannot be null");
+        Ace ace = null;
+        String rspName = rsp.getName().getValue();
+        String rspNameSuffix = "_rsp";
+        String sfcName = rspName.substring(0, rspName.length() - rspNameSuffix.length());
+        ace = sfcUtils.getAce(sfcName);
+
+        return ace;
+    }
+
     private RenderedServicePath getRenderedServicePath (Ace entry) {
         RenderedServicePath rsp = null;
         RedirectToSfc sfcRedirect = entry.getActions().getAugmentation(RedirectToSfc.class);
@@ -425,6 +456,16 @@ public class NetvirtSfcWorkaroundOF13Provider implements INetvirtSfcOF13Provider
         return mac;
     }
 
+    @Override
+    public void removeRsp(RenderedServicePath change) {
+        LOG.info("removeRsp not implemented yet");
+    }
+
+    @Override
+    public void updateRsp(RenderedServicePath change) {
+        LOG.info("updateRsp not implemented yet");
+    }
+
     @Override
     public void setDependencies(ServiceReference serviceReference) {
         nodeCacheManager = (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
index 1f06202b07e907733a22d8eeceda7f6bf8d77160..e96b9006bf2f4c6411ac33cc146ab915e9932780 100644 (file)
@@ -72,6 +72,11 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         return new BigInteger(cookieString, 16);
     }
 
+    private BigInteger getCookie(FlowID flowID, short nsp, short nsi) {
+        String cookieString = String.format("1110%02d%03d%03d0%03d", flowID.value, 0, nsp, nsi);
+        return new BigInteger(cookieString, 16);
+    }
+
     public SfcClassifierService(Service service) {
         super(service);
     }
@@ -88,30 +93,35 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
     @Override
     public void setDependencies(Object impl) {}
 
+    private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table, FlowID flowID) {
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, table)
+                .setCookie(new FlowCookie(getCookie(flowID)))
+                .setCookieMask(new FlowCookie(getCookie(flowID)));
+        return flowBuilder;
+    }
+
+    private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table, FlowID flowID,
+                                        short nsp, short nsi) {
+        FlowUtils.initFlowBuilder(flowBuilder, flowName, table)
+                .setCookie(new FlowCookie(getCookie(flowID, nsp, nsi)))
+                .setCookieMask(new FlowCookie(getCookie(flowID, nsp, nsi)));
+        return flowBuilder;
+    }
+
     @Override
     public void programIngressClassifier(long dataPathId, String ruleName, Matches matches,
                                          NshUtils nshHeader, long vxGpeOfPort, boolean write) {
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
         FlowBuilder flowBuilder = new FlowBuilder();
+        String flowName = "sfcIngressClass_" + ruleName;// + "_" + nshHeader.getNshNsp();
+        initFlowBuilder(flowBuilder, flowName, getTable(), FlowID.FLOW_INGRESSCLASS,
+                (short)nshHeader.getNshNsp(), nshHeader.getNshNsi());
 
         MatchBuilder matchBuilder = buildMatch(matches);
-        MatchUtils.addNxRegMatch(matchBuilder,
-                MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
         MatchUtils.addNxRegMatch(matchBuilder,
                 MatchUtils.RegMatch.of(FlowUtils.REG_FIELD, FlowUtils.REG_VALUE_FROM_LOCAL));
         flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "sfcIngressClass_" + ruleName;// + "_" + nshHeader.getNshNsp();
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(getTable());
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_INGRESSCLASS)));
-
         if (write) {
             ActionBuilder ab = new ActionBuilder();
             List<Action> actionList = new ArrayList<>();
@@ -151,24 +161,14 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
     public void programSfcTable(long dataPathId, long vxGpeOfPort, short goToTableId, boolean write) {
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
         FlowBuilder flowBuilder = new FlowBuilder();
+        String flowName = "sfcTable_" + vxGpeOfPort;
+        initFlowBuilder(flowBuilder, flowName, getTable(Service.CLASSIFIER), FlowID.FLOW_SFCTABLE)
+                .setPriority(1000);
 
         MatchBuilder matchBuilder = new MatchBuilder();
         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
         flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "sfcTable_" + vxGpeOfPort;
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(getTable(Service.CLASSIFIER));
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
-        flowBuilder.setPriority(1000);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_SFCTABLE)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_SFCTABLE)));
-
         if (write) {
             InstructionsBuilder isb = new InstructionsBuilder();
             List<Instruction> instructions = Lists.newArrayList();
@@ -191,6 +191,9 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
                                          int tunnelOfPort, int tunnelId, short gotoTableId, boolean write) {
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
         FlowBuilder flowBuilder = new FlowBuilder();
+        String flowName = "sfcEgressClass1_" + vxGpeOfPort;
+        initFlowBuilder(flowBuilder, flowName, getTable(Service.CLASSIFIER), FlowID.FLOW_EGRESSCLASSUNUSED,
+                (short)nsp, nsi);
 
         MatchBuilder matchBuilder = new MatchBuilder();
         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
@@ -198,18 +201,6 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         MatchUtils.addNxNsiMatch(matchBuilder, nsi);
         flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "sfcEgressClass1_" + vxGpeOfPort;
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(getTable(Service.CLASSIFIER));
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSUNUSED)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASSUNUSED)));
-
         if (write) {
             InstructionsBuilder isb = new InstructionsBuilder();
             List<Instruction> instructions = Lists.newArrayList();
@@ -232,6 +223,9 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
                                         long sfOfPort, int tunnelId, boolean write) {
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
         FlowBuilder flowBuilder = new FlowBuilder();
+        String flowName = "sfcEgressClass_" + nsp + "_" + + nsi + "_"  + vxGpeOfPort;
+        initFlowBuilder(flowBuilder, flowName, getTable(Service.SFC_CLASSIFIER), FlowID.FLOW_EGRESSCLASS,
+                (short)nsp, nsi);
 
         MatchBuilder matchBuilder = new MatchBuilder();
         MatchUtils.createInPortMatch(matchBuilder, dataPathId, vxGpeOfPort);
@@ -239,18 +233,6 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         MatchUtils.addNxNsiMatch(matchBuilder, nsi);
         flowBuilder.setMatch(matchBuilder.build());
 
-        String flowId = "sfcEgressClass_" + nsp + "_" + + nsi + "_"  + vxGpeOfPort;
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(getTable(Service.CLASSIFIER));
-        flowBuilder.setKey(key);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
-        flowBuilder.setCookie(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASS)));
-        flowBuilder.setCookieMask(new FlowCookie(getCookie(FlowID.FLOW_EGRESSCLASS)));
-
         if (write) {
             InstructionsBuilder isb = new InstructionsBuilder();
             List<Instruction> instructions = Lists.newArrayList();
@@ -270,7 +252,7 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
             ab.setKey(new ActionKey(actionList.size()));
             actionList.add(ab.build());
 
-            ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, Service.CLASSIFIER.getTable()));
+            ab.setAction(ActionUtils.nxResubmitAction((int)sfOfPort, getTable(Service.CLASSIFIER)));
             ab.setOrder(actionList.size());
             ab.setKey(new ActionKey(actionList.size()));
             actionList.add(ab.build());
@@ -292,21 +274,15 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         }
     }
 
-    private FlowBuilder initFlowBuilder(FlowBuilder flowBuilder, String flowName, short table, FlowID flowID) {
-        FlowUtils.initFlowBuilder(flowBuilder, flowName, table)
-                .setCookie(new FlowCookie(getCookie(flowID)))
-                .setCookieMask(new FlowCookie(getCookie(flowID)));
-        return flowBuilder;
-    }
-
     @Override
     public void programEgressClassifierBypass(long dataPathId, long vxGpeOfPort, long nsp, short nsi,
                                               long sfOfPort, int tunnelId, boolean write) {
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
         FlowBuilder flowBuilder = new FlowBuilder();
         String flowName = "sfcEgressClassBypass_" + nsp + "_" + + nsi + "_"  + sfOfPort;
-        initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(),
-                FlowID.FLOW_EGRESSCLASSBYPASS).setPriority(40000);
+        initFlowBuilder(flowBuilder, flowName, getTable(Service.CLASSIFIER),
+                FlowID.FLOW_EGRESSCLASSBYPASS, (short)nsp, nsi)
+                .setPriority(40000);
 
         MatchBuilder matchBuilder = new MatchBuilder();
         MatchUtils.createInPortMatch(matchBuilder, dataPathId, sfOfPort);
@@ -406,7 +382,8 @@ public class SfcClassifierService extends AbstractServiceInstance implements Con
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dataPathId);
         FlowBuilder flowBuilder = new FlowBuilder();
         String flowName = "ArpResponder_" + ipAddress;
-        initFlowBuilder(flowBuilder, flowName, Service.CLASSIFIER.getTable(), FlowID.FLOW_SFARP).setPriority(1024);
+        initFlowBuilder(flowBuilder, flowName, getTable(Service.ARP_RESPONDER), FlowID.FLOW_SFARP)
+                .setPriority(1024);
 
         MacAddress macAddress = new MacAddress(macAddressStr);
 
index 771921a7681d9237f55964f32d1c854b9ac522a3..7a215dc2c7e3383d34fb3254ea0282637a40dc5f 100644 (file)
@@ -48,17 +48,24 @@ import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.standalone.openflow13.SfcClassifier;
 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.NetvirtConfigUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionChainUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionForwarderUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionPathUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.ServiceFunctionUtils;
+import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcConfigUtils;
 import org.opendaylight.ovsdb.openstack.netvirt.sfc.utils.SfcUtils;
 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
+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.SftType;
+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.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.sf.rev140701.ServiceFunctions;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
@@ -77,6 +84,8 @@ import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev1407
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfig;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfigBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessListsBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.AclBuilder;
@@ -89,6 +98,8 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
 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.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfigBuilder;
 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.ClassifiersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder;
@@ -133,6 +144,8 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
     private static ServiceFunctionForwarderUtils serviceFunctionForwarderUtils = new ServiceFunctionForwarderUtils();
     private static ServiceFunctionChainUtils serviceFunctionChainUtils = new ServiceFunctionChainUtils();
     private static ServiceFunctionPathUtils serviceFunctionPathUtils = new ServiceFunctionPathUtils();
+    private static SfcConfigUtils sfcConfigUtils = new SfcConfigUtils();
+    private static NetvirtConfigUtils netvirtConfigUtils = new NetvirtConfigUtils();
     private static MdsalUtils mdsalUtils;
     private static AtomicBoolean setup = new AtomicBoolean(false);
     private static SouthboundUtils southboundUtils;
@@ -161,9 +174,11 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
     private static final String SF2NAME = "dpi-72";
     private static final String SF1IP = "10.2.1.1";//"192.168.50.70";//"192.168.120.31";
     private static final String SF2IP = "10.2.1.2";
-    private static final String SF1DPLNAME = "sf1Dpl";
-    private static final String SF2DPLNAME = "sf2Dpl";
-    private static final String SFF1IP = "127.0.0.1"; //"192.168.1.129"
+    private static final String SF1DPLNAME = "sf1";
+    private static final String SF2DPLNAME = "sf2";
+    // Use 192.168.50.70 when running against vagrant vm for workaround testing
+    // "192.168.50.70"; "127.0.0.1"; "192.168.1.129";
+    private static final String SFF1IP = "192.168.1.129";
     private static final String SFF2IP = "192.168.1.129";//"127.0.0.1";
     private static final String SFF1NAME = "sff1";
     private static final String SFF2NAME = "sff2";
@@ -249,6 +264,9 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
                 //editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
                 //        "log4j.logger.org.opendaylight.ovsdb",
                 //        LogLevelOption.LogLevel.TRACE.name()),
+                editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
+                        "log4j.logger.org.opendaylight.ovsdb.library",
+                        LogLevel.INFO.name()),
                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
                         logConfiguration(NetvirtSfcIT.class),
                         LogLevel.INFO.name()),
@@ -409,7 +427,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         SffsBuilder sffsBuilder = classifierUtils.sffsBuilder(new SffsBuilder(), sffBuilder);
         ClassifierBuilder classifierBuilder = classifierUtils.classifierBuilder(new ClassifierBuilder(),
                 "classifierName", ACLNAME, sffsBuilder);
-        ClassifiersBuilder classifiersBuilder = classifierUtils.ClassifiersBuilder(new ClassifiersBuilder(),
+        ClassifiersBuilder classifiersBuilder = classifierUtils.classifiersBuilder(new ClassifiersBuilder(),
                 classifierBuilder);
         LOG.info("Classifiers: {}", classifiersBuilder.build());
         return classifiersBuilder;
@@ -573,6 +591,20 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         return serviceFunctionPathsBuilder;
     }
 
+    private SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder(short tableOffset, short egressTable) {
+        SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder =
+                sfcConfigUtils.sfcOfRendererConfigBuilder(new SfcOfRendererConfigBuilder(), tableOffset, egressTable);
+        LOG.info("SfcOfRendererConfig: {}", sfcOfRendererConfigBuilder.build());
+        return sfcOfRendererConfigBuilder;
+    }
+
+    private NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder(short tableOffset) {
+        NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder =
+                netvirtConfigUtils.netvirtProvidersConfigBuilder(new NetvirtProvidersConfigBuilder(), tableOffset);
+        LOG.info("NetvirtProvidersConfig: {}", netvirtProvidersConfigBuilder.build());
+        return netvirtProvidersConfigBuilder;
+    }
+
     @Test
     public void testSfcModel() throws InterruptedException {
         int timeout = 1000;
@@ -618,6 +650,8 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         String flowId = "DEFAULT_PIPELINE_FLOW_" + Service.SFC_CLASSIFIER.getTable();
         verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
 
+        readwait();
+
         assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
         Thread.sleep(1000);
         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
@@ -635,6 +669,13 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
             LOG.info("testNetvirtSfcAll: skipping test because userSpaceEnabled {}", userSpaceEnabled);
             return;
         }
+
+        short netvirtTableOffset = 1;
+        testModelPut(netvirtProvidersConfigBuilder(netvirtTableOffset), NetvirtProvidersConfig.class);
+        short sfcTableoffset = 150;
+        short egressTable = pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
+        testModelPut(sfcOfRendererConfigBuilder(sfcTableoffset, egressTable), SfcOfRendererConfig.class);
+
         String bridgeName = INTEGRATION_BRIDGE_NAME;
         ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
         assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
@@ -651,15 +692,20 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
         assertNotEquals("datapathId was not found", datapathId, 0);
 
-        String flowId = "DEFAULT_PIPELINE_FLOW_" + Service.SFC_CLASSIFIER.getTable();
+        String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
         verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
 
         Map<String, String> externalIds = Maps.newHashMap();
         externalIds.put("attached-mac", "f6:00:00:0f:00:01");
         southboundUtils.addTerminationPoint(bridgeNode, SF1DPLNAME, "internal", null, externalIds);
+        externalIds.clear();
+        externalIds.put("attached-mac", "f6:00:00:0c:00:01");
         southboundUtils.addTerminationPoint(bridgeNode, "vm1", "internal");
+        externalIds.clear();
+        externalIds.put("attached-mac", "f6:00:00:0c:00:02");
         southboundUtils.addTerminationPoint(bridgeNode, "vm2", "internal");
-        Map<String, String> options = Maps.newHashMap();
+        // SFC will add the SFF dpl port when creating the RSP
+        /*Map<String, String> options = Maps.newHashMap();
         options.put("key", "flow");
         options.put("dst_port", String.valueOf(GPEUDPPORT));
         options.put("remote_ip", "flow");
@@ -671,8 +717,7 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         options.clear();
         options.put("key", "flow");
         options.put("remote_ip", "192.168.120.32");
-        southboundUtils.addTerminationPoint(bridgeNode, "vx", "vxlan", options, null);
-        long vxGpeOfPort = getOFPort(bridgeNode, "vxgpe");
+        southboundUtils.addTerminationPoint(bridgeNode, "vx", "vxlan", options, null);*/
 
         testModelPut(serviceFunctionsBuilder(), ServiceFunctions.class);
         testModelPut(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class);
@@ -682,24 +727,53 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         testModelPut(accessListsBuilder(), AccessLists.class);
         testModelPut(classifiersBuilder(), Classifiers.class);
 
+        long vxGpeOfPort = getOFPort(bridgeNode, "vxgpe");
+        assertNotEquals("vxGpePort was not found", 0, vxGpeOfPort);
+
         readwait();
 
         flowId = "sfcIngressClass_" + "httpRule";
         verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
-        flowId = "sfcTable_" + vxGpeOfPort;
-        verifyFlow(datapathId, flowId, Service.CLASSIFIER);
-        flowId = "sfEgress_" + GPEUDPPORT;
-        verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
-        flowId = "sfIngress_" + GPEUDPPORT + "_" + SF1IP;
-        verifyFlow(datapathId, flowId, Service.CLASSIFIER);
+        // SFC is adding these flows now
+        //flowId = "sfcTable_" + vxGpeOfPort;
+        //verifyFlow(datapathId, flowId, Service.CLASSIFIER);
+        //flowId = "sfEgress_" + GPEUDPPORT;
+        //verifyFlow(datapathId, flowId, Service.SFC_CLASSIFIER);
+        //flowId = "sfIngress_" + GPEUDPPORT + "_" + SF1IP;
+        //verifyFlow(datapathId, flowId, Service.CLASSIFIER);
         flowId = "ArpResponder_" + SF1IP;
-        verifyFlow(datapathId, flowId, Service.CLASSIFIER);
+        verifyFlow(datapathId, flowId, Service.ARP_RESPONDER);
+
+        readwait();
 
         assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
         Thread.sleep(1000);
         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
     }
 
+    // Not used yet
+    private void getSffDplPort(String rspName) {
+        long ofPort = 0;
+        RenderedServicePathKey renderedServicePathKey =
+                new RenderedServicePathKey(RspName.getDefaultInstance(rspName));
+        InstanceIdentifier<RenderedServicePath> path =
+                InstanceIdentifier.create(RenderedServicePaths.class)
+                        .child(RenderedServicePath.class, renderedServicePathKey);
+        RenderedServicePath rsp = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
+        if (rsp == null) {
+            LOG.warn("handleRenderedServicePath: RSP {} has empty hops!!", rsp.getName());
+            return;
+        }
+        List<RenderedServicePathHop> pathHopList = rsp.getRenderedServicePathHop();
+        if (pathHopList.isEmpty()) {
+            LOG.warn("handleRenderedServicePath: RSP {} has empty hops!!", rsp.getName());
+            return;
+        }
+
+        for (RenderedServicePathHop hop : pathHopList) {
+        }
+    }
+
     /**
      * Test the standalone NetvirtSfc implementation
      * NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably.
@@ -803,15 +877,20 @@ public class NetvirtSfcIT extends AbstractMdsalTestBase {
         return flow;
     }
 
-    private void verifyFlow(long datapathId, String flowId, Service service) throws InterruptedException {
+    private void verifyFlow(long datapathId, String flowId, short table) throws InterruptedException {
         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
                 FlowUtils.createNodeBuilder(datapathId);
         FlowBuilder flowBuilder =
-                FlowUtils.initFlowBuilder(new FlowBuilder(), flowId, pipelineOrchestrator.getTable(service));
+                FlowUtils.initFlowBuilder(new FlowBuilder(), flowId, table);
         Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
         assertNotNull("Could not find flow in config: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
         flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
-        assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(), flow);
+        assertNotNull("Could not find flow in operational: " + flowBuilder.build() + "--" + nodeBuilder.build(),
+                flow);
+    }
+
+    private void verifyFlow(long datapathId, String flowId, Service service) throws InterruptedException {
+        verifyFlow(datapathId, flowId, pipelineOrchestrator.getTable(service));
     }
 
     private void readwait() {
index 52585479abf03cb10436bca9541fd26d82adcdc8..3662aaf682ddfb3743860f201bf3e5058295553d 100644 (file)
@@ -1,3 +1,11 @@
+/*
+ * 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.utils;
 
 import java.util.List;
index 54d31dbab720b96ac853517e539cead1c817bed1..1aed97a96d596bba0b282dce835072cb90d1130b 100644 (file)
@@ -38,7 +38,7 @@ public class ClassifierUtils extends AbstractUtils {
                 .setAcl(aclName);
     }
 
-    public ClassifiersBuilder ClassifiersBuilder(ClassifiersBuilder classifiersBuilder,
+    public ClassifiersBuilder classifiersBuilder(ClassifiersBuilder classifiersBuilder,
                                                  ClassifierBuilder classifierBuilder) {
         List<Classifier> classifierList = new ArrayList<>();
         classifierList.add(classifierBuilder.build());
diff --git a/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/NetvirtConfigUtils.java b/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/NetvirtConfigUtils.java
new file mode 100644 (file)
index 0000000..6cb6904
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.utils;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfigBuilder;
+
+public class NetvirtConfigUtils {
+    public NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder(
+            NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder, short tableOffset) {
+        return netvirtProvidersConfigBuilder.setTableOffset(tableOffset);
+    }
+}
diff --git a/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/SfcConfigUtils.java b/openstack/net-virt-sfc/it/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/sfc/utils/SfcConfigUtils.java
new file mode 100644 (file)
index 0000000..9fc74f2
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2016 Red Hat, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.ovsdb.openstack.netvirt.sfc.utils;
+
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfig;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfigBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SfcConfigUtils {
+    public SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder(SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder,
+                                                                 short tableOffset, short egressTable) {
+        return sfcOfRendererConfigBuilder
+                .setSfcOfTableOffset(tableOffset)
+                .setSfcOfAppEgressTableOffset(egressTable);
+    }
+
+    public InstanceIdentifier<SfcOfRendererConfig> getPath() {
+        return InstanceIdentifier.create(SfcOfRendererConfig.class);
+    }
+}