Use config instead of Activator for netvirt and netvirt-providers
[ovsdb.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / L2ForwardingService.java
index 199055779da1baa34b10e3aefe3db07b6c79de3b..4ab2a3da4360357cf1963ec292ca37ae8bb31eb6 100644 (file)
@@ -12,16 +12,18 @@ package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
 import java.math.BigInteger;
 import java.util.List;
 
+import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.L2ForwardingProvider;
+import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
+import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
 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.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.PopVlanActionCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
@@ -42,12 +44,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.Lists;
 
-public class L2ForwardingService extends AbstractServiceInstance implements L2ForwardingProvider {
+public class L2ForwardingService extends AbstractServiceInstance implements ConfigInterface, L2ForwardingProvider {
     private static final Logger logger = LoggerFactory.getLogger(L2ForwardingService.class);
     public L2ForwardingService() {
         super(Service.L2_FORWARDING);
@@ -57,13 +62,8 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         super(service);
     }
 
-    @Override
-    public boolean isBridgeInPipeline (String nodeId) {
-        return true;
-    }
-
     /*
-     * (Table:L2Forwarding) Local Broadcast Flood
+     * (Table:L2Forwarding) Local Unicast
      * Match: Tunnel ID and dMAC
      * Action: Output Port
      * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2 goto:<next-table>
@@ -102,12 +102,6 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
             // Instructions List Stores Individual Instructions
             List<Instruction> instructions = Lists.newArrayList();
 
-            // GOTO Instructions Need to be added first to the List
-            ib = this.getMutablePipelineInstructionBuilder();
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
-
             // Set the Output Port/Iface
             InstructionUtils.createOutputPortInstructions(ib, dpidLong, localPort);
             ib.setOrder(0);
@@ -129,6 +123,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
      * Match: VLAN ID and dMAC
      * Action: Output Port
      * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
+     * table=110,dl_vlan=2001,dl_dst=fa:16:3e:a3:3b:cc actions=pop_vlan,output:1
      */
 
     @Override
@@ -142,7 +137,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
 
         // Create the OF Match using MatchBuilder
         flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
 
         String flowId = "VlanUcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
@@ -166,12 +161,6 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
             List<Instruction> instructions = Lists.newArrayList();
             List<Instruction> instructions_tmp = Lists.newArrayList();
 
-            // GOTO Instructions Need to be added first to the List
-            ib = this.getMutablePipelineInstructionBuilder();
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
-
             /* Strip vlan and store to tmp instruction space*/
             InstructionUtils.createPopVlanInstructions(ib);
             ib.setOrder(0);
@@ -181,7 +170,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
             // Set the Output Port/Iface
             ib = new InstructionBuilder();
             InstructionUtils.addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
-            ib.setOrder(0);
+            ib.setOrder(1);
             ib.setKey(new InstructionKey(0));
             instructions.add(ib.build());
 
@@ -196,6 +185,34 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         }
     }
 
+
+    /**
+     * Utility function used by the flooding logic to allow a flow to be resubmitted
+     * to the local port flooding rule, after being outputed to all available tunnel
+     * or VLAN egress ports.
+     */
+    private void appendResubmitLocalFlood(InstructionBuilder ib) {
+
+        //Update the ApplyActions instructions
+        ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
+        List<Action> actionList = aac.getApplyActions().getAction();
+
+        int index = actionList.size();
+        ActionBuilder ab = new ActionBuilder();
+        ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(ClassifierService.REG_FIELD).build(),
+                BigInteger.valueOf(ClassifierService.REG_VALUE_FROM_REMOTE)));
+        ab.setOrder(index);
+        ab.setKey(new ActionKey(index));
+        actionList.add(ab.build());
+
+        index++;
+        ab = new ActionBuilder();
+        ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
+        ab.setOrder(index);
+        ab.setKey(new ActionKey(index));
+        actionList.add(ab.build());
+    }
+
     /*
      * (Table:2) Local Broadcast Flood
      * Match: Tunnel ID and dMAC (::::FF:FF)
@@ -213,6 +230,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         FlowBuilder flowBuilder = new FlowBuilder();
 
         // Create the OF Match using MatchBuilder
+        MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_REMOTE));
         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
                 new MacAddress("01:00:00:00:00:00")).build());
@@ -247,6 +265,11 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
             createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
             ib.setOrder(0);
             ib.setKey(new InstructionKey(0));
+
+            /* Alternative method to address Bug 2004 is to make a call
+             * here to appendResubmitLocalFlood(ib) so that we send the
+             * flow back to the local flood rule.
+             */
             instructions.add(ib.build());
 
             // Add InstructionBuilder to the Instruction(s)Builder List
