BUG 6403 - outport cant be the same as inport 69/43869/1
authorBrady Johnson <brady.allen.johnson@ericsson.com>
Fri, 12 Aug 2016 16:23:35 +0000 (18:23 +0200)
committerBrady Johnson <brady.allen.johnson@ericsson.com>
Fri, 12 Aug 2016 16:32:27 +0000 (16:32 +0000)
- the inport cant be the same as the outport. if they are,
  outport must be the string INPORT, else the pkt will be
  dropped according to openflow spec.
- https://bugs.opendaylight.org/show_bug.cgi?id=6403

Change-Id: If16523ddd5eae0f94806f0bbdc7e1af1f4869267
Signed-off-by: Brady Johnson <brady.allen.johnson@ericsson.com>
sfc-renderers/sfc-openflow-renderer/src/main/java/org/opendaylight/sfc/ofrenderer/openflow/SfcOfFlowProgrammerImpl.java
sfc-renderers/sfc-openflow-renderer/src/test/java/org/opendaylight/sfc/ofrenderer/SfcOfFlowProgrammerTest.java
sfc-util/sfc-openflow-utils/src/main/java/org/opendaylight/sfc/util/openflow/SfcOpenflowUtils.java

index d976a2d6566f9bf8edce625ad3a569a2f661cb52..14849a2fbe0f2dd250a065d6f07ae1f7992783bb 100644 (file)
@@ -15,7 +15,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import org.opendaylight.sfc.ofrenderer.sfg.GroupBucketInfo;
-//import org.opendaylight.sfc.sfc_ovs.provider.SfcOvsUtil;
+import org.opendaylight.sfc.sfc_ovs.provider.SfcOvsUtil;
 import org.opendaylight.sfc.util.openflow.SfcOpenflowUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
@@ -42,6 +42,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
@@ -1185,9 +1186,44 @@ public class SfcOfFlowProgrammerImpl implements SfcOfFlowProgrammerInterface {
     public void configureVxlanGpeTransportEgressFlow(
             final String sffNodeName, final long nshNsp, final short nshNsi, String port) {
 
+        // When outputing to an outport, if inport==outport, then according to the
+        // openflow spec, the packet will be dropped. To avoid this, outport must
+        // be set to INPORT. This method writes 2 flows to avoid this situation:
+        //   flow1: if inport==port, actions=output:INPORT (higher priority than flow2)
+        //   flow2: actions=output:port (flow2 is basically the else condition)
+
+        Long vxgpePort = null;
+        try {
+            vxgpePort = SfcOvsUtil.getVxlanGpeOfPort(sffNodeName);
+        } catch(Exception e) {
+            // getVxlanGpeOfPort throws NPE in Unit Tests, which is ok
+        }
+
+        if(vxgpePort != null) {
+            String vxgpePortStr = "output:" + vxgpePort.toString();
+            configureVxlanGpeTransportEgressFlowPorts(sffNodeName, nshNsp, nshNsi, vxgpePortStr, OutputPortValues.INPORT.toString());
+            configureVxlanGpeTransportEgressFlowPorts(sffNodeName, nshNsp, nshNsi, OutputPortValues.INPORT.toString(), vxgpePortStr);
+        } else {
+            configureVxlanGpeTransportEgressFlowPorts(sffNodeName, nshNsp, nshNsi, port, port);
+        }
+    }
+
+    /**
+     * Simple call through for configureVxlanGpeTransportEgressFlow()
+     */
+    private void configureVxlanGpeTransportEgressFlowPorts(
+            final String sffNodeName, final long nshNsp, final short nshNsi, String inport, String outport) {
+        int flowPriority = FLOW_PRIORITY_TRANSPORT_EGRESS;
+
         MatchBuilder match = new MatchBuilder();
         SfcOpenflowUtils.addMatchNshNsp(match, nshNsp);
         SfcOpenflowUtils.addMatchNshNsi(match, nshNsi);
+        if(!inport.startsWith(OutputPortValues.INPORT.toString())) {
+            // if we output to a port that's the same as the inport, the pkt will be dropped
+            SfcOpenflowUtils.addMatchInPort(match, new NodeConnectorId(inport));
+            outport = OutputPortValues.INPORT.toString();
+            flowPriority += 5;
+        }
 
         int order = 0;
         List<Action> actionList = new ArrayList<Action>();
@@ -1201,15 +1237,9 @@ public class SfcOfFlowProgrammerImpl implements SfcOfFlowProgrammerInterface {
         /* Need to set TUN_GPE_NP for VxLAN-gpe port */
         actionList.add(SfcOpenflowUtils.createActionNxLoadTunGpeNp(TUN_GPE_NP_NSH, order++));
 
-        String vxgpePortStr = port;
-        //Long vxgpePort = SfcOvsUtil.getVxlanGpeOfPort(sffNodeName);
-        //if(vxgpePort != null) {
-        //    vxgpePortStr = "output:" + vxgpePort.toString();
-        //}
-
         FlowBuilder transportEgressFlow =
-                configureTransportEgressFlow(match, actionList, vxgpePortStr, order,
-                        FLOW_PRIORITY_TRANSPORT_EGRESS,
+                configureTransportEgressFlow(match, actionList, outport, order,
+                        flowPriority,
                         TRANSPORT_EGRESS_NSH_VXGPE_COOKIE);
         sfcOfFlowWriter.writeFlow(flowRspId, sffNodeName, transportEgressFlow);
     }
index 043b457851b1c947a54b86a01b343047d3d3e47f..8fc0350c9e46d74461968dbe9929691c0a985a41 100644 (file)
@@ -592,7 +592,9 @@ public class SfcOfFlowProgrammerTest {
         flowBuilder = sfcOfFlowWriter.getFlowBuilder();
 
         assertEquals(flowBuilder.getTableId().shortValue(), SfcOfFlowProgrammerImpl.TABLE_INDEX_TRANSPORT_EGRESS);
-        assertEquals(flowBuilder.getPriority().intValue(), SfcOfFlowProgrammerImpl.FLOW_PRIORITY_TRANSPORT_EGRESS);
+        int priority = flowBuilder.getPriority().intValue();
+        assertTrue((priority == SfcOfFlowProgrammerImpl.FLOW_PRIORITY_TRANSPORT_EGRESS) ||
+                   (priority == SfcOfFlowProgrammerImpl.FLOW_PRIORITY_TRANSPORT_EGRESS+5));
         checkMatchNsh(flowBuilder.build(), NSP, NSI);
 
         Instructions isb = flowBuilder.getInstructions();
index b590e8af88867479892ca36bdd4f0a59ca78cdaf..a981dc044563fe3e222402ac60f30e3577a91f5a 100644 (file)
@@ -594,6 +594,10 @@ public class SfcOpenflowUtils {
         match.setInPort(new NodeConnectorId(nodeId + ":" + inPort));
     }
 
+    public static void addMatchInPort(MatchBuilder match, NodeConnectorId nodeConnId) {
+        match.setInPort(nodeConnId);
+    }
+
     //
     // Create Action methods
     //