Now using NSH Nsc Registers 16/20416/2
authorBrady Johnson <[email protected]>
Thu, 14 May 2015 17:39:27 +0000 (19:39 +0200)
committerBrady Johnson <[email protected]>
Thu, 14 May 2015 19:30:18 +0000 (21:30 +0200)
- Add NshOneHop UT
- Copy Nsc1/Nsc2 from hop-to-hop to maintain the values through the chain
- Use Nsi, Nsp, Nsc1, and Nsc2 on the last hop (last Nsi)
-- If on the last Hop
---    If Nsc1 is not set, that is Nsc1==0
----      Output to INPORT
---    Else
----      Copy/Move Nsi, Nsp, Nsc1=>Ipv4TunDst, and Nsc2=>TunId (Vnid)

Change-Id: Ibf1a071c8de4f44a00d2e90df07e8c1df9fee305
Signed-off-by: Brady Johnson <[email protected]>
sfcofl2/src/main/java/org/opendaylight/sfc/l2renderer/SfcL2FlowProgrammerInterface.java
sfcofl2/src/main/java/org/opendaylight/sfc/l2renderer/SfcL2RspProcessor.java
sfcofl2/src/main/java/org/opendaylight/sfc/l2renderer/openflow/SfcL2FlowProgrammerOFimpl.java
sfcofl2/src/main/java/org/opendaylight/sfc/l2renderer/openflow/SfcOpenflowUtils.java
sfcofl2/src/test/java/org/opendaylight/sfc/l2renderer/SfcL2FlowProgrammerTestMoc.java
sfcofl2/src/test/java/org/opendaylight/sfc/l2renderer/SfcL2RspProcessorTest.java