@@ -273,7 +296,6 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
 
                 // Add InstructionsBuilder to FlowBuilder
                 flowBuilder.setInstructions(isb.build());
-
                 writeFlow(flowBuilder, nodeBuilder);
             }
         }
@@ -284,12 +306,12 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
      * Match: vlan ID and dMAC (::::FF:FF)
      * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
      * actions=strip_vlan, output:2,3,4,5
+     * table=110,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
      */
 
     @Override
-    public void programLocalVlanBcastOut(Long dpidLong,
-            String segmentationId, Long localPort,
-            boolean write) {
+    public void programLocalVlanBcastOut(Long dpidLong, String segmentationId,
+                                         Long localPort, Long ethPort, boolean write) {
 
         String nodeName = OPENFLOW + dpidLong;
 
@@ -299,11 +321,11 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
 
         // Create the OF Match using MatchBuilder
         flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
                 new MacAddress("01:00:00:00:00:00")).build());
 
-        String flowId = "VlanBcastOut_"+segmentationId;
+        String flowId = "VlanBcastOut_"+segmentationId+"_"+ethPort;
         // Add Flow Attributes
         flowBuilder.setId(new FlowId(flowId));
         FlowKey key = new FlowKey(new FlowId(flowId));
@@ -317,11 +339,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         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();
-        List<Instruction> instructions = Lists.newArrayList();
         List<Instruction> existingInstructions = null;
-        boolean add_pop_vlan = true;
         if (flow != null) {
             Instructions ins = flow.getInstructions();
             if (ins != null) {
@@ -329,52 +347,82 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
             }
         }
 
+        List<Instruction> instructions = Lists.newArrayList();
+        InstructionBuilder ib = new InstructionBuilder();
+        List<Action> actionList = null;
         if (write) {
-            if (existingInstructions != null) {
-                /* Check if pop vlan is already the first action in action list */
-                List<Action> existingActions;
-                for (Instruction in : existingInstructions) {
-                    if (in.getInstruction() instanceof ApplyActionsCase) {
-                        existingActions = (((ApplyActionsCase)
-                                in.getInstruction()).getApplyActions().getAction());
-                        if (existingActions.get(0).getAction() instanceof PopVlanActionCase) {
-                            add_pop_vlan = false;
+            if (existingInstructions == null) {
+                /* First time called there should be no instructions.
+                 * We can simply add the output:ethPort first, followed by
+                 * popVlan and then the local port. The next calls will append
+                 * the rest of the local ports.
+                 */
+                ActionBuilder ab = new ActionBuilder();
+                actionList = Lists.newArrayList();
+
+                ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + ethPort)));
+                ab.setOrder(0);
+                ab.setKey(new ActionKey(0));
+                actionList.add(ab.build());
+
+                ab.setAction(ActionUtils.popVlanAction());
+                ab.setOrder(1);
+                ab.setKey(new ActionKey(1));
+                actionList.add(ab.build());
+
+                ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
+                ab.setOrder(2);
+                ab.setKey(new ActionKey(2));
+                actionList.add(ab.build());
+            } else {
+                /* Subsequent calls require appending any new local ports for this tenant. */
+                ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
+                Instruction in = existingInstructions.get(0);
+                actionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
+
+                NodeConnectorId ncid = new NodeConnectorId(nodeName + ":" + localPort);
+                boolean addNew = true;
+
+                /* Check if the port is already in the output list */
+                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;
                         }
                     }
                 }
