Use directional dpls for openflow rendering 56/66956/11
authorJaime Caamaño Ruiz <[email protected]>
Mon, 8 Jan 2018 22:34:03 +0000 (23:34 +0100)
committerBrady Johnson <[email protected]>
Tue, 30 Jan 2018 22:29:43 +0000 (22:29 +0000)
Change-Id: I36ceff0509d0d33d9e34e6cec4f30df100c3cd06
Signed-off-by: Jaime Caamaño Ruiz <[email protected]>
sfc-genius/src/main/java/org/opendaylight/sfc/genius/util/SfcGeniusDataUtils.java
sfc-genius/src/test/java/org/opendaylight/sfc/genius/util/SfcGeniusDataUtilsTest.java
sfc-renderers/sfc-openflow-renderer/src/main/java/org/opendaylight/sfc/ofrenderer/processors/SfcOfRspProcessor.java
sfc-renderers/sfc-openflow-renderer/src/main/java/org/opendaylight/sfc/ofrenderer/processors/SfcRspProcessorLogicalSff.java
sfc-renderers/sfc-openflow-renderer/src/main/java/org/opendaylight/sfc/ofrenderer/processors/SffGraph.java
sfc-renderers/sfc-openflow-renderer/src/main/java/org/opendaylight/sfc/ofrenderer/utils/SfcOfBaseProviderUtils.java
sfc-renderers/sfc-openflow-renderer/src/main/java/org/opendaylight/sfc/ofrenderer/utils/SfcOfProviderUtils.java
sfc-renderers/sfc-openflow-renderer/src/test/java/org/opendaylight/sfc/ofrenderer/RspBuilder.java
sfc-renderers/sfc-openflow-renderer/src/test/java/org/opendaylight/sfc/ofrenderer/processors/SfcOfLogicalSffRspProcessorTest.java

index b7d7288a549c73cac4bd3b9600b6d7d96e39abe2..4258fc3c0f11243019dc2405fa6fb8fa3ee799fc 100644 (file)
@@ -77,18 +77,6 @@ public final class SfcGeniusDataUtils {
         return Optional.of(new MacAddress(theIf.getPhysAddress().getValue()));
     }
 
