DROP and FLOOD/Broadcast Support 84/4784/2
authorMadhu Venugopal <mavenugo@gmail.com>
Sun, 26 Jan 2014 04:49:19 +0000 (20:49 -0800)
committerMadhu Venugopal <mavenugo@gmail.com>
Sun, 26 Jan 2014 07:30:44 +0000 (23:30 -0800)
Change-Id: I6cbf14382c9855387e052e133a2c91baad017283
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF13ProviderManager.java

index 53bd3ec63d1196e3c98f7aa630e497c80d7e2e67..34876e8a8ac3bcb24a8099c2378ba88360c32956 100644 (file)
@@ -47,6 +47,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DecNwTtlCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCaseBuilder;
@@ -75,8 +76,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
@@ -253,9 +256,7 @@ class OF13ProviderManager extends ProviderNetworkManager {
          * Action: Drop w/ a low priority
          */
 
-         // TODO : Drop flows causing problems with other existing flows. Commenting them out for now till it is fixed.
-
-         // writeDropSrcIface(dpid, localPort);
+         writeDropSrcIface(dpid, localPort);
 
          /*
           * Table(2) Rule #1
@@ -299,8 +300,7 @@ class OF13ProviderManager extends ProviderNetworkManager {
            * table=2,priority=8192,tun_id=0x5 actions=drop
            */
 
-           // TODO : Drop flows causing problems with other existing flows. Commenting them out for now till it is fixed.
-           // writeLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId);
+           writeLocalTableMiss(dpid, TABLE_2_LOCAL_FORWARD, segmentationId);
     }
 
     private void programLocalIngressTunnelBridgeRules(Node node, Long dpid, String segmentationId, String attachedMac, long tunnelOFPort, long localPort) {
@@ -759,6 +759,7 @@ class OF13ProviderManager extends ProviderNetworkManager {
         flowBuilder.setId(new FlowId(flowId));
         FlowKey key = new FlowKey(new FlowId(flowId));
         flowBuilder.setBarrier(false);
+        flowBuilder.setStrict(true);
         flowBuilder.setTableId((short) 0);
         flowBuilder.setKey(key);
         flowBuilder.setFlowName(flowId);
@@ -844,18 +845,39 @@ class OF13ProviderManager extends ProviderNetworkManager {
 
         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
 
+        String flowId = "TunnelFloodOut_"+segmentationId;
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setBarrier(true);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setPriority(16384);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+
+        Flow flow = this.getFlow(flowBuilder, nodeBuilder);
         // Instantiate the Builders for the OF Actions and Instructions
         InstructionBuilder ib = new InstructionBuilder();
         InstructionsBuilder isb = new InstructionsBuilder();
-
-        // Instructions List Stores Individual Instructions
         List<Instruction> instructions = new ArrayList<Instruction>();
-
+        List<Instruction> existingInstructions = null;
+        if (flow != null) {
+            Instructions ins = flow.getInstructions();
+            if (ins != null) {
+                existingInstructions = ins.getInstruction();
+            }
+        }
         // GOTO Instuction
         createGotoTableInstructions(ib, localTable);
+        ib.setOrder(0);
+        ib.setKey(new InstructionKey(0));
         instructions.add(ib.build());
         // Set the Output Port/Iface
-        createOutputPortInstructions(ib, dpidLong, OFPortOut);
+        createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
+        ib.setOrder(1);
+        ib.setKey(new InstructionKey(1));
         instructions.add(ib.build());
 
         // Add InstructionBuilder to the Instruction(s)Builder List
@@ -864,17 +886,6 @@ class OF13ProviderManager extends ProviderNetworkManager {
         // Add InstructionsBuilder to FlowBuilder
         flowBuilder.setInstructions(isb.build());
 
-        String flowId = "TunnelFloodOut_"+segmentationId;
-        // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setBarrier(true);
-        flowBuilder.setTableId(writeTable);
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(16384);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
         writeFlow(flowBuilder, nodeBuilder);
     }
 
@@ -995,15 +1006,34 @@ class OF13ProviderManager extends ProviderNetworkManager {
         flowBuilder.setMatch(createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
         flowBuilder.setMatch(createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"), new MacAddress("01:00:00:00:00:00")).build());
 
+        String flowId = "BcastOut_"+segmentationId;
+        // Add Flow Attributes
+        flowBuilder.setId(new FlowId(flowId));
+        FlowKey key = new FlowKey(new FlowId(flowId));
+        flowBuilder.setBarrier(false);
+        flowBuilder.setTableId(writeTable);
+        flowBuilder.setKey(key);
+        flowBuilder.setPriority(16384);
+        flowBuilder.setFlowName(flowId);
+        flowBuilder.setHardTimeout(0);
+        flowBuilder.setIdleTimeout(0);
+        Flow flow = this.getFlow(flowBuilder, nodeBuilder);
         // Instantiate the Builders for the OF Actions and Instructions
         InstructionBuilder ib = new InstructionBuilder();
         InstructionsBuilder isb = new InstructionsBuilder();
-
-        // Instructions List Stores Individual Instructions
         List<Instruction> instructions = new ArrayList<Instruction>();
+        List<Instruction> existingInstructions = null;
+        if (flow != null) {
+            Instructions ins = flow.getInstructions();
+            if (ins != null) {
+                existingInstructions = ins.getInstruction();
+            }
+        }
 
         // Broken OutPort TODO: localPort needs to be a list of Ports)
-        createOutputPortInstructions(ib, dpidLong, localPort);
+        createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
+        ib.setOrder(0);
+        ib.setKey(new InstructionKey(0));
         instructions.add(ib.build());
 
         // Add InstructionBuilder to the Instruction(s)Builder List
@@ -1012,17 +1042,6 @@ class OF13ProviderManager extends ProviderNetworkManager {
         // Add InstructionsBuilder to FlowBuilder
         flowBuilder.setInstructions(isb.build());
 
-        String flowId = "BcastOut_"+segmentationId;
-        // Add Flow Attributes
-        flowBuilder.setId(new FlowId(flowId));
-        FlowKey key = new FlowKey(new FlowId(flowId));
-        flowBuilder.setBarrier(false);
-        flowBuilder.setTableId(writeTable);
-        flowBuilder.setKey(key);
-        flowBuilder.setPriority(16384);
-        flowBuilder.setFlowName(flowId);
-        flowBuilder.setHardTimeout(0);
-        flowBuilder.setIdleTimeout(0);
         writeFlow(flowBuilder, nodeBuilder);
     }
 
@@ -1066,6 +1085,7 @@ class OF13ProviderManager extends ProviderNetworkManager {
         flowBuilder.setId(new FlowId(flowId));
         FlowKey key = new FlowKey(new FlowId(flowId));
         flowBuilder.setBarrier(false);
+        flowBuilder.setStrict(true);
         flowBuilder.setTableId(writeTable);
         flowBuilder.setKey(key);
         flowBuilder.setPriority(8192);
@@ -1075,6 +1095,26 @@ class OF13ProviderManager extends ProviderNetworkManager {
         writeFlow(flowBuilder, nodeBuilder);
     }
 
+    private Flow getFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
+        IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
+        if (mdsalConsumer == null) {
+            logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
+            return null;
+        }
+
+        dataBrokerService = mdsalConsumer.getDataBrokerService();
+
+        if (dataBrokerService == null) {
+            logger.error("ERROR finding reference for DataBrokerService. Please check out the MD-SAL support on the Controller.");
+            return null;
+        }
+
+        InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
+                .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
+                new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
+        return (Flow)dataBrokerService.readConfigurationData(path1);
+    }
+
     private void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
         IMDSALConsumer mdsalConsumer = (IMDSALConsumer) ServiceHelper.getInstance(IMDSALConsumer.class, "default", this);
         if (mdsalConsumer == null) {
@@ -1412,6 +1452,58 @@ class OF13ProviderManager extends ProviderNetworkManager {
         return ib;
     }
 
+    /**
+     * Create Output Port Instruction
+     *
+     * @param ib       Map InstructionBuilder without any instructions
+     * @param dpidLong Long the datapath ID of a switch/node
+     * @param port     Long representing a port on a switch/node
+     * @return ib InstructionBuilder Map with instructions
+     */
+    protected static InstructionBuilder createOutputPortInstructions(InstructionBuilder ib, Long dpidLong, Long port , List<Instruction> instructions) {
+
+        NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
+        logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
+
+        List<Action> actionList = new ArrayList<Action>();
+        ActionBuilder ab = new ActionBuilder();
+
+        List<Action> existingActions = null;
+        if (instructions != null) {
+            for (Instruction in : instructions) {
+                if (in.getInstruction() instanceof ApplyActionsCase) {
+                    existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
+                    actionList.addAll(existingActions);
+                }
+            }
+        }
+
+        OutputActionBuilder oab = new OutputActionBuilder();
+        oab.setOutputNodeConnector(ncid);
+        ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
+        Action newAction = ab.build();
+        boolean addNew = true;
+        for (Action action : actionList) {
+            if (action.getAction() instanceof OutputActionCase) {
+                OutputActionCase opAction = (OutputActionCase)action.getAction();
+                if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
+                    addNew = false;
+                    break;
+                }
+            }
+        }
+        if (addNew) actionList.add(newAction);
+
+        // Create an Apply Action
+        ApplyActionsBuilder aab = new ApplyActionsBuilder();
+        aab.setAction(actionList);
+        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+        return ib;
+    }
+
     /**
      * Create Set Vlan ID Instruction
      *