-            } else {
-                existingInstructions = Lists.newArrayList();
-            }
 
-            if (add_pop_vlan) {
-                /* pop vlan */
-                InstructionUtils.createPopVlanInstructions(ib);
-                ib.setOrder(0);
-                ib.setKey(new InstructionKey(0));
-                existingInstructions.add(ib.build());
-                ib = new InstructionBuilder();
+                if (addNew) {
+                    ActionBuilder ab = new ActionBuilder();
+
+                    ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
+                    ab.setOrder(actionList.size());
+                    ab.setKey(new ActionKey(actionList.size()));
+                    actionList.add(ab.build());
+                }
             }
 
-            // Create port list
-            //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, localPort, existingInstructions);
-            createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
+            ApplyActionsBuilder aab = new ApplyActionsBuilder();
+            aab.setAction(actionList);
+            ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
             ib.setOrder(0);
             ib.setKey(new InstructionKey(0));
             instructions.add(ib.build());
 
             // Add InstructionBuilder to the Instruction(s)Builder List
+            InstructionsBuilder isb = new InstructionsBuilder();
             isb.setInstruction(instructions);
 
             // Add InstructionsBuilder to FlowBuilder
             flowBuilder.setInstructions(isb.build());
-
             writeFlow(flowBuilder, nodeBuilder);
         } else {
             //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
             //                     localPort, existingInstructions);
-            boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
-                    localPort, existingInstructions);
+            boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong, localPort, ethPort,
+                    existingInstructions);
             if (flowRemove) {
                 /* if all ports are removed, remove flow */
                 removeFlow(flowBuilder, nodeBuilder);
@@ -385,6 +433,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
                 instructions.add(ib.build());
 
                 // Add InstructionBuilder to the Instruction(s)Builder List
+                InstructionsBuilder isb = new InstructionsBuilder();
                 isb.setInstruction(instructions);
 
                 // Add InstructionsBuilder to FlowBuilder
@@ -394,6 +443,54 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         }
     }
 