-    /**
-     * Checks if a given Service Function has logical interfaces attached to it.
-     *
-     * @param sf
-     *            The service function we want to check
-     * @return True if it has a LogicalInterface attached attached, False
-     *         otherwise
-     */
-    public static boolean isSfUsingALogicalInterface(ServiceFunction sf) {
-        return !getSfLogicalInterfaces(sf).isEmpty();
-    }
-
     /**
      * Get the information of all physical interfaces mapped to a given logical
      * interface.
index 087625b36aee89f0383c0c5dc7a1a7befd45abb9..49d7e3c4063a444dc637c8e731ec3ac4b459aa4e 100644 (file)
@@ -20,8 +20,6 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.opendaylight.sfc.genius.impl.utils.SfcGeniusConstants;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfDataPlaneLocatorName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
@@ -39,7 +37,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.re
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
@@ -83,9 +80,6 @@ public class SfcGeniusDataUtilsTest {
     private final BigInteger theDpnId = new BigInteger("79268612506848");
     private final String logicalIfName = "tap40c552e0-36";
 
-    @Captor
-    ArgumentCaptor<Interface> interfaceCaptor;
-
     public SfcGeniusDataUtilsTest() {
     }
 
@@ -326,7 +320,6 @@ public class SfcGeniusDataUtilsTest {
                 .setRestUri(new Uri(dpiIpAddress.concat(":5000"))).setType(new SftTypeName("dpi"))
                 .setSfDataPlaneLocator(dpLocators).build();
 
-        Assert.assertFalse(SfcGeniusDataUtils.isSfUsingALogicalInterface(dpiNode));
         List<String> sfLogicalInterfaces = SfcGeniusDataUtils.getSfLogicalInterfaces(dpiNode);
         Assert.assertTrue("There are no logical interfaces", sfLogicalInterfaces.isEmpty());
     }
@@ -362,7 +355,6 @@ public class SfcGeniusDataUtilsTest {
                 .setRestUri(new Uri(dpiIpAddress.concat(":5000"))).setType(new SftTypeName("dpi"))
                 .setSfDataPlaneLocator(dpLocators).build();
 
-        Assert.assertTrue(SfcGeniusDataUtils.isSfUsingALogicalInterface(dpiNode));
         Assert.assertEquals(
                 Arrays.asList("40c552e0-3695-472d-bace-7618786aba27", "12345678-3695-472d-bace-7618786aba27"),
                 SfcGeniusDataUtils.getSfLogicalInterfaces(dpiNode));
index f57b2697ab9aaf5047e98754c531d557c8023383..8b6972515b024c97bfabf5d3ed3e2e9dc53358a1 100644 (file)
@@ -10,9 +10,11 @@ package org.opendaylight.sfc.ofrenderer.processors;
 
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Collectors;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.genius.mdsalutil.NwConstants;
@@ -26,6 +28,7 @@ import org.opendaylight.sfc.ofrenderer.utils.operdsupdate.OperDsUpdateHandlerLSF
 import org.opendaylight.sfc.ovs.provider.SfcOvsUtil;
 import org.opendaylight.sfc.util.openflow.OpenflowConstants;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffDataPlaneLocatorName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
@@ -33,7 +36,6 @@ import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev14070
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocator;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.service.function.dictionary.SffSfDataPlaneLocator;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.DataPlaneLocator;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.Mac;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.MacChaining;
@@ -255,6 +257,7 @@ public class SfcOfRspProcessor {
         String sfgName = null;
         SffGraph.SffGraphEntry entry;
         short lastServiceIndex = rsp.getStartingIndex();
+        boolean isForwardPath = !rsp.isReversePath();
 
         while (servicePathHopIter.hasNext()) {
             RenderedServicePathHop rspHop = servicePathHopIter.next();
@@ -263,34 +266,21 @@ public class SfcOfRspProcessor {
             sfgName = rspHop.getServiceFunctionGroupName();
 
             entry = sffGraph.addGraphEntry(prevSffName, curSffName, sfName, sfgName, rsp.getPathId(),
-                    rspHop.getServiceIndex());
+                    isForwardPath, rspHop.getServiceIndex());
             entry.setPrevSf(prevSfName);
             lastServiceIndex = rspHop.getServiceIndex();
             prevSfName = sfName;
             prevSffName = curSffName;
             ServiceFunction sf = sfcOfProviderUtils.getServiceFunction(sfName, rsp.getPathId());
-            if (SfcGeniusDataUtils.isSfUsingALogicalInterface(sf)) {
-                String logicalInterfaceName = sfcOfProviderUtils.getSfLogicalInterfaceName(sf);
-                LOG.debug("SF uses a logical interface -> storing id for the dataplane node (interface:{})",
-                        logicalInterfaceName);
-                Optional<DpnIdType> dpnid = getGeniusRpcClient()
-                        .getDpnIdFromInterfaceNameFromGeniusRPC(logicalInterfaceName);
-                if (!dpnid.isPresent()) {
-                    throw new SfcRenderingException("populateSffGraph:failed.dpnid for interface ["
-                            + logicalInterfaceName + "] was not returned by genius. "
-                            + "Rendered service path cannot be generated at this time");
-                }
-                LOG.debug("populateSffGraph: retrieved dpn id for SF {} :[{}] ", sf.getName(), dpnid.get());
-                entry.setDstDpnId(dpnid.get());
-            }
+            DpnIdType dpnId = this.getSfDpn(sf);
+            entry.setDstDpnId(dpnId);
             entry.setSrcDpnId(srcDpnId);
+            srcDpnId = dpnId;
             LOG.debug("populateSffGraph:added graph entry: [{}]", entry);
-            srcDpnId = entry.getDstDpnId();
-
         }
         // Add the final connection, which will be the RSP Egress
         // Using the previous sfName as the SrcSf
-        entry = sffGraph.addGraphEntry(prevSffName, SffGraph.EGRESS, sfName, sfgName, rsp.getPathId(),
+        entry = sffGraph.addGraphEntry(prevSffName, SffGraph.EGRESS, sfName, sfgName, rsp.getPathId(), isForwardPath,
                 (short) (lastServiceIndex - 1));
         entry.setPrevSf(prevSfName);
         entry.setSrcDpnId(srcDpnId);
@@ -313,21 +303,25 @@ public class SfcOfRspProcessor {
     private void configureTransportIngressFlows(SffGraph.SffGraphEntry entry, SffGraph sffGraph,
             SfcRspTransportProcessorBase transportProcessor) {
 
-        if (entry.getDstSff().equals(SffGraph.EGRESS)) {
+        SffName dstSffName = entry.getDstSff();
+        long pathId = entry.getPathId();
+
+        if (SffGraph.EGRESS.equals(dstSffName)) {
             return;
         }
 
-        ServiceFunctionForwarder sffDst = sfcOfProviderUtils.getServiceFunctionForwarder(entry.getDstSff(),
-                entry.getPathId());
-        SffDataPlaneLocator sffDstIngressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(sffDst,
-                sffGraph.getSffIngressDpl(entry.getDstSff(), entry.getPathId()));
+        ServiceFunctionForwarder dstSff = sfcOfProviderUtils.getServiceFunctionForwarder(dstSffName, pathId);
+        SffDataPlaneLocatorName sffIngressDplName = sffGraph.getSffIngressDpl(dstSffName, pathId);
+        SffDataPlaneLocator sffIngressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(dstSff, sffIngressDplName);
 
-        transportProcessor.configureSffTransportIngressFlow(entry, sffDstIngressDpl);
+        transportProcessor.configureSffTransportIngressFlow(entry, sffIngressDpl);
 
         // Configure the SF related flows
-        if (entry.getSf() != null) {
-            ServiceFunction sf = sfcOfProviderUtils.getServiceFunction(entry.getSf(), entry.getPathId());
-            SfDataPlaneLocator sfDpl = sfcOfProviderUtils.getSfDataPlaneLocator(sf, entry.getDstSff());
+        SfName sfName = entry.getSf();
+        if (sfName != null) {
+            ServiceFunction sf = sfcOfProviderUtils.getServiceFunction(sfName, pathId);
+            boolean isForwardPath = entry.isForwardPath();
+            SfDataPlaneLocator sfDpl = sfcOfProviderUtils.getIngressSfDataPlaneLocator(dstSff, sf, isForwardPath);
             transportProcessor.configureSfTransportIngressFlow(entry, sfDpl);
         }
     }
@@ -346,20 +340,26 @@ public class SfcOfRspProcessor {
     private void configurePathMapperFlows(SffGraph.SffGraphEntry entry, SffGraph sffGraph,
             SfcRspTransportProcessorBase transportProcessor) {
 
-        if (entry.getDstSff().equals(SffGraph.EGRESS)) {
+        SffName sffName = entry.getDstSff();
+        long pathId = entry.getPathId();
+
+        if (SffGraph.EGRESS.equals(sffName)) {
             return;
         }
 
-        DataPlaneLocator dstHopIngressDpl = sffGraph.getHopIngressDpl(entry.getDstSff(), entry.getPathId());
+        DataPlaneLocator dstHopIngressDpl = sffGraph.getHopIngressDpl(sffName, pathId);
 
         // configure SFF-SFF-SF ingress -OR- Ingress-SFF-SF ingress flow using
         // dstHopIngressDpl
         transportProcessor.configureSffPathMapperFlow(entry, dstHopIngressDpl);
 
         // configure the SF Ingress Flow
-        if (entry.getSf() != null) {
-            ServiceFunction sf = sfcOfProviderUtils.getServiceFunction(entry.getSf(), entry.getPathId());
-            SfDataPlaneLocator sfDpl = sfcOfProviderUtils.getSfDataPlaneLocator(sf, entry.getDstSff());
+        SfName sfName = entry.getSf();
+        if (sfName != null) {
+            ServiceFunctionForwarder dstSff = sfcOfProviderUtils.getServiceFunctionForwarder(sffName, pathId);
+            ServiceFunction sf = sfcOfProviderUtils.getServiceFunction(sfName, pathId);
+            boolean isForwardPath = entry.isForwardPath();
+            SfDataPlaneLocator sfDpl = sfcOfProviderUtils.getIngressSfDataPlaneLocator(dstSff, sf, isForwardPath);
             transportProcessor.configureSfPathMapperFlow(entry, sfDpl);
         }
     }
@@ -379,34 +379,42 @@ public class SfcOfRspProcessor {
             SfcRspTransportProcessorBase transportProcessor) {
 
         LOG.debug("configureNextHopFlows: entry:{}, sffGraph:{}", entry, sffGraph);
-        ServiceFunction sfDst = sfcOfProviderUtils.getServiceFunction(entry.getSf(), entry.getPathId());
-        SfDataPlaneLocator sfDstDpl = sfDst == null ? null
-                : sfcOfProviderUtils.getSfDataPlaneLocator(sfDst, entry.getDstSff());
-        if (sfDstDpl != null) {
-            if (entry.getSrcSff().equals(SffGraph.INGRESS)) {
-                // Configure the GW-SFF-SF NextHop using sfDpl
-                transportProcessor.configureNextHopFlow(entry, (SffDataPlaneLocator) null, sfDstDpl);
+
+        long pathId = entry.getPathId();
+        boolean isForwardPath = entry.isForwardPath();
+        SfName dstSfName = entry.getSf();
+        SfName srcSfName = entry.getPrevSf();
+        SffName dstSffName = entry.getDstSff();
+        SffName srcSffName = entry.getSrcSff();
+        ServiceFunction dstSf = sfcOfProviderUtils.getServiceFunction(dstSfName, pathId);
+        ServiceFunction srcSf = sfcOfProviderUtils.getServiceFunction(srcSfName, pathId);
+        ServiceFunctionForwarder dstSff = sfcOfProviderUtils.getServiceFunctionForwarder(dstSffName, pathId);
+        ServiceFunctionForwarder srcSff = sfcOfProviderUtils.getServiceFunctionForwarder(srcSffName, pathId);
+        SfDataPlaneLocator dstSfDpl;
+        SfDataPlaneLocator srcSfDpl;
+        dstSfDpl = sfcOfProviderUtils.getEgressSfDataPlaneLocator(dstSff, dstSf, isForwardPath);
+        srcSfDpl = sfcOfProviderUtils.getIngressSfDataPlaneLocator(srcSff, srcSf, isForwardPath);
+
+        if (dstSfDpl != null) {
+            if (SffGraph.INGRESS.equals(srcSffName)) {
+                // Configure the GW-SFF-SF NextHop using dstSfDpl
+                transportProcessor.configureNextHopFlow(entry, (SffDataPlaneLocator) null, dstSfDpl);
 
                 // If its Ingress, nothing else to be done
                 return;
             } else {
-
-                ServiceFunctionForwarder sffSrc = sfcOfProviderUtils.getServiceFunctionForwarder(entry.getSrcSff(),
-                        entry.getPathId());
-                SffDataPlaneLocator sffSrcEgressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(sffSrc,
-                        sffGraph.getSffEgressDpl(entry.getSrcSff(), entry.getPathId()));
-                // Configure the SFF-SFF-SF NextHop using sfDpl
-                transportProcessor.configureNextHopFlow(entry, sffSrcEgressDpl, sfDstDpl);
+                SffDataPlaneLocatorName sffEgressDplName = sffGraph.getSffEgressDpl(srcSffName, pathId);
+                SffDataPlaneLocator sffEgressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(srcSff, sffEgressDplName);
+                // Configure the SFF-SFF-SF NextHop using dstSfDpl
+                transportProcessor.configureNextHopFlow(entry, sffEgressDpl, dstSfDpl);
             }
         }
 
-        if (entry.getDstSff().equals(SffGraph.EGRESS)) {
+        if (SffGraph.EGRESS.equals(dstSffName)) {
             // If dstSff is EGRESS, the SF is actually on the srcSff
-            SfDataPlaneLocator sfSrcDpl = sfcOfProviderUtils.getSfDataPlaneLocator(sfDst, entry.getSrcSff());
-
             // Configure the SF-SFF-GW NextHop, we dont have the DstDpl, leaving
             // it blank
-            transportProcessor.configureNextHopFlow(entry, sfSrcDpl, (SffDataPlaneLocator) null);
+            transportProcessor.configureNextHopFlow(entry, srcSfDpl, (SffDataPlaneLocator) null);
         }
 
         if (entry.isIntraLogicalSFFEntry()) {
@@ -415,27 +423,18 @@ public class SfcOfRspProcessor {
             return;
         }
 
-        SfDataPlaneLocator sfSrcDpl = null;
-        if (entry.getPrevSf() != null) {
-            sfSrcDpl = sfcOfProviderUtils.getSfDataPlaneLocator(
-                    sfcOfProviderUtils.getServiceFunction(entry.getPrevSf(), entry.getPathId()), entry.getSrcSff());
-        }
-
-        // Configure the SFF-SFF NextHop using the sfDpl and sffDstIngressDpl
-        if (sfSrcDpl != null) {
-            if (entry.getSrcSff().getValue().equals(entry.getDstSff().getValue())) {
+        if (srcSfDpl != null) {
+            if (srcSffName.equals(dstSffName)) {
                 // If the next hop is on this SFF then go straight to the next
                 // SF
                 // Configure SF-SFF-SF NextHop on the same SFF
-                transportProcessor.configureNextHopFlow(entry, sfSrcDpl, sfDstDpl);
+                transportProcessor.configureNextHopFlow(entry, srcSfDpl, dstSfDpl);
             } else {
-                // Configure the SFF-SFF NextHop using the sfDpl and
-                // sffDstIngressDpl
-                ServiceFunctionForwarder sffDst = sfcOfProviderUtils.getServiceFunctionForwarder(entry.getDstSff(),
-                        entry.getPathId());
-                SffDataPlaneLocator sffDstIngressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(sffDst,
-                        sffGraph.getSffIngressDpl(entry.getDstSff(), entry.getPathId()));
-                transportProcessor.configureNextHopFlow(entry, sfSrcDpl, sffDstIngressDpl);
+                // Configure the SFF-SFF NextHop using the srcSfDpl and sffIngressDpl
+                SffDataPlaneLocatorName sffIngressDplName = sffGraph.getSffIngressDpl(dstSffName, pathId);
+                SffDataPlaneLocator sffIngressDpl;
+                sffIngressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(dstSff, sffIngressDplName);
+                transportProcessor.configureNextHopFlow(entry, srcSfDpl, sffIngressDpl);
             }
         }
     }
@@ -454,51 +453,49 @@ public class SfcOfRspProcessor {
     private void configureTransportEgressFlows(SffGraph.SffGraphEntry entry, SffGraph sffGraph,
             SfcRspTransportProcessorBase transportProcessor) {
 
-        // Configure the SFF-Egress Transport Egress
-        ServiceFunctionForwarder sffSrc = sfcOfProviderUtils.getServiceFunctionForwarder(entry.getSrcSff(),
-                entry.getPathId());
-        if (entry.getDstSff().equals(SffGraph.EGRESS)) {
-            SffDataPlaneLocator sffSrcEgressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(sffSrc,
-                    sffGraph.getSffEgressDpl(entry.getSrcSff(), entry.getPathId()));
+        long pathId = entry.getPathId();
+        boolean isForwardPath = entry.isForwardPath();
+        SfName dstSfName = entry.getSf();
+        SffName dstSffName = entry.getDstSff();
+        SffName srcSffName = entry.getSrcSff();
+        ServiceFunction dstSf = sfcOfProviderUtils.getServiceFunction(dstSfName, pathId);
+        ServiceFunctionForwarder dstSff = sfcOfProviderUtils.getServiceFunctionForwarder(dstSffName, pathId);
+        ServiceFunctionForwarder srcSff = sfcOfProviderUtils.getServiceFunctionForwarder(srcSffName, pathId);
+        SfDataPlaneLocator dstSfDpl;
+        SffDataPlaneLocator dstSffDpl;
+        dstSfDpl = sfcOfProviderUtils.getEgressSfDataPlaneLocator(dstSff, dstSf, isForwardPath);
+        dstSffDpl = sfcOfProviderUtils.getEgressSffDataPlaneLocator(dstSff, dstSf, isForwardPath);
+        SffDataPlaneLocatorName sffEgressDpl = sffGraph.getSffEgressDpl(srcSffName, pathId);
+        SffDataPlaneLocator srcSffEgressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(srcSff, sffEgressDpl);
 
-            transportProcessor.configureSffTransportEgressFlow(entry, sffSrcEgressDpl, null,
-                    sffGraph.getPathEgressDpl(entry.getPathId()));
+        // Configure the SFF-Egress Transport Egress
+        if (SffGraph.EGRESS.equals(dstSffName)) {
+            DataPlaneLocator pathEgressDpl = sffGraph.getPathEgressDpl(pathId);
+            transportProcessor.configureSffTransportEgressFlow(entry, srcSffEgressDpl, null, pathEgressDpl);
             return;
         }
 
-        // Configure the SFF-SF Transport Egress using sfDpl
-        ServiceFunction sfDst = sfcOfProviderUtils.getServiceFunction(entry.getSf(), entry.getPathId());
-        SfDataPlaneLocator sfDstDpl = sfcOfProviderUtils.getSfDataPlaneLocator(sfDst, entry.getDstSff());
-        ServiceFunctionForwarder sffDst = sfcOfProviderUtils.getServiceFunctionForwarder(entry.getDstSff(),
-                entry.getPathId());
-
-        if (sfDstDpl != null) {
-            SffDataPlaneLocator sffDstDpl = null;
-            SffSfDataPlaneLocator sffSfDpl = sfcOfProviderUtils.getSffSfDataPlaneLocator(sffDst, entry.getSf());
-            if (sffSfDpl != null) {
-                sffDstDpl = sfcOfProviderUtils.getSffDataPlaneLocator(sffDst, sffSfDpl.getSffDplName());
-            }
-            transportProcessor.configureSfTransportEgressFlow(entry, sffDstDpl, sfDstDpl, sfDstDpl);
+        if (dstSfDpl != null) {
+            transportProcessor.configureSfTransportEgressFlow(entry, dstSffDpl, dstSfDpl, dstSfDpl);
         }
 
         // Nothing else to be done for Ingress
-        if (entry.getSrcSff().equals(SffGraph.INGRESS)) {
+        if (SffGraph.INGRESS.equals(srcSffName)) {
             return;
         }
 
-        // Configure the SFF-SFF Transport Egress using the sffDstIngressDpl
-        if (!entry.getSrcSff().getValue().equals(entry.getDstSff().getValue()) || entry.isIntraLogicalSFFEntry()
-                && !entry.getSrcDpnId().getValue().equals(entry.getDstDpnId().getValue())) {
+        DpnIdType srcDpnId = entry.getSrcDpnId();
+        DpnIdType dstDpnId = entry.getDstDpnId();
+        if (!srcSffName.equals(dstSffName) || entry.isIntraLogicalSFFEntry() && !srcDpnId.equals(dstDpnId)) {
 
-            SffDataPlaneLocator sffDstIngressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(sffDst,
-                    sffGraph.getSffIngressDpl(entry.getDstSff(), entry.getPathId()));
-            SffDataPlaneLocator sffSrcEgressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(sffSrc,
-                    sffGraph.getSffEgressDpl(entry.getSrcSff(), entry.getPathId()));
+            // Configure the SFF-SFF Transport Egress using the sffIngressDpl
+            SffDataPlaneLocatorName sffIngressDplName = sffGraph.getSffIngressDpl(dstSffName, entry.getPathId());
+            SffDataPlaneLocator sffIngressDpl = sfcOfProviderUtils.getSffDataPlaneLocator(dstSff, sffIngressDplName);
             // This is the HOP DPL details between srcSFF and dstSFF, for
             // example: VLAN ID 100
-            DataPlaneLocator dstHopIngressDpl = sffGraph.getHopIngressDpl(entry.getDstSff(), entry.getPathId());
+            DataPlaneLocator dstHopIngressDpl = sffGraph.getHopIngressDpl(dstSffName, pathId);
 
-            transportProcessor.configureSffTransportEgressFlow(entry, sffSrcEgressDpl, sffDstIngressDpl,
+            transportProcessor.configureSffTransportEgressFlow(entry, srcSffEgressDpl, sffIngressDpl,
                     dstHopIngressDpl);
         }
     }
@@ -613,4 +610,47 @@ public class SfcOfRspProcessor {
     private SfcGeniusRpcClient getGeniusRpcClient() {
         return theGeniusRpcClient;
     }
+
+    /**
+     * Helper to get the DPN where an interface is currently located.
+     *
+     * @param interfaceName the interface name
+     * @return the dpn
+     * @throws SfcRenderingException if the location of the interface could not be determined
+     */
+    private DpnIdType getInterfaceDpn(String interfaceName) {
+        Optional<DpnIdType> dpnIdType = getGeniusRpcClient().getDpnIdFromInterfaceNameFromGeniusRPC(interfaceName);
+        return dpnIdType.orElseThrow(() -> new SfcRenderingException(
+                "SfcOfRspProcessor failed: dpnid for interface [" + interfaceName + "] was not returned by genius."));
+    }
+
+    /**
+     * Helper to get the DPN location of a service function with logical
+     * interface locators.
+     *
+     * @param sf the service function
+     * @return the DPN or null if the service function has no logical
+     *         interface locators
+     * @throws SfcRenderingException if the location of the SF interfaces could not be determined
+     */
+    private DpnIdType getSfDpn(ServiceFunction sf) {
+        List<String> logicalInterfaces = SfcGeniusDataUtils.getSfLogicalInterfaces(sf);
+        if (logicalInterfaces.isEmpty()) {
+            LOG.debug("SF has no logical interfaces, cannot get its DPN location");
+            return null;
+        }
+
+        List<DpnIdType> dpnIdTypeList = logicalInterfaces.stream()
+                .map(this::getInterfaceDpn)
+                .distinct()
+                .collect(Collectors.toList());
+        if (dpnIdTypeList.size() > 1) {
+            throw new SfcRenderingException("SfcOfRspProcessor failed: multiple logical interfaces on different data "
+                    + "plane nodes for the same service function are not supported");
+        }
+        DpnIdType dpnId = dpnIdTypeList.get(0);
+        LOG.debug("SfcOfRspProcessor: retrieved dpn id for SF {} :[{}] ", sf.getName(), dpnId);
+        return dpnId;
+    }
+
 }