index f2bbcd11a74ecb5987672c917849758cd4cb3b2e..86d03a825d4df5b9d135fd69bbc8618cec63f848 100644 (file)
@@ -1,10 +1,8 @@
 /**
- * Copyright (c) 2014 Ericsson Inc. and others.  All rights reserved.
- *
+ * Copyright (c) 2014 Ericsson 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.sfc.l2renderer;
@@ -54,8 +52,8 @@ public interface SfcL2FlowProgrammerInterface {
     //
     // Table 2, NextHop
     //
-    public void configureNextHopFlow(
-            final String sffNodeName, final long sfpId, final String srcMac, final String dstMac, final boolean isAddFlow);
+    public void configureNextHopFlow(final String sffNodeName, final long sfpId, final String srcMac,
+            final String dstMac, final boolean isAddFlow);
 
     public void configureGroupNextHopFlow(
             final String sffNodeName, final long sfpId, final String srcMac, final long groupId, final String groupName, final boolean isAddFlow);
@@ -73,6 +71,7 @@ public interface SfcL2FlowProgrammerInterface {
             final String port,
             final long pathId,
             final boolean setDscp,
+            final boolean isLastHop,
             final boolean isAddFlow);
 
     public void configureVlanTransportEgressFlow(
@@ -83,6 +82,7 @@ public interface SfcL2FlowProgrammerInterface {
             final String port,
             final long pathId,
             final boolean setDscp,
+            final boolean isLastHop,
             final boolean isAddFlow);
 
     public void configureVxlanGpeTransportEgressFlow(
@@ -90,6 +90,7 @@ public interface SfcL2FlowProgrammerInterface {
             final long nshNsp,
             final short nshNsi,
             final String port,
+            final boolean isLastHop,
             final boolean isAddFlow);
 
     public void configureMplsTransportEgressFlow(
@@ -100,6 +101,14 @@ public interface SfcL2FlowProgrammerInterface {
             final String port,
             final long pathId,
             boolean setDscp,
+            final boolean isLastHop,
+            final boolean isAddFlow);
+
+    public void configureNshNscTransportEgressFlow(
+            String sffNodeName,
+            final long nshNsp,
+            final short nshNsi,
+            String switchPort,
             final boolean isAddFlow);
 
     //
@@ -112,9 +121,12 @@ public interface SfcL2FlowProgrammerInterface {
     public void configureTransportIngressTableMatchAny(final String sffNodeName, final boolean doDrop, final boolean isAddFlow);
     public void configurePathMapperTableMatchAny(final String sffNodeName, final boolean doDrop, final boolean isAddFlow);
     public void configureNextHopTableMatchAny(final String sffNodeName, final boolean doDrop, final boolean isAddFlow);
-    public void configureTransportEgressTableMatchAny(final String sffNodeName, final boolean doDrop, final boolean isAddFlow);
+
+    public void configureTransportEgressTableMatchAny(final String sffNodeName, final boolean doDrop,
+            final boolean isAddFlow);
 
     // group configuration
-    public void configureGroup(final String sffNodeName, final String openflowNodeId, final String sfgName, final long sfgId, int groupType, List<GroupBucketInfo> bucketInfos, final boolean isAddGroup);
+    public void configureGroup(final String sffNodeName, final String openflowNodeId, final String sfgName,
+            final long sfgId, int groupType, List<GroupBucketInfo> bucketInfos, final boolean isAddGroup);
 
 }
index d2dcc9435a105bc3ec97b78fca14ace00e1ff3a1..623f3c1ee8de8bf209a9ace40b9604c9bdb97b69 100644 (file)
@@ -40,8 +40,8 @@ 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.locator.type.Mpls;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.MplsBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -181,7 +181,8 @@ public class SfcL2RspProcessor {
                     null,
                     sffGraph.getPathEgressDpl(entry.getPathId()),
                     entry.getPathId(),
-                    entry.getServiceIndex());
+                    entry.getServiceIndex(),
+                    true);
 
             // Nothing else to be done for the egress tables
             return;
@@ -228,7 +229,8 @@ public class SfcL2RspProcessor {
                 sffDstIngressDpl,
                 dstHopIngressDpl,
                 entry.getPathId(),
-                entry.getServiceIndex());
+                entry.getServiceIndex(),
+                false);
 
     }
 
@@ -365,7 +367,8 @@ public class SfcL2RspProcessor {
                     null,
                     sffGraph.getPathEgressDpl(entry.getPathId()),
                     entry.getPathId(),
-                    entry.getServiceIndex());
+                    entry.getServiceIndex(),
+                    true);
 
             // Nothing else to be done for the egress tables
             return;
@@ -419,7 +422,8 @@ public class SfcL2RspProcessor {
                 sffDstIngressDpl,
                 dstHopIngressDpl,
                 entry.getPathId(),
-                entry.getServiceIndex());
+                entry.getServiceIndex(),
+                false);
     }
 
     private void initializeSff(final String sffName, final long pathId) {
@@ -589,11 +593,11 @@ public class SfcL2RspProcessor {
 
     private void configureGroupNextHopFlow(final String sffName, SffDataPlaneLocator srcSffDpl, long groupId, String groupName,
             final long pathId, final short serviceIndex) {
-        DataPlaneLocator srcDpl = null;
+        //DataPlaneLocator srcDpl = null;
         // currently support only mac
         String srcMac = null;
         if (srcSffDpl != null) {
-            srcDpl = srcSffDpl.getDataPlaneLocator();
+            //srcDpl = srcSffDpl.getDataPlaneLocator();
             srcMac = sfcL2ProviderUtils.getDplPortInfoMac(srcSffDpl);
         }
         String sffNodeName = sfcL2ProviderUtils.getSffOpenFlowNodeName(sffName, pathId);
@@ -605,7 +609,6 @@ public class SfcL2RspProcessor {
         this.sfcL2FlowProgrammer.configureGroupNextHopFlow(sffName, pathId, srcMac, groupId, groupName, addFlow);
     }
 
-    // TODO I think isSf can be removed from this one, and just pass true to the final signature
     // Simple pass-through method that calculates the srcOfsPort
     // and srcMac from the srcSffSfDict, and the dstMac from the dstDpl
     private void configureSffTransportEgressFlow(final String sffName,
@@ -624,7 +627,7 @@ public class SfcL2RspProcessor {
         String srcMac = sfcL2ProviderUtils.getDictPortInfoMac(srcSffSfDict);
         String dstMac = sfcL2ProviderUtils.getSfDplMac(dstSfDpl);
         configureSffTransportEgressFlow(
-                sffName, srcDpl, dstSfDpl, hopDpl, srcOfsPortStr, srcMac, dstMac, pathId, serviceIndex, true);
+                sffName, srcDpl, dstSfDpl, hopDpl, srcOfsPortStr, srcMac, dstMac, pathId, serviceIndex, true, false);
     }
 
     // Simple pass-through method that calculates the srcOfsPort
@@ -634,7 +637,8 @@ public class SfcL2RspProcessor {
                                                  SffDataPlaneLocator dstDpl,
                                                  DataPlaneLocator hopDpl,
                                                  long pathId,
-                                                 short serviceIndex) {
+                                                 short serviceIndex,
+                                                 boolean isLastServiceIndex) {
         String srcOfsPortStr = sfcL2ProviderUtils.getDplPortInfoPort(srcDpl);
         if(srcOfsPortStr == null) {
             throw new RuntimeException(
@@ -646,7 +650,7 @@ public class SfcL2RspProcessor {
         configureSffTransportEgressFlow(sffName,
                 srcDpl.getDataPlaneLocator(),
                 ((dstDpl == null) ? null : dstDpl.getDataPlaneLocator()),
-                hopDpl, srcOfsPortStr, srcMac, dstMac, pathId, serviceIndex, false);
+                hopDpl, srcOfsPortStr, srcMac, dstMac, pathId, serviceIndex, false, isLastServiceIndex);
     }
 
     // This version is only used by the previous 2 configureSffTransportEgressFlow() signatures
@@ -659,7 +663,8 @@ public class SfcL2RspProcessor {
                                                  String dstMac,
                                                  long pathId,
                                                  short serviceIndex,
-                                                 boolean isSf) {
+                                                 boolean isSf,
+                                                 boolean isLastServiceIndex) {
         if(hopDpl == null) {
             throw new RuntimeException(
                     "configureSffTransportEgressFlow SFF [" + sffName + "] hopDpl is null");
@@ -687,23 +692,27 @@ public class SfcL2RspProcessor {
             Integer vlanTag = ((MacAddressLocator) hopLocatorType).getVlanId();
             if(vlanTag == null) {
                 this.sfcL2FlowProgrammer.configureMacTransportEgressFlow(
-                        sffNodeName, srcMac, dstMac, srcOfsPort, pathId, isSf, this.addFlow);
+                        sffNodeName, srcMac, dstMac, srcOfsPort, pathId, isSf, isLastServiceIndex, this.addFlow);
             } else {
                 this.sfcL2FlowProgrammer.configureVlanTransportEgressFlow(
-                        sffNodeName, srcMac, dstMac, vlanTag, srcOfsPort, pathId, isSf, this.addFlow);
+                        sffNodeName, srcMac, dstMac, vlanTag, srcOfsPort, pathId, isSf, isLastServiceIndex, this.addFlow);
             }
         } else if (implementedInterface.equals(Mpls.class)) {
             // MPLS
             long mplsLabel = ((MplsLocator) hopLocatorType).getMplsLabel();
             this.sfcL2FlowProgrammer.configureMplsTransportEgressFlow(
-                    sffNodeName, srcMac, dstMac, mplsLabel, srcOfsPort, pathId, isSf, this.addFlow);
+                    sffNodeName, srcMac, dstMac, mplsLabel, srcOfsPort, pathId, isSf, isLastServiceIndex, this.addFlow);
         } else if (implementedInterface.equals(Ip.class)) {
            //VxLAN-gpe, it is IP/UDP flow with VLAN tag
            if (hopDpl.getTransport().equals(VxlanGpe.class)) {
                 long nsp = pathId;
                 short nsi = serviceIndex;
                 this.sfcL2FlowProgrammer.configureVxlanGpeTransportEgressFlow(
-                        sffNodeName, nsp, nsi, srcOfsPort, this.addFlow);
+                        sffNodeName, nsp, nsi, srcOfsPort, isLastServiceIndex, this.addFlow);
+                if(isLastServiceIndex) {
+                    this.sfcL2FlowProgrammer.configureNshNscTransportEgressFlow(
+                            sffNodeName, nsp, nsi, OutputPortValues.INPORT.toString(), this.addFlow);
+                }
            }
         }
     }
index 1e8b60dd98ddee89f861ee46bd88fa1ac0decc4e..5f7d3c6d13e3842afe537fa460e2e0d91e2c1b0e 100644 (file)
@@ -725,9 +725,9 @@ public class SfcL2FlowProgrammerOFimpl implements SfcL2FlowProgrammerInterface {
     //
     public void configureMacTransportEgressFlow(
             final String sffNodeName, final String srcMac, final String dstMac,
-            String port, final long pathId, boolean setDscp, final boolean isAddFlow) {
+            String port, final long pathId, boolean setDscp, final boolean isLastHop, final boolean isAddFlow) {
         ConfigureTransportEgressThread configureEgressTransportThread =
-                new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isAddFlow);
+                new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isLastHop, isAddFlow);
         try {
             threadPoolExecutorService.execute(configureEgressTransportThread);
         } catch (Exception ex) {
@@ -737,9 +737,10 @@ public class SfcL2FlowProgrammerOFimpl implements SfcL2FlowProgrammerInterface {
 
     public void configureVlanTransportEgressFlow(
             final String sffNodeName, final String srcMac, final String dstMac,
-            final int dstVlan, String port, final long pathId, boolean setDscp, final boolean isAddFlow) {
+            final int dstVlan, String port, final long pathId, boolean setDscp,
+            final boolean isLastHop, final boolean isAddFlow) {
         ConfigureTransportEgressThread configureEgressTransportThread =
-                new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isAddFlow);
+                new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isLastHop, isAddFlow);
         configureEgressTransportThread.setDstVlan(dstVlan);
         try {
             threadPoolExecutorService.execute(configureEgressTransportThread);
@@ -749,9 +750,10 @@ public class SfcL2FlowProgrammerOFimpl implements SfcL2FlowProgrammerInterface {
     }
 
     public void configureVxlanGpeTransportEgressFlow(
-            final String sffNodeName, final long nshNsp, final short nshNsi, String port, final boolean isAddFlow) {
+            final String sffNodeName, final long nshNsp, final short nshNsi, String port,
+            final boolean isLastHop, final boolean isAddFlow) {
         ConfigureTransportEgressThread configureEgressTransportThread =
-                new ConfigureTransportEgressThread(sffNodeName, null, null, port, nshNsp, false, isAddFlow);
+                new ConfigureTransportEgressThread(sffNodeName, null, null, port, nshNsp, false, isLastHop, isAddFlow);
         configureEgressTransportThread.setNshNsp(nshNsp);
         configureEgressTransportThread.setNshNsi(nshNsi);
         try {
@@ -763,10 +765,11 @@ public class SfcL2FlowProgrammerOFimpl implements SfcL2FlowProgrammerInterface {
 
     public void configureMplsTransportEgressFlow(
             final String sffNodeName, final String srcMac, final String dstMac,
-            final long mplsLabel, String port, final long pathId, boolean setDscp, final boolean isAddFlow) {
+            final long mplsLabel, String port, final long pathId, boolean setDscp,
+            final boolean isLastHop, final boolean isAddFlow) {
 
         ConfigureTransportEgressThread configureEgressTransportThread =
-                new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isAddFlow);
+                new ConfigureTransportEgressThread(sffNodeName, srcMac, dstMac, port, pathId, setDscp, isLastHop, isAddFlow);
         configureEgressTransportThread.setMplsLabel(mplsLabel);
         try {
             threadPoolExecutorService.execute(configureEgressTransportThread);
@@ -786,11 +789,12 @@ public class SfcL2FlowProgrammerOFimpl implements SfcL2FlowProgrammerInterface {
         String port;
         long pathId;
         boolean setDscp;
+        boolean isLastHop;
         boolean isAddFlow;
 
         public ConfigureTransportEgressThread(
                 final String sffNodeName, String srcMac, String dstMac, String port,
-                final long pathId, boolean setDscp, boolean isAddFlow) {
+                final long pathId, boolean setDscp, final boolean isLastHop, boolean isAddFlow) {
             super();
             this.sffNodeName = sffNodeName;
             this.srcMac = srcMac;
@@ -802,6 +806,7 @@ public class SfcL2FlowProgrammerOFimpl implements SfcL2FlowProgrammerInterface {
             this.port = port;
             this.pathId = pathId;
             this.setDscp = setDscp;
+            this.isLastHop = isLastHop;
             this.isAddFlow = isAddFlow;
         }
         public void setDstVlan(final int dstVlan) { this.dstVlan = dstVlan; }
@@ -817,15 +822,14 @@ public class SfcL2FlowProgrammerOFimpl implements SfcL2FlowProgrammerInterface {
 
                 int flowPriority = FLOW_PRIORITY_TRANSPORT_EGRESS;
 
-                int order = 0;
-                List<Action> actionList = new ArrayList<Action>();
+                //
+                // Matches
                 MatchBuilder match = new MatchBuilder();
 
                 if (this.nshNsp >=0 && this.nshNsi >= 0) {
-                    // If its NSH, then we dont need the metadata
+                    // If its NSH, then we dont need the metadata, match on Nsp/Nsi instead
                     SfcOpenflowUtils.addMatchNshNsp(match, this.nshNsp);
                     SfcOpenflowUtils.addMatchNshNsi(match, this.nshNsi);
-                    actionList.add(SfcOpenflowUtils.createActionNxMoveTunIdRegister(order++));
                 } else {
                     // Match on the metadata pathId
                     SfcOpenflowUtils.addMatchMetada(match, getMetadataSFP(this.pathId), METADATA_MASK_SFP_MATCH);
@@ -839,11 +843,37 @@ public class SfcL2FlowProgrammerOFimpl implements SfcL2FlowProgrammerInterface {
                     flowPriority -= 10;
                 }
 
-                // Set the macSrc
+
+                //
+                // Actions
+                int order = 0;
+                List<Action> actionList = new ArrayList<Action>();
+
+                // Set the macSrc, if present
                 if(this.srcMac != null) {
                     actionList.add(SfcOpenflowUtils.createActionSetDlSrc(this.srcMac, order++));
                 }
 
+                // Nsh stuff, if present
+                if (this.nshNsp >=0 && this.nshNsi >= 0) {
+                    Action mvNsc1;
+                    Action mvNsc2;
+                    if(this.isLastHop) {
+                        // On the last hop Copy/Move Nsi, Nsp, Nsc1=>TunIpv4Dst, and Nsc2=>TunId (Vnid)
+                        actionList.add(SfcOpenflowUtils.createActionNxMoveNsi(order++));
+                        actionList.add(SfcOpenflowUtils.createActionNxMoveNsp(order++));
+                        mvNsc1 = SfcOpenflowUtils.createActionNxMoveNsc1ToTunIpv4DstRegister(order++);
+                        mvNsc2 = SfcOpenflowUtils.createActionNxMoveNsc2ToTunIdRegister(order++);
+                    } else {
+                        // If its not the last hop, Copy/Move Nsc1/Nsc2 to the next hop
+                        mvNsc1 = SfcOpenflowUtils.createActionNxMoveNsc1(order++);
+                        mvNsc2 = SfcOpenflowUtils.createActionNxMoveNsc2(order++);
+                    }
+                    actionList.add(SfcOpenflowUtils.createActionNxMoveTunIdRegister(order++));
+                    actionList.add(mvNsc1);
+                    actionList.add(mvNsc2);
+                }
+
                 // Optionally write the DSCP with the pathId
                 if(this.setDscp) {
                     // In order to set the IP DSCP, we need to match IPv4
@@ -897,6 +927,92 @@ public class SfcL2FlowProgrammerOFimpl implements SfcL2FlowProgrammerInterface {
         }
     }
 
+    // For NSH, Return the packet to INPORT if the NSH Nsc1 Register is not present (==0)
+    // If it is present, it will be handled in ConfigureTransportEgressFlowThread()
+    // This flow will have a higher priority than the flow created in ConfigureTransportEgressFlowThread()
+    public void configureNshNscTransportEgressFlow(final String sffNodeName, final long nshNsp, final short nshNsi,String port, final boolean isAddFlow) {
+        // This is the last table, cant set next table AND doDrop should be false
+        ConfigureNshNscTransportEgressFlowThread configureNshNscTransportEgressFlowThread =
+                new ConfigureNshNscTransportEgressFlowThread(sffNodeName, nshNsp, nshNsi, port, isAddFlow);
+        try {
+            threadPoolExecutorService.execute(configureNshNscTransportEgressFlowThread);
+        } catch (Exception ex) {
+            LOG.error(LOGSTR_THREAD_QUEUE_FULL, ex.toString());
+        }
+    }
+
+    private class ConfigureNshNscTransportEgressFlowThread implements Runnable {
+        private String sffNodeName;
+        private final long nshNsp;
+        private final short nshNsi;
+        private String port;
+        private boolean isAddFlow;
+
+        public ConfigureNshNscTransportEgressFlowThread(
+                final String sffNodeName, final long nshNsp, final short nshNsi,String port, final boolean isAddFlow) {
+            this.sffNodeName = sffNodeName;
+            this.nshNsp = nshNsp;
+            this.nshNsi = nshNsi;
+            this.port = port;
+            this.isAddFlow = isAddFlow;
+        }
+
+        @Override
+        public void run() {
+            try {
+                LOG.debug("SfcProviderSffFlowWriter.ConfigureNshNscTransportEgressFlowThread, sff [{}]", this.sffNodeName);
+
+
+                //
+                // Match any
+                MatchBuilder match = new MatchBuilder();
+                SfcOpenflowUtils.addMatchNshNsp(match, this.nshNsp);
+                SfcOpenflowUtils.addMatchNshNsi(match, this.nshNsi);
+                SfcOpenflowUtils.addMatchNshNsc1(match, 0l);
+
+                //
+                // Create the actions
+                int order = 0;
+                Action outPortBuilder = SfcOpenflowUtils.createActionOutPort(this.port, order++);
+
+                List<Action> actionList = new ArrayList<Action>();
+                actionList.add(outPortBuilder);
+
+                // Create an Apply Action
+                ApplyActionsBuilder aab = new ApplyActionsBuilder();
+                aab.setAction(actionList);
+
+                // Wrap our Apply Action in an Instruction
+                InstructionBuilder ib = new InstructionBuilder();
+                ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+                ib.setOrder(0);
+                ib.setKey(new InstructionKey(0));
+
+                // Put our Instruction in a list of Instructions
+                InstructionsBuilder isb = SfcOpenflowUtils.createInstructionsBuilder(ib);
+
+                //
+                // Create and configure the FlowBuilder
+                FlowBuilder transportIngressFlow =
+                        SfcOpenflowUtils.createFlowBuilder(
+                                TABLE_INDEX_TRANSPORT_EGRESS,
+                                FLOW_PRIORITY_TRANSPORT_EGRESS+10,
+                                "MatchAny",
+                                match,
+                                isb);
+
+                if (isAddFlow) {
+                    writeFlowToConfig(sffNodeName, transportIngressFlow);
+                } else {
+                    removeFlowFromConfig(sffNodeName, transportIngressFlow);
+                }
+            } catch (Exception e) {
+                LOG.error("ConfigureNshNscTransportEgressFlowThread writer caught an Exception: ", e);
+            }
+        }
+    }
+
+
     @Override
     public void configureGroup(String sffNodeName, String openflowNodeId, String sfgName, long sfgId, int groupType,
             List<GroupBucketInfo> bucketInfos, boolean isAddGroup) {
index 92b99162341633d7f38c786fd6a1064bf6fa657a..0ba44506853656f2f8036604e3bd6b458d7e77cc 100644 (file)
@@ -81,6 +81,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 
 // Import Nicira extension
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.DstChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc1CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNshc2CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNsiCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxNspCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIdCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxTunIpv4DstCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder;
@@ -100,13 +104,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMoveBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.nx.reg.move.SrcBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.SrcChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNspCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxTunIdCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc1CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNshc2CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxNsiCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxNspKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nsp.grouping.NxmNxNspBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxNsiKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nshc._1.grouping.NxmNxNshc1Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nsi.grouping.NxmNxNsiBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxNshc1Key;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlowBuilder;
@@ -223,7 +233,7 @@ public class SfcOpenflowUtils {
 
     public static void addMatchIpProtocol(MatchBuilder match, final short ipProtocol) {
         IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version
-        ipMatch.setIpProtocol((short) ipProtocol);
+        ipMatch.setIpProtocol(ipProtocol);
 
         match.setIpMatch(ipMatch.build());
     }
@@ -254,7 +264,7 @@ public class SfcOpenflowUtils {
         match.setEthernetMatch(eth.build());
 
         ProtocolMatchFieldsBuilder protomatch = new ProtocolMatchFieldsBuilder();
-        protomatch.setMplsLabel((long) label);
+        protomatch.setMplsLabel(label);
         match.setProtocolMatchFields(protomatch.build());
     }
 
@@ -334,24 +344,34 @@ public class SfcOpenflowUtils {
 
     public static void addMatchNshNsp(MatchBuilder match, long nsp) {
         NxAugMatchNodesNodeTableFlow am =
-                new NxAugMatchNodesNodeTableFlowBuilder()
+            new NxAugMatchNodesNodeTableFlowBuilder()
                 .setNxmNxNsp(new NxmNxNspBuilder()
-                .setValue(nsp)
-                .build())
+                    .setValue(nsp)
+                    .build())
                 .build();
         addExtension(match, NxmNxNspKey.class, am);
     }
 
     public static void addMatchNshNsi(MatchBuilder match, short nsi) {
         NxAugMatchNodesNodeTableFlow am =
-                new NxAugMatchNodesNodeTableFlowBuilder()
+            new NxAugMatchNodesNodeTableFlowBuilder()
                 .setNxmNxNsi(new NxmNxNsiBuilder()
-                .setNsi(nsi)
-                .build())
+                    .setNsi(nsi)
+                    .build())
                 .build();
         addExtension(match, NxmNxNsiKey.class, am);
     }
 
+    public static void addMatchNshNsc1(MatchBuilder match, long nsc) {
+        NxAugMatchNodesNodeTableFlow am =
+            new NxAugMatchNodesNodeTableFlowBuilder()
+                .setNxmNxNshc1(new NxmNxNshc1Builder()
+                    .setValue(nsc)
+                    .build())
+                .build();
+        addExtension(match, NxmNxNshc1Key.class, am);
+    }
+
 
     //
     // Create Action methods
@@ -621,7 +641,8 @@ public class SfcOpenflowUtils {
         }
     }
 
-    public static org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action nxMoveRegAction(
+    public static org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action
+    nxMoveRegAction(
             SrcChoice srcChoice, DstChoice dstChoice, int endOffset, boolean groupBucket) {
         NxRegMove r = new NxRegMoveBuilder()
             .setSrc(new SrcBuilder()
@@ -672,6 +693,78 @@ public class SfcOpenflowUtils {
         return ab.build();
     }
 
+    public static Action createActionNxMoveNsc1(int order) {
+        ActionBuilder ab = createActionBuilder(order);
+        ab.setAction(nxMoveRegAction(
+                new SrcNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),
+                new DstNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),
+                31,
+                false));
+
+        return ab.build();
+    }
+
+    public static Action createActionNxMoveNsc2(int order) {
+        ActionBuilder ab = createActionBuilder(order);
+        ab.setAction(nxMoveRegAction(
+                new SrcNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),
+                new DstNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),
+                31,
+                false));
+
+        return ab.build();
+    }
+
+    public static Action createActionNxMoveNsi(int order) {
+        ActionBuilder ab = createActionBuilder(order);
+        ab.setAction(nxMoveRegAction(
+                new SrcNxNsiCaseBuilder().setNxNsiDst(Boolean.TRUE).build(),
+                new DstNxNsiCaseBuilder().setNxNsiDst(Boolean.TRUE).build(),
+                7,  // Service Index is 8 bits, moving bits 0-7
+                false));
+
+        return ab.build();
+    }
+
+    public static Action createActionNxMoveNsp(int order) {
+        ActionBuilder ab = createActionBuilder(order);
+        ab.setAction(nxMoveRegAction(
+                new SrcNxNspCaseBuilder().setNxNspDst(Boolean.TRUE).build(),
+                new DstNxNspCaseBuilder().setNxNspDst(Boolean.TRUE).build(),
+                23,  // Service Index is 24 bits, moving bits 0-23
+                false));
+
+        return ab.build();
+    }
+
+    // Used by NSH to move one of the NSH Context registers (NSC) to
+    // the Tunnel Id (VNID) Register. This is for the RSP NSH egress tunnel.
+    // GBP will set the Tunnel ID (VNID) in NSC2 and pass it along the
+    // chain, and in the last SFF, we will use it to set the VNID
+    // This will only work with this patch: https://git.opendaylight.org/gerrit/#/c/19478
+    public static Action createActionNxMoveNsc2ToTunIdRegister(int order) {
+        ActionBuilder ab = createActionBuilder(order);
+        ab.setAction(nxMoveRegAction(
+                new SrcNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),
+                new DstNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(),
+                31,
+                false));
+
+        return ab.build();
+    }
+
+    // This will only work with this patch: https://git.opendaylight.org/gerrit/#/c/19478
+    public static Action createActionNxMoveNsc1ToTunIpv4DstRegister(int order) {
+        ActionBuilder ab = createActionBuilder(order);
+        ab.setAction(nxMoveRegAction(
+                new SrcNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),
+                new DstNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),
+                31,
+                false));
+
+        return ab.build();
+    }
+
     public static WriteMetadataCase createInstructionMetadata(int order, BigInteger metadataVal, BigInteger metadataMask) {
         WriteMetadataBuilder wmb = new WriteMetadataBuilder();
         wmb.setMetadata(metadataVal);
index 58e3deef6b5cd3aadba13fc5eaf501e6477cdd4d..99f9d5230a7dbd5df1136be12e96525045c6ae4c 100644 (file)
@@ -31,6 +31,7 @@ public class SfcL2FlowProgrammerTestMoc implements SfcL2FlowProgrammerInterface
         configureVlanTransportEgressFlowMethodIndex,
         configureVxlanGpeTransportEgressFlowMethodIndex,
         configureMplsTransportEgressFlowMethodIndex,
+        configureNshNscTransportEgressFlowMethodIndex,
 
         configureTransportIngressTableMatchAnyMethodIndex,
         configurePathMapperTableMatchAnyMethodIndex,
@@ -173,6 +174,7 @@ public class SfcL2FlowProgrammerTestMoc implements SfcL2FlowProgrammerInterface
             String port,
             long pathId,
             boolean setDscp,
+            final boolean isLastHop,
             boolean isAddFlow) {
         incrementMethodCalled(MethodIndeces.configureMacTransportEgressFlowMethodIndex);
     }
@@ -186,6 +188,7 @@ public class SfcL2FlowProgrammerTestMoc implements SfcL2FlowProgrammerInterface
             String port,
             long pathId,
             boolean setDscp,
+            final boolean isLastHop,
             boolean isAddFlow) {
         incrementMethodCalled(MethodIndeces.configureVlanTransportEgressFlowMethodIndex);
     }
@@ -196,6 +199,7 @@ public class SfcL2FlowProgrammerTestMoc implements SfcL2FlowProgrammerInterface
             long nshNsp,
             short nshNsi,
             String port,
+            final boolean isLastHop,
             boolean isAddFlow) {
         incrementMethodCalled(MethodIndeces.configureVxlanGpeTransportEgressFlowMethodIndex);
     }
@@ -209,10 +213,21 @@ public class SfcL2FlowProgrammerTestMoc implements SfcL2FlowProgrammerInterface
             String port,
             long pathId,
             boolean setDscp,
+            final boolean isLastHop,
             boolean isAddFlow) {
         incrementMethodCalled(MethodIndeces.configureMplsTransportEgressFlowMethodIndex);
     }
 
+    @Override
+    public void configureNshNscTransportEgressFlow(
+            String sffNodeName,
+            final long nshNsp,
+            final short nshNsi,
+            String switchPort,
+            final boolean isAddFlow) {
+        incrementMethodCalled(MethodIndeces.configureNshNscTransportEgressFlowMethodIndex);
+    }
+
     //---------------------------------------------
     //
     //            Match Any methods
index 6e38297f77331d9a02d1500f25a11f79db6d24f8..6561a4c531e7f0f85308d093f31f21c424e53cff 100644 (file)
@@ -42,20 +42,29 @@ public class SfcL2RspProcessorTest {
     }
 
     private void assertMethodCallCount(SfcL2FlowProgrammerTestMoc.MethodIndeces methodIndex, int count) {
-        LOG.info("assertMethodCallCount [{}] comparing [{}] to expected count [{}]", methodIndex, flowProgrammerTestMoc.getMethodCalledCount(methodIndex), count);
-        assertTrue(flowProgrammerTestMoc.getMethodCalledCount(methodIndex) == count);
+        assertEquals(count, flowProgrammerTestMoc.getMethodCalledCount(methodIndex));
     }
 
     private void assertMatchAnyMethodsCalled() {
+        // Default values
+        assertMatchAnyMethodsCalled(2, 2, 2, 2);
+    }
+
+    private void assertMatchAnyMethodsCalled(
+            int transportIngressCount, int pathMapperCount, int nextHopCount, int transportEgressCount) {
         // Each of these is called once per SFF, and there are 2 SFFs
         assertMethodCallCount(
-                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureTransportIngressTableMatchAnyMethodIndex, 2);
+                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureTransportIngressTableMatchAnyMethodIndex,
+                transportIngressCount);
         assertMethodCallCount(
-                SfcL2FlowProgrammerTestMoc.MethodIndeces.configurePathMapperTableMatchAnyMethodIndex, 2);
+                SfcL2FlowProgrammerTestMoc.MethodIndeces.configurePathMapperTableMatchAnyMethodIndex,
+                pathMapperCount);
         assertMethodCallCount(
-                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureNextHopTableMatchAnyMethodIndex, 2);
+                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureNextHopTableMatchAnyMethodIndex,
+                nextHopCount);
         assertMethodCallCount(
-                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureTransportEgressTableMatchAnyMethodIndex, 2);
+                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureTransportEgressTableMatchAnyMethodIndex,
+                transportEgressCount);
     }
 
     @Before
@@ -67,6 +76,10 @@ public class SfcL2RspProcessorTest {
         sfcUtilsTestMock.resetCache();
     }
 
+    // TODO tests to add:
+    //   - An SFF with > 1 SF
+    //   - An SF of type TCP Proxy
+
     @Test
     public void testVlanFlowCreation() {
         LOG.info("SfcL2RspProcessorTest testVlanFlowCreation");
@@ -128,4 +141,26 @@ public class SfcL2RspProcessorTest {
         assertMethodCallCount(
                 SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpeTransportEgressFlowMethodIndex, 4);
     }
+
+    @Test
+    public void testNshOneHopFlowCreation() {
+        LOG.info("SfcL2RspProcessorTest testNshOneHopFlowCreation");
+
+        List<Class<? extends ServiceFunctionTypeIdentity>> sfOneHopTypes;
+        sfOneHopTypes = new ArrayList<Class<? extends ServiceFunctionTypeIdentity>>();
+        sfOneHopTypes.add(Firewall.class);
+
+        RenderedServicePath nshRsp = rspBuilder.createRspFromSfTypes(sfOneHopTypes, VxlanGpe.class);
+        this.sfcL2RspProcessor.processRenderedServicePath(nshRsp, true);
+
+        assertMatchAnyMethodsCalled(1, 1, 1, 1);
+        assertMethodCallCount(
+                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpeTransportIngressFlowMethodIndex, 2);
+        assertMethodCallCount(
+                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpePathMapperFlowMethodIndex, 0);
+        assertMethodCallCount(
+                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpeNextHopFlowMethodIndex, 1);
+        assertMethodCallCount(
+                SfcL2FlowProgrammerTestMoc.MethodIndeces.configureVxlanGpeTransportEgressFlowMethodIndex, 2);
+    }
 }