+    private boolean removeOutputPortFromInstructions(InstructionBuilder ib, Long dpidLong, Long localPort,
+                                                     Long ethPort, List<Instruction> instructions) {
+        List<Action> actionList = Lists.newArrayList();
+        boolean removeFlow = true;
+
+        if (instructions != null) {
+            ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
+            Instruction in = instructions.get(0);
+            List<Action> oldActionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
+            NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + localPort);
+            NodeConnectorId ncidEth = new NodeConnectorId(OPENFLOW + dpidLong + ":" + ethPort);
+
+            // Remove the port from the output list
+            ActionBuilder ab = new ActionBuilder();
+            int index = 2;
+            //for (ListIterator<Action> it = oldActionList.listIterator(oldActionList.size()); it.hasPrevious();) {
+            //    Action action = it.previous();
+            for (Action action : oldActionList) {
+                if (action.getAction() instanceof OutputActionCase) {
+                    OutputActionCase opAction = (OutputActionCase) action.getAction();
+                    if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncidEth))) {
+                        actionList.add(action);
+                    } else if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid)) == false) {
+                        ab.setAction(action.getAction());
+                        ab.setOrder(index);
+                        ab.setKey(new ActionKey(index));
+                        actionList.add(ab.build());
+                        index++;
+                    }
+                } else {
+                    actionList.add(action);
+                }
+            }
+            ApplyActionsBuilder aab = new ApplyActionsBuilder();
+            aab.setAction(actionList);
+            ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+        }
+
+        if (actionList != null && actionList.size() > 2) {
+            // Add InstructionBuilder to the Instruction(s)Builder List
+            InstructionsBuilder isb = new InstructionsBuilder();
+            isb.setInstruction(instructions);
+            removeFlow = false;
+        }
+
+        return removeFlow;
+    }
+
     /*
      * (Table:1) Local Table Miss
      * Match: Any Remaining Flows w/a TunID
@@ -471,7 +568,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
 
         // Create Match(es) and Set them in the FlowBuilder Object
         flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
 
         if (write) {
             // Create the OF Actions and Instructions
@@ -555,14 +652,9 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
             // Instructions List Stores Individual Instructions
             List<Instruction> instructions = Lists.newArrayList();
 
-            // GOTO Instructions
-            ib = this.getMutablePipelineInstructionBuilder();
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
             // Set the Output Port/Iface
             InstructionUtils.createOutputPortInstructions(ib, dpidLong, OFPortOut);
-            ib.setOrder(1);
+            ib.setOrder(0);
             ib.setKey(new InstructionKey(1));
             instructions.add(ib.build());
 
@@ -597,7 +689,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
 
         // Create the OF Match using MatchBuilder
         flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
 
         String flowId = "VlanOut_"+segmentationId+"_"+ethPort+"_"+attachedMac;
@@ -619,11 +711,9 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
 
             // Instructions List Stores Individual Instructions
             List<Instruction> instructions = Lists.newArrayList();
-
-            // GOTO Instructions
-            ib = this.getMutablePipelineInstructionBuilder();
+            InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
             ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
+            ib.setKey(new InstructionKey(1));
             instructions.add(ib.build());
 
             // Add InstructionBuilder to the Instruction(s)Builder List
@@ -656,9 +746,9 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
 
         // Create the OF Match using MatchBuilder
         // Match TunnelID
+        MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_LOCAL));
         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
         // Match DMAC
-
         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
                 new MacAddress("01:00:00:00:00:00")).build());
 
@@ -669,7 +759,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         flowBuilder.setBarrier(true);
         flowBuilder.setTableId(getTable());
         flowBuilder.setKey(key);
-        flowBuilder.setPriority(16384);
+        flowBuilder.setPriority(16383);  // FIXME: change it back to 16384 once bug 3005 is fixed.
         flowBuilder.setFlowName(flowId);
         flowBuilder.setHardTimeout(0);
         flowBuilder.setIdleTimeout(0);
@@ -688,16 +778,11 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         }
 
         if (write) {
-            // GOTO Instruction
-            ib = this.getMutablePipelineInstructionBuilder();
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
             // Set the Output Port/Iface
             //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
             createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
-            ib.setOrder(1);
-            ib.setKey(new InstructionKey(1));
+            ib.setOrder(0);
+            ib.setKey(new InstructionKey(0));
             instructions.add(ib.build());
 
             // Add InstructionBuilder to the Instruction(s)Builder List
@@ -725,6 +810,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
 
                 // Add InstructionsBuilder to FlowBuilder
                 flowBuilder.setInstructions(isb.build());
+                writeFlow(flowBuilder, nodeBuilder);
             }
         }
     }
@@ -749,12 +835,12 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         // Create the OF Match using MatchBuilder
         // Match Vlan ID
         flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
         // Match DMAC
         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
                 new MacAddress("01:00:00:00:00:00")).build());
 
-        String flowId = "VlanFloodOut_"+segmentationId;
+        String flowId = "VlanFloodOut_"+segmentationId+"_"+ethPort;
         // Add Flow Attributes
         flowBuilder.setId(new FlowId(flowId));
         FlowKey key = new FlowKey(new FlowId(flowId));
@@ -775,15 +861,10 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         List<Instruction> instructions = Lists.newArrayList();
 
         if (write) {
-            // GOTO Instruction
-            ib = this.getMutablePipelineInstructionBuilder();
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
             // Set the Output Port/Iface
             InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
-            ib.setOrder(1);
-            ib.setKey(new InstructionKey(1));
+            ib.setOrder(0);
+            ib.setKey(new InstructionKey(0));
             instructions.add(ib.build());
 
             // Add InstructionBuilder to the Instruction(s)Builder List
@@ -861,6 +942,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
      * Match: Vlan ID
      * Action: Output port eth interface
      * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
+     * table=110,priority=8192,dl_vlan=2001 actions=output:2
      */
 
     @Override