index 06d653b311388ad56398d30e8ffa983c17e03690..6684e2d3370ec29c0773b3548f152f2e4fe8be2c 100644 (file)
@@ -19,10 +19,13 @@ import org.opendaylight.sfc.ofrenderer.processors.SffGraph.SffGraphEntry;
 import org.opendaylight.sfc.ofrenderer.utils.operdsupdate.OperDsUpdateHandlerInterface;
 import org.opendaylight.sfc.util.openflow.OpenflowConstants;
 import org.opendaylight.sfc.util.openflow.SfcOpenflowUtils;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
 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.sf.rev140701.service.function.base.SfDataPlaneLocator;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocator;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.DataPlaneLocator;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.logical.rev160620.DpnIdType;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.logical.rev160620.LogicalInterfaceLocator;
@@ -246,21 +249,27 @@ public class SfcRspProcessorLogicalSff extends SfcRspTransportProcessorBase {
     @Override
     public void configureSffTransportEgressFlow(SffGraph.SffGraphEntry entry, SffDataPlaneLocator srcSffDpl,
             SffDataPlaneLocator dstSffDpl, DataPlaneLocator hopDpl) {
-        long nsp = entry.getPathId();
+        long pathId = entry.getPathId();
+        long nsp = pathId;
         short nsi = entry.getServiceIndex();
-        String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getSrcSff(), entry.getPathId(),
-                entry.getSrcDpnId());
+        SffName dstSff = entry.getDstSff();
+        SffName srcSff = entry.getSrcSff();
+        DpnIdType srcDpnId = entry.getSrcDpnId();
+        DpnIdType dstDpnId = entry.getDstDpnId();
+        String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(srcSff, pathId, srcDpnId);
 
-        if (entry.getDstSff().equals(SffGraph.EGRESS)) {
+        if (SffGraph.EGRESS.equals(dstSff)) {
             LOG.debug("configureSffTransportEgressFlow: called for chain egress");
-            SfDataPlaneLocator srcSfDpl = sfcProviderUtils.getSfDataPlaneLocator(
-                    sfcProviderUtils.getServiceFunction(entry.getPrevSf(), entry.getPathId()), entry.getSrcSff());
+            SfName prevSfName = entry.getPrevSf();
+            ServiceFunctionForwarder prevSff = sfcProviderUtils.getServiceFunctionForwarder(srcSff, pathId);
+            ServiceFunction prevSf = sfcProviderUtils.getServiceFunction(prevSfName, pathId);
+            boolean isForwardPath = entry.isForwardPath();
+            SfDataPlaneLocator srcSfDpl = sfcProviderUtils.getIngressSfDataPlaneLocator(prevSff, prevSf, isForwardPath);
             MacAddress sfMacAddress = getMacAddress(srcSfDpl, false)
                     .orElseThrow(() -> new SfcRenderingException(
                             "Failed on mac address retrieval for dst SF dpl [" + srcSfDpl + "]"));
 
-            DpnIdType srcDpid = entry.getSrcDpnId();
-            IpAddress sffIpAddress = Optional.ofNullable(sfcGeniusRpcClient.getDpnIpFromGeniusRPC(srcDpid))
+            IpAddress sffIpAddress = Optional.ofNullable(sfcGeniusRpcClient.getDpnIpFromGeniusRPC(srcDpnId))
                     .filter(ipAddresses -> !ipAddresses.isEmpty())
                     .map(ipAddresses -> ipAddresses.get(0))
                     .orElse(null);
@@ -272,19 +281,18 @@ public class SfcRspProcessorLogicalSff extends SfcRspTransportProcessorBase {
             if (entry.isIntraLogicalSFFEntry()) {
                 // in this case, use Genius to program egress flow
                 // 1. Get dpid for both source sff, dst sff
-                DpnIdType srcDpid = entry.getSrcDpnId();
-                DpnIdType dstDpid = entry.getDstDpnId();
+
                 // 2, use genius to retrieve dst interface name (ITM manager
                 // RPC)
-                Optional<String> targetInterfaceName = sfcGeniusRpcClient.getTargetInterfaceFromGeniusRPC(srcDpid,
-                        dstDpid);
+                Optional<String> targetInterfaceName = sfcGeniusRpcClient.getTargetInterfaceFromGeniusRPC(srcDpnId,
+                        dstDpnId);
                 if (!targetInterfaceName.isPresent()) {
-                    throw new SfcRenderingException("Failure during transport egress config. Genius did not return"
-                            + " the interface to use between src dpnid:" + srcDpid + "and dst dpnid:" + dstDpid + ")");
+                    throw new SfcRenderingException("Failure during transport egress config. Genius did not return the"
+                            + " interface to use between src dpnid:" + srcDpnId + "and dst dpnid:" + dstDpnId + ")");
                 }
 
-                LOG.debug("configureSffTransportEgressFlow: srcDpn [{}] destDpn [{}] interface to use: [{}]", srcDpid,
-                        dstDpid, targetInterfaceName.get());
+                LOG.debug("configureSffTransportEgressFlow: srcDpn [{}] destDpn [{}] interface to use: [{}]", srcDpnId,
+                        dstDpnId, targetInterfaceName.get());
                 // 3, use genius for retrieving egress actions (Interface
                 // Manager RPC)
                 Optional<List<Action>> actionList = sfcGeniusRpcClient
@@ -293,7 +301,7 @@ public class SfcRspProcessorLogicalSff extends SfcRspTransportProcessorBase {
                 if (!actionList.isPresent() || actionList.get().isEmpty()) {
                     throw new SfcRenderingException("Failure during transport egress config. Genius did not return"
                             + " egress actions for logical interface [" + targetInterfaceName.get() + "] (src dpnid:"
-                            + srcDpid + "; dst dpnid:" + dstDpid + ")");
+                            + srcDpnId + "; dst dpnid:" + dstDpnId + ")");
                 }
 
                 LOG.debug("configureSffTransportEgressFlow: adding NSH as NP to GPE encap");
@@ -302,7 +310,7 @@ public class SfcRspProcessorLogicalSff extends SfcRspTransportProcessorBase {
 
                 StringJoiner flowName = new StringJoiner(OpenflowConstants.OF_NAME_DELIMITER);
                 flowName.add(OpenflowConstants.OF_NAME_TRANSPORT_EGRESS)
-                    .add("SFF").add(String.valueOf(entry.getServiceIndex())).add(String.valueOf(entry.getPathId()));
+                    .add("SFF").add(String.valueOf(entry.getServiceIndex())).add(String.valueOf(pathId));
 
                 // 4, write those actions
                 this.sfcFlowProgrammer.configureNshEthTransportEgressFlow(
index f5a54c5d0b54c98c8a386d0f32f7d2cf543bacfe..ef0d54bcd7b4fb504006ae19c54ea2323053b058 100644 (file)
@@ -46,6 +46,7 @@ public class SffGraph {
         private final short serviceIndex;
         private DpnIdType logicalSffSrcDpnId;
         private DpnIdType logicalSffDstDpnId;
+        private boolean isForwardPath;
 
         public SffName getSrcSff() {
             return srcSff;
@@ -80,12 +81,13 @@ public class SffGraph {
         }
 
         public SffGraphEntry(final SffName srcSff, final SffName dstSff, final SfName sf, final String sfg, long pathId,
-                short serviceIndex) {
+                             boolean isForwardPath, short serviceIndex) {
             this.srcSff = srcSff;
             this.dstSff = dstSff;
             this.sf = sf;
             this.sfg = sfg;
             this.pathId = pathId;
+            this.isForwardPath = isForwardPath;
             this.serviceIndex = serviceIndex;
             this.prevSf = null;
         }
@@ -93,7 +95,8 @@ public class SffGraph {
         @Override
         public String toString() {
             String str = "SffGraphEntry [srcSff=" + srcSff + ", dstSff=" + dstSff + ", sf=" + sf + ", prevSf=" + prevSf
-                    + ", sfg=" + sfg + ", pathId=" + pathId + ", serviceIndex=" + serviceIndex;
+                    + ", sfg=" + sfg + ", pathId=" + pathId + ", isForwardPath=" + isForwardPath + ", serviceIndex="
+                    + serviceIndex;
             if (getSrcDpnId() != null || getDstDpnId() != null) {
                 str += ", Logical SFF params: src dpnid [" + getSrcDpnId() + "], dst dpnid [" + getDstDpnId() + "]";
             }
@@ -125,6 +128,10 @@ public class SffGraph {
         public void setDstDpnId(DpnIdType dpnId) {
             this.logicalSffDstDpnId = dpnId;
         }
+
+        public boolean isForwardPath() {
+            return isForwardPath;
+        }
     }
 
     /**
@@ -190,12 +197,11 @@ public class SffGraph {
     // Graph methods
     //
     public SffGraphEntry addGraphEntry(final SffName srcSff, final SffName dstSff, final SfName sf, final String sfg,
-            long pathId, short serviceIndex) {
-        SffGraphEntry entry = new SffGraphEntry(srcSff, dstSff, sf, sfg, pathId, serviceIndex);
+            long pathId, boolean isForwardPath, short serviceIndex) {
+        SffGraphEntry entry = new SffGraphEntry(srcSff, dstSff, sf, sfg, pathId, isForwardPath, serviceIndex);
         graphEntries.add(entry);
 
-        LOG.info("SffGraphEntry addEntry srcSff [{}] dstSff [{}] sf [{}] sfg [{}] pathId [{}] serviceIndex [{}] ",
-                srcSff.getValue(), dstSff.getValue(), sf.getValue(), sfg, pathId, serviceIndex);
+        LOG.info("addGraphEntry {}", entry);
 
         return entry;
     }
index 90a6ea2ee7c7cba3cf70c655a41a9051ff78797c..e88fee17ff16a6968ab70dcb76497a60bf8f6ef2 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.sfc.ofrenderer.utils;
 
 import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfDataPlaneLocatorName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffDataPlaneLocatorName;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
@@ -25,7 +26,6 @@ import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev14070
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.LocatorType;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Mac;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.logical.rev160620.DpnIdType;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.logical.rev160620.service.functions.service.function.sf.data.plane.locator.locator.type.LogicalInterface;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.ofs.rev150408.SffDataPlaneLocator1;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.ofs.rev150408.port.details.OfsPort;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
@@ -76,7 +76,7 @@ public abstract class SfcOfBaseProviderUtils {
     public SffDataPlaneLocator getSffDataPlaneLocator(ServiceFunctionForwarder sff, SffDataPlaneLocatorName dplName) {
         SffDataPlaneLocator sffDpl = null;
 
-        if (dplName == null || dplName.getValue() == null) {
+        if (sff == null || sff.getSffDataPlaneLocator() == null || dplName == null || dplName.getValue() == null) {
             return null;
         }
 
@@ -93,7 +93,36 @@ public abstract class SfcOfBaseProviderUtils {
     }
 
     /**
-     * Return the SfDataPlaneLocator on the SF that connects to the named SFF.
+     * Return a named SfDataPlaneLocator on a SF.
+     *
+     * @param sf
+     *            - The SF to search in
+     * @param dplName
+     *            - The name of the DPL to look for
+     * @return SfDataPlaneLocator or null if not found
+     */
+    public SfDataPlaneLocator getSfDataPlaneLocator(ServiceFunction sf, SfDataPlaneLocatorName dplName) {
+        SfDataPlaneLocator sfDpl = null;
+
+        if (sf == null || sf.getSfDataPlaneLocator() == null || dplName == null || dplName.getValue() == null) {
+            return null;
+        }
+
+        List<SfDataPlaneLocator> sfDataPlanelocatorList = sf.getSfDataPlaneLocator();
+        for (SfDataPlaneLocator sfDataPlanelocator : sfDataPlanelocatorList) {
+            if (sfDataPlanelocator.getName() != null
+                    && sfDataPlanelocator.getName().getValue().equals(dplName.getValue())) {
+                sfDpl = sfDataPlanelocator;
+                break;
+            }
+        }
+
+        return sfDpl;
+    }
+
+    /**
+     * Return any of the SfDataPlaneLocator on the SF that connects to the named
+     * SFF.
      *
      * @param sf
      *            the ServiceFunction to search through
@@ -113,25 +142,124 @@ public abstract class SfcOfBaseProviderUtils {
     }
 
     /**
-     * Given a ServiceFunction get the SF DPL name from the
-     * SffSfDataPlaneLocator and return the SF DPL.
+     * Returns the SfDataPlaneLocator for SFF Egress in relation to a path
+     * direction. On a forward path, this is the forward SF DPL, while on a
+     * reverse path, this is the reverse SF DPL.
      *
+     * @param sff
+     *            - The SFF
      * @param sf
-     *            the ServiceFunction to search through
-     * @param sffSfDpl
-     *            The SffSf DPL to compare against
-     * @return SfDataPlaneLocator if found, else null
+     *            - The SF
+     * @param isForwardPath
+     *            - True if the path is a forward path, false otherwise
+     * @return SfDataPlaneLocator or null if not found
      */
-    public SfDataPlaneLocator getSfDataPlaneLocator(ServiceFunction sf, SffSfDataPlaneLocator sffSfDpl) {
-        List<SfDataPlaneLocator> sfDataPlanelocatorList = sf.getSfDataPlaneLocator();
+    public SfDataPlaneLocator getEgressSfDataPlaneLocator(ServiceFunctionForwarder sff,
+                                                          ServiceFunction sf,
+                                                          boolean isForwardPath) {
+        SffSfDataPlaneLocator sffSfDpl = getSffSfDataPlaneLocator(sff, sf);
+
+        if (sffSfDpl == null) {
+            // revert to look by SFF name when using old provisioning model
+            // with no SFF dictionary
+            return sff != null ? getSfDataPlaneLocator(sf, sff.getName()) : null;
+        }
 
-        for (SfDataPlaneLocator sfDpl : sfDataPlanelocatorList) {
-            if (sfDpl.getName().getValue().equals(sffSfDpl.getSfDplName().getValue())) {
-                return sfDpl;
-            }
+        final SfDataPlaneLocatorName sfForwardDplName = sffSfDpl.getSfForwardDplName();
+        final SfDataPlaneLocatorName sfReverseDplName = sffSfDpl.getSfReverseDplName();
+        SfDataPlaneLocatorName sfDplName = isForwardPath ? sfForwardDplName : sfReverseDplName;
+        if (sfDplName == null) {
+            // fallback to non directional DPL
+            sfDplName = sffSfDpl.getSfDplName();
         }
 
-        return null;
+        return getSfDataPlaneLocator(sf, sfDplName);
+    }
+
+    /**
+     * Returns the SffDataPlaneLocator for SFF Egress in relation to a path
+     * direction. On a forward path, this is the forward SFF DPL, while on a
+     * reverse path, this is the reverse SFF DPL.
+     *
+     * @param sff
+     *            - The SFF
+     * @param sf
+     *            - The SF
+     * @param isForwardPath
+     *            - True if the path is a forward path, false otherwise
+     * @return SffDataPlaneLocator or null if not found
+     */
+    public SffDataPlaneLocator getEgressSffDataPlaneLocator(ServiceFunctionForwarder sff,
+                                                            ServiceFunction sf,
+                                                            boolean isForwardPath) {
+        SffSfDataPlaneLocator sffSfDpl = getSffSfDataPlaneLocator(sff, sf);
+
+        if (sffSfDpl == null) {
+            return null;
+        }
+
+        final SffDataPlaneLocatorName sffForwardDplName = sffSfDpl.getSffForwardDplName();
+        final SffDataPlaneLocatorName sffReverseDplName = sffSfDpl.getSffReverseDplName();
+        SffDataPlaneLocatorName sffDplName = isForwardPath ? sffForwardDplName : sffReverseDplName;
+        if (sffDplName == null) {
+            // fallback to non directional DPL
+            sffDplName = sffSfDpl.getSffDplName();
+        }
+
+        return getSffDataPlaneLocator(sff, sffDplName);
+    }
+
+    /**
+     * Returns the SfDataPlaneLocator for SFF Ingress in relation to a path
+     * direction. On a forward path, this is the reverse SF DPL, while on a
+     * reverse path, this is the forward SF DPL.
+     *
+     * @param sff
+     *            - The SFF
+     * @param sf
+     *            - The SF
+     * @param isForwardPath
+     *            - True if the path is a forward path, false otherwise
+     * @return SfDataPlaneLocator or null if not found
+     */
+    public SfDataPlaneLocator getIngressSfDataPlaneLocator(ServiceFunctionForwarder sff,
+                                                           ServiceFunction sf,
+                                                           boolean isForwardPath) {
+
+        SffSfDataPlaneLocator sffSfDpl = getSffSfDataPlaneLocator(sff, sf);
+
+        if (sffSfDpl == null) {
+            // revert to look by SFF name when using old provisioning model
+            // with no SFF dictionary
+            return sff != null ? getSfDataPlaneLocator(sf, sff.getName()) : null;
+        }
+
+        final SfDataPlaneLocatorName sfForwardDplName = sffSfDpl.getSfForwardDplName();
+        final SfDataPlaneLocatorName sfReverseDplName = sffSfDpl.getSfReverseDplName();
+        SfDataPlaneLocatorName sfDplName = isForwardPath ? sfReverseDplName : sfForwardDplName;
+        if (sfDplName == null) {
+            // fallback to non directional DPL
+            sfDplName = sffSfDpl.getSfDplName();
+        }
+
+        return getSfDataPlaneLocator(sf, sfDplName);
+    }
+
+    /**
+     * Return the named SF ServiceFunctionDictionary SffSfDataPlaneLocator from
+     * the sff sf-dictionary list.
+     *
+     * @param sff
+     *            - The SFF to search in
+     * @param sf
+     *            - The SF to look for
+     * @return SffSfDataPlaneLocator or null if not found
+     */
+    public SffSfDataPlaneLocator getSffSfDataPlaneLocator(ServiceFunctionForwarder sff, ServiceFunction sf) {
+        if (sf == null) {
+            return null;
+        }
+        return getSffSfDataPlaneLocator(sff, sf.getName());
     }
 
     /**
@@ -141,7 +269,7 @@ public abstract class SfcOfBaseProviderUtils {
      * @param sff
      *            - The SFF to search in
      * @param sfName
-     *            - The name of the DPL to look for
+     *            - The name of the SF to look for
      * @return SffSfDataPlaneLocator or null if not found
      */
     public SffSfDataPlaneLocator getSffSfDataPlaneLocator(ServiceFunctionForwarder sff, SfName sfName) {
@@ -168,6 +296,10 @@ public abstract class SfcOfBaseProviderUtils {
     public ServiceFunctionDictionary getSffSfDictionary(ServiceFunctionForwarder sff, SfName sfName) {
         ServiceFunctionDictionary sffSfDict = null;
 
+        if (sff == null || sfName == null) {
+            return null;
+        }
+
         List<ServiceFunctionDictionary> sffSfDictList = sff.getServiceFunctionDictionary();
         if (sffSfDictList != null) {
             for (ServiceFunctionDictionary dict : sffSfDictList) {
@@ -408,33 +540,6 @@ public abstract class SfcOfBaseProviderUtils {
         return sff.getServiceNode().getValue();
     }
 
-    /**
-     * Given a SF, retrieve the logical interface name.
-     *
-     * @param sf
-     *            The service function to use
-     * @return String the logical interface name when the SF is using a logical
-     *         interface; null otherwise
-     */
-    public String getSfLogicalInterfaceName(ServiceFunction sf) {
-        String interfaceName = null;
-        LOG.debug("getSfLogicalInterfaceName: called for sf {}", sf.getName());
-        if (sf.getSfDataPlaneLocator() != null && sf.getSfDataPlaneLocator().get(0) != null) {
-            SfDataPlaneLocator sfdpl = sf.getSfDataPlaneLocator().get(0);
-            LOG.debug("getSfLogicalInterfaceName: dpl 0 is not null! it is {}", sfdpl);
-            if (sfdpl.getLocatorType() != null
-                    && sfdpl.getLocatorType().getImplementedInterface() == LogicalInterface.class) {
-                LogicalInterface logicalInterface = (LogicalInterface) sfdpl.getLocatorType();
-                if (logicalInterface != null && logicalInterface.getInterfaceName() != null) {
-                    LOG.debug("getSfLogicalInterfaceName: hop is using a logical interface [{}]",
-                            logicalInterface.getInterfaceName());
-                    interfaceName = logicalInterface.getInterfaceName();
-                }
-            }
-        }
-        return interfaceName;
-    }
-
     public SffDataPlaneLocator getSffSfDictSffDpl(SfName sfName, SffName sffName, long rspId) {
         ServiceFunctionForwarder sff = getServiceFunctionForwarder(sffName, rspId);
 
index 39b65a30e2e07aeb8ff67ecd587afbbd3af94470..012f362fa109f7d3b597763713faba212f390ca7 100644 (file)
@@ -89,6 +89,11 @@ public class SfcOfProviderUtils extends SfcOfBaseProviderUtils {
      */
     @Override
     public ServiceFunction getServiceFunction(final SfName sfName, long rspId) {
+
+        if (sfName == null) {
+            return null;
+        }
+
         RspContext rspContext = rspIdToContext.get(rspId);
 
         ServiceFunction sf = rspContext.serviceFunctions.get(sfName);
@@ -125,6 +130,11 @@ public class SfcOfProviderUtils extends SfcOfBaseProviderUtils {
      */
     @Override
     public ServiceFunctionForwarder getServiceFunctionForwarder(final SffName sffName, long rspId) {
+
+        if (sffName == null) {
+            return null;
+        }
+
         RspContext rspContext = rspIdToContext.get(rspId);
 
         ServiceFunctionForwarder sff = rspContext.serviceFunctionFowarders.get(sffName);
index 4ca50ee31f56a81da040a64ae917da879284d901..9a74930b88cfac87e08a3c3913af8675df658138 100644 (file)
@@ -228,6 +228,7 @@ public class RspBuilder {
         rspBuilder.setPathId(rspPathIdIndex++);
         rspBuilder.setTransportType(sfp.getTransportType());
         rspBuilder.setSfcEncapsulation(sfp.getSfcEncapsulation());
+        rspBuilder.setReversePath(false);
 
         short index = 0;
         short serviceIndex = STARTING_INDEX;
index 11418651bb26d95802fea3d41dfce706d9c388a9..effa4de5304606fe71391e6fadf69f983e621eff 100644 (file)
@@ -12,6 +12,7 @@ import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.junit.Assert.assertThat;
 import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -25,6 +26,7 @@ import static org.opendaylight.sfc.ofrenderer.openflow.SfcOfFlowProgrammerImpl.T
 import static org.opendaylight.sfc.ofrenderer.openflow.SfcOfFlowProgrammerImpl.TRANSPORT_EGRESS_NSH_ETH_LASTHOP_TUNNEL_LOCAL_COOKIE;
 import static org.opendaylight.sfc.ofrenderer.openflow.SfcOfFlowProgrammerImpl.TRANSPORT_EGRESS_NSH_ETH_LASTHOP_TUNNEL_REMOTE_COOKIE;
 import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.replace;
 import static org.powermock.api.support.membermodification.MemberModifier.suppress;
 
 import com.google.common.net.InetAddresses;
@@ -63,8 +65,6 @@ import org.opendaylight.sfc.util.openflow.writer.FlowDetails;
 import org.opendaylight.sfc.util.openflow.writer.SfcOfFlowWriterImpl;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SftTypeName;
 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.sf.rev140701.service.function.base.SfDataPlaneLocator;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
@@ -222,7 +222,6 @@ public class SfcOfLogicalSffRspProcessorTest {
     public void setUp() throws Exception {
         sfcUtils.resetCache();
 
-        PowerMockito.mockStatic(SfcGeniusDataUtils.class);
         Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(Mockito.mock(WriteTransaction.class));
         PowerMockito.when(sfcOfRspProcessor, "getGeniusRpcClient").thenReturn(geniusClient);
         PowerMockito.doReturn(logicalSffProcessor).when(sfcOfRspProcessor, "getReusableTransportProcessor", any(),
@@ -231,25 +230,30 @@ public class SfcOfLogicalSffRspProcessorTest {
         PowerMockito.when(geniusClient, "getItmRpcService").thenReturn(itmRpcService);
 
         String ifName0 = rspBuilder.getLogicalInterfaceName(0);
-        PowerMockito.mockStatic(SfcGeniusDataUtils.class);
-        PowerMockito.when(SfcGeniusDataUtils.getServiceFunctionMacAddress(ifName0))
-                .thenReturn(Optional.of(MAC_ADDRESS_SF_SIDE[0]));
-        PowerMockito.when(SfcGeniusDataUtils.getServiceFunctionForwarderPortMacAddress(ifName0))
-                .thenReturn(Optional.of(MAC_ADDRESS_OVS_SIDE[0]));
-
         String ifName1 = rspBuilder.getLogicalInterfaceName(1);
-        PowerMockito.when(SfcGeniusDataUtils.getServiceFunctionMacAddress(ifName1))
-                .thenReturn(Optional.of(MAC_ADDRESS_SF_SIDE[1]));
-        PowerMockito.when(SfcGeniusDataUtils.getServiceFunctionForwarderPortMacAddress(ifName1))
-                .thenReturn(Optional.of(MAC_ADDRESS_OVS_SIDE[1]));
-
-        PowerMockito.when(SfcGeniusDataUtils.getLogicalInterfaceNameFromLocator(any(SfDataPlaneLocator.class)))
-                .thenReturn(LOGICAL_INTERFACE_NAME);
+        PowerMockito.mockStatic(SfcGeniusDataUtils.class, CALLS_REAL_METHODS);
+
+        replace(method(SfcGeniusDataUtils.class,"getServiceFunctionMacAddress", String.class))
+                .with((object, method, arguments) -> {
+                    if (arguments[0].equals(ifName0)) {
+                        return Optional.of(MAC_ADDRESS_SF_SIDE[0]);
+                    } else if (arguments[0].equals(ifName1)) {
+                        return Optional.of(MAC_ADDRESS_SF_SIDE[1]);
+                    }
+                    return Optional.empty();
+                });
+        replace(method(SfcGeniusDataUtils.class,"getServiceFunctionForwarderPortMacAddress", String.class))
+                .with((object, method, arguments) -> {
+                    if (arguments[0].equals(ifName0)) {
+                        return Optional.of(MAC_ADDRESS_OVS_SIDE[0]);
+                    } else if (arguments[0].equals(ifName1)) {
+                        return Optional.of(MAC_ADDRESS_OVS_SIDE[1]);
+                    }
+                    return Optional.empty();
+                });
 
         PowerMockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(null);
 
-        PowerMockito.when(SfcGeniusDataUtils.isSfUsingALogicalInterface(any(ServiceFunction.class))).thenReturn(true);
-
         when(interfaceManagerRpcService.getEgressActionsForInterface(any(GetEgressActionsForInterfaceInput.class)))
                 .thenReturn(Futures.immediateFuture(RpcResultBuilder
                         .success(new GetEgressActionsForInterfaceOutputBuilder().setAction(new ArrayList<>()))