@@ -874,7 +956,7 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
 
         // Create Match(es) and Set them in the FlowBuilder Object
         flowBuilder.setMatch(
-                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId))).build());
+                MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
 
         if (write) {
             // Create the OF Actions and Instructions
@@ -884,12 +966,6 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
             // Instructions List Stores Individual Instructions
             List<Instruction> instructions = Lists.newArrayList();
 
-            // Call the InstructionBuilder Methods Containing Actions
-            ib = this.getMutablePipelineInstructionBuilder();
-            ib.setOrder(0);
-            ib.setKey(new InstructionKey(0));
-            instructions.add(ib.build());
-
             // Set the Output Port/Iface
             InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
             ib.setOrder(0);
@@ -940,41 +1016,55 @@ public class L2ForwardingService extends AbstractServiceInstance implements L2Fo
         ActionBuilder ab = new ActionBuilder();
 
         List<Action> existingActions;
-        if (instructions != null) {
-            for (Instruction in : instructions) {
-                if (in.getInstruction() instanceof ApplyActionsCase) {
-                    existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
-                    actionList.addAll(existingActions);
-                }
+        if (instructions != null && instructions.size() > 0) {
+            /**
+             * First instruction is the one containing the output ports.
+             * So, only extract the actions from that.
+             */
+            Instruction in = instructions.get(0);
+            if (in.getInstruction() instanceof ApplyActionsCase) {
+                existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
+                // Only include output actions
+                for (Action action : existingActions)
+                    if (action.getAction() instanceof OutputActionCase)
+                        actionList.add(action);
             }
         }
         /* Create output action for this port*/
         OutputActionBuilder oab = new OutputActionBuilder();
-                oab.setOutputNodeConnector(ncid);
-                ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
-                boolean addNew = true;
+        oab.setOutputNodeConnector(ncid);
+        ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
+        boolean addNew = true;
+
+        /* Find the group action and get the group */
+        for (Action action : actionList) {
+            OutputActionCase opAction = (OutputActionCase)action.getAction();
+            /* If output port action already in the action list of one of the buckets, skip */
+            if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
+                addNew = false;
+                break;
+            }
+        }
+        if (addNew) {
+            ab.setOrder(actionList.size());
+            ab.setKey(new ActionKey(actionList.size()));
+            actionList.add(ab.build());
+        }
+        // Create an Apply Action
+        ApplyActionsBuilder aab = new ApplyActionsBuilder();
+        aab.setAction(actionList);
+        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+        logger.debug("createOutputPortInstructions() : applyAction {}", aab.build());
+        return ib;
+    }
+
+    @Override
+    public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
+        super.setOrchestrator(bundleContext.getServiceReference(L2ForwardingProvider.class.getName()), this);
+    }
+
+    @Override
+    public void setDependencies(Object impl) {
 
-                /* Find the group action and get the group */
-                for (Action action : actionList) {
-                    if (action.getAction() instanceof OutputActionCase) {
-                        OutputActionCase opAction = (OutputActionCase)action.getAction();
-                        /* If output port action already in the action list of one of the buckets, skip */
-                        if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
-                            addNew = false;
-                            break;
-                        }
-                    }
-                }
-                if (addNew) {
-                    ab.setOrder(actionList.size());
-                    ab.setKey(new ActionKey(actionList.size()));
-                    actionList.add(ab.build());
-                }
-                // Create an Apply Action
-                ApplyActionsBuilder aab = new ApplyActionsBuilder();
-                aab.setAction(actionList);
-                ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
-                logger.debug("createOutputPortInstructions() : applyAction {}", aab.build());
-                return ib;
     }
-}
\ No newline at end of file
+}