Clean up L2ForwardingService
[netvirt.git] / utils / mdsal-openflow / src / main / java / org / opendaylight / ovsdb / utils / mdsal / openflow / InstructionUtils.java
index f846ee0ac182eceb55a1b037116735f8112565db..4c59d45c555d382d70361647de70c6ff9620d4c6 100644 (file)
@@ -1,20 +1,15 @@
 /*
- * Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (c) 2013, 2015 Red Hat, 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.ovsdb.utils.mdsal.openflow;
 
 import static org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils.dropAction;
 
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
@@ -25,6 +20,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 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.PopVlanActionCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCaseBuilder;
 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;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCaseBuilder;
@@ -36,6 +33,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 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.action.pop.vlan.action._case.PopVlanActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
@@ -44,6 +43,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
+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.types.rev131026.OutputPortValues;
 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.instruction.instruction.ApplyActionsCase;
@@ -55,7 +57,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
 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.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
@@ -65,31 +69,37 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Lists;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 public class InstructionUtils {
-    private static final Logger logger = LoggerFactory.getLogger(InstructionUtils.class);
+    private static final Logger LOG = LoggerFactory.getLogger(InstructionUtils.class);
     private static final int IPV4 = 0x8100;
     private static final int MAX_LENGTH = 0xffff;
 
     /**
      * Create Send to Controller Reserved Port Instruction (packet_in)
      *
+     * @param nodeName Uri Prefix, containing nodeConnectorType and dpId (aka NodeId)
      * @param ib Map InstructionBuilder without any instructions
      * @return ib Map InstructionBuilder with instructions
      */
-    public static InstructionBuilder createSendToControllerInstructions(InstructionBuilder ib) {
+    public static InstructionBuilder createSendToControllerInstructions(String nodeName, InstructionBuilder ib) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         OutputActionBuilder output = new OutputActionBuilder();
         output.setMaxLength(MAX_LENGTH);
-        Uri value = new Uri("CONTROLLER");
-        output.setOutputNodeConnector(value);
+        NodeId nodeId = new NodeId(nodeName);
+        output.setOutputNodeConnector(new NodeConnectorId(nodeId.getValue() + ":"
+                + OutputPortValues.CONTROLLER.toString()));
         ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
         ab.setOrder(0);
         ab.setKey(new ActionKey(0));
@@ -108,18 +118,49 @@ public class InstructionUtils {
     /**
      * Create NORMAL Reserved Port Instruction (packet_in)
      *
+     * @param nodeName Uri Prefix, containing nodeConnectorType and dpId (aka NodeId)
      * @param ib Map InstructionBuilder without any instructions
      * @return ib Map InstructionBuilder with instructions
      */
 
-    public static InstructionBuilder createNormalInstructions(InstructionBuilder ib) {
+    public static InstructionBuilder createNormalInstructions(String nodeName, InstructionBuilder ib) {
+
+        List<Action> actionList = new ArrayList<>();
+        ActionBuilder ab = new ActionBuilder();
+
+        OutputActionBuilder output = new OutputActionBuilder();
+        NodeId nodeId = new NodeId(nodeName);
+        output.setOutputNodeConnector(new NodeConnectorId(nodeId.getValue() + ":"
+                + OutputPortValues.NORMAL.toString()));
+        ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
+        actionList.add(ab.build());
+
+        // Create an Apply Action
+        ApplyActionsBuilder aab = new ApplyActionsBuilder();
+        aab.setAction(actionList);
 
-        List<Action> actionList = Lists.newArrayList();
+        // Wrap our Apply Action in an Instruction
+        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+        return ib;
+    }
+
+    /**
+     * Create LOCAL Reserved Port Instruction
+     *
+     * @param ib Map InstructionBuilder without any instructions
+     * @param dpidLong Long the datapath ID of a switch/node
+     * @return ib Map InstructionBuilder with instructions
+     */
+    public static InstructionBuilder createLocalInstructions(InstructionBuilder ib, long dpidLong) {
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         OutputActionBuilder output = new OutputActionBuilder();
-        Uri value = new Uri("NORMAL");
-        output.setOutputNodeConnector(value);
+        output.setOutputNodeConnector(new NodeConnectorId("openflow:" + dpidLong + ":"
+                + OutputPortValues.LOCAL.toString()));
         ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
         ab.setOrder(0);
         ab.setKey(new ActionKey(0));
@@ -146,10 +187,10 @@ public class InstructionUtils {
     public static InstructionBuilder createOutputPortInstructions(InstructionBuilder ib, Long dpidLong, Long port) {
 
         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
-        logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} inPort={} ",
+        LOG.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} inPort={} ",
                 dpidLong, port);
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         OutputActionBuilder oab = new OutputActionBuilder();
         oab.setOutputNodeConnector(ncid);
@@ -181,11 +222,11 @@ public class InstructionUtils {
             Long dpidLong, Long port,
             List<Instruction> instructions) {
         NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
-        logger.debug(
+        LOG.debug(
                 "addOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}",
                 dpidLong, port, instructions);
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         List<Action> existingActions;
@@ -225,14 +266,17 @@ public class InstructionUtils {
     public static boolean removeOutputPortFromInstructions(InstructionBuilder ib,
             Long dpidLong, Long port, List<Instruction> instructions) {
 
-        NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
-        logger.debug(
+        final NodeConnectorId ncid = new NodeConnectorId("openflow:" + dpidLong + ":" + port);
+        final Uri ncidUri = new Uri(ncid);
+        LOG.debug(
                 "removeOutputPortFromInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}",
                 dpidLong, port, instructions);
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab;
 
+        // Start of by locating actions that will have port removed, from the existing instructionList
+        //
         List<Action> existingActions;
         if (instructions != null) {
             for (Instruction in : instructions) {
@@ -244,40 +288,69 @@ public class InstructionUtils {
             }
         }
 
-        int index = 0;
+        int removedActionOrder = 0;
         boolean isPortDeleted = false;
         boolean removeFlow = true;
+
+        // Locate specific action that has the port to be removed. Then, take note on its action order
+        // and remove it from list, in addition to flag that it was found.
+        //
         for (Action action : actionList) {
             if (action.getAction() instanceof OutputActionCase) {
                 OutputActionCase opAction = (OutputActionCase) action.getAction();
-                if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
+                if (opAction.getOutputAction().getOutputNodeConnector().equals(ncidUri)) {
                     /* Find the output port in action list and remove */
-                    index = actionList.indexOf(action);
+                    removedActionOrder = action.getOrder();
                     actionList.remove(action);
                     isPortDeleted = true;
                     break;
                 }
-                removeFlow = false;
             }
         }
 
         if (isPortDeleted) {
-            for (int i = index; i < actionList.size(); i++) {
+            // Iterate through all actions in the modified list and adjust the order of
+            // the actions left behind. With that, all actions that have order higher than
+            // the action removed gets their value decremented by 1. Note that this iteration
+            // visits all entries to account for cases where the list order is not the same
+            // as the action's order.
+            //
+            for (int i = 0; i < actionList.size(); i++) {
                 Action action = actionList.get(i);
-                if (action.getOrder() != i) {
-                    /* Shift the action order */
+                if (action.getOrder() > removedActionOrder) {
+                    /* Shift the action by rebuilding action, using adjusted order */
                     ab = new ActionBuilder();
                     ab.setAction(action.getAction());
-                    ab.setOrder(i);
-                    ab.setKey(new ActionKey(i));
+                    ab.setOrder(action.getOrder() - 1);
+                    ab.setKey(new ActionKey(action.getOrder() - 1));
                     Action actionNewOrder = ab.build();
                     actionList.remove(action);
                     actionList.add(i, actionNewOrder);
+                } else if (action.getOrder() == removedActionOrder) {
+                    // Sanity: implementation assumes no two actions have the same order
+                    //
+                    LOG.error("Found action with same order as the action removed for {}, order {} index {}: {}",
+                            ncid, removedActionOrder, i, action);
                 }
+
+                // If action refers to a port output, then flow should be preserved.
+                // We do this, so that if we are only left with non-output port actions,
+                // we still remove the flow
+                //
                 if (action.getAction() instanceof OutputActionCase) {
                     removeFlow = false;
                 }
             }
+        } else {
+            // If port we are asked to delete is not found, this implementation will leave actions
+            // alone and not remove the flow, as long as a remaining OutputActionCase is found.
+            //
+            for (Action action : actionList) {
+                if (action.getAction() instanceof OutputActionCase) {
+                    removeFlow = false;
+                    break;
+                }
+            }
         }
 
         /* Put new action list in Apply Action instruction */
@@ -285,16 +358,16 @@ public class InstructionUtils {
             ApplyActionsBuilder aab = new ApplyActionsBuilder();
             aab.setAction(actionList);
             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
-            logger.debug("removeOutputPortFromInstructions() : applyAction {}", aab.build());
+            LOG.debug("removeOutputPortFromInstructions() : applyAction {}", aab.build());
             return false;
         } else {
-            /* if all output port are removed. Return true to indicate flow remove */
+            /* if all output ports are removed. Return true to indicate flow remove */
             return true;
         }
     }
 
     /**
-     * Create Set Vlan ID Instruction - This includes push vlan action, and set field -> vlan vid action
+     * Create Set Vlan ID Instruction - This includes push vlan action, and set field -&gt; vlan vid action
      *
      * @param ib     Map InstructionBuilder without any instructions
      * @param vlanId Integer representing a VLAN ID Integer representing a VLAN ID
@@ -302,7 +375,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createSetVlanInstructions(InstructionBuilder ib, VlanId vlanId) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         /* First we push vlan header */
@@ -337,7 +410,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createPopVlanInstructions(InstructionBuilder ib) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         PopVlanActionBuilder popVlanActionBuilder = new PopVlanActionBuilder();
@@ -364,7 +437,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createNwSrcInstructions(InstructionBuilder ib, Ipv4Prefix prefixsrc) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         SetNwSrcActionBuilder setNwsrcActionBuilder = new SetNwSrcActionBuilder();
@@ -372,6 +445,8 @@ public class InstructionUtils {
         ipsrc.setIpv4Address(prefixsrc);
         setNwsrcActionBuilder.setAddress(ipsrc.build());
         ab.setAction(new SetNwSrcActionCaseBuilder().setSetNwSrcAction(setNwsrcActionBuilder.build()).build());
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
         // Create an Apply Action
@@ -389,11 +464,13 @@ public class InstructionUtils {
      *
      * @param ib        Map InstructionBuilder without any instructions
      * @param prefixdst String containing an IPv4 prefix
+     * @param extraAction (optional) Additional action to be performed in actionList
      * @return ib Map InstructionBuilder with instructions
      */
-    public static InstructionBuilder createNwDstInstructions(InstructionBuilder ib, Ipv4Prefix prefixdst) {
+    public static InstructionBuilder createNwDstInstructions(InstructionBuilder ib, Ipv4Prefix prefixdst,
+                                                             ActionBuilder extraAction) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         SetNwDstActionBuilder setNwDstActionBuilder = new SetNwDstActionBuilder();
@@ -401,8 +478,16 @@ public class InstructionUtils {
         ipdst.setIpv4Address(prefixdst);
         setNwDstActionBuilder.setAddress(ipdst.build());
         ab.setAction(new SetNwDstActionCaseBuilder().setSetNwDstAction(setNwDstActionBuilder.build()).build());
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
+        if (extraAction != null) {
+            extraAction.setOrder(1);
+            extraAction.setKey(new ActionKey(1));
+            actionList.add(extraAction.build());
+        }
+
         // Create an Apply Action
         ApplyActionsBuilder aab = new ApplyActionsBuilder();
         aab.setAction(actionList);
@@ -426,9 +511,10 @@ public class InstructionUtils {
         ActionBuilder ab = new ActionBuilder();
         ab.setAction(new DropActionCaseBuilder().setDropAction(dropAction).build());
         ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
 
         // Add our drop action to a list
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         actionList.add(ab.build());
 
         // Create an Apply Action
@@ -468,7 +554,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createSetTunnelIdInstructions(InstructionBuilder ib, BigInteger tunnelId) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
 
@@ -478,6 +564,7 @@ public class InstructionUtils {
         setFieldBuilder.setTunnel(tunnel.build());
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
         ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
         ApplyActionsBuilder aab = new ApplyActionsBuilder();
@@ -498,7 +585,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createSetSrcTCPPort(InstructionBuilder ib, PortNumber tcpport) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
 
@@ -509,7 +596,8 @@ public class InstructionUtils {
 
         setFieldBuilder.setLayer4Match(tcpmatch.build());
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
-        ab.setKey(new ActionKey(1));
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
         ApplyActionsBuilder aab = new ApplyActionsBuilder();
@@ -528,7 +616,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createSetDstTCPPort(InstructionBuilder ib, PortNumber tcpport) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
 
@@ -539,7 +627,8 @@ public class InstructionUtils {
 
         setFieldBuilder.setLayer4Match(tcpmatch.build());
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
-        ab.setKey(new ActionKey(1));
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
         ApplyActionsBuilder aab = new ApplyActionsBuilder();
@@ -558,7 +647,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createSetSrcUDPPort(InstructionBuilder ib, PortNumber udpport) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
 
@@ -569,7 +658,8 @@ public class InstructionUtils {
 
         setFieldBuilder.setLayer4Match(udpmatch.build());
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
-        ab.setKey(new ActionKey(1));
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
         ApplyActionsBuilder aab = new ApplyActionsBuilder();
@@ -588,7 +678,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createSetDstUDPPort(InstructionBuilder ib, PortNumber udpport) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
 
@@ -599,7 +689,8 @@ public class InstructionUtils {
 
         setFieldBuilder.setLayer4Match(udpmatch.build());
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
-        ab.setKey(new ActionKey(1));
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
         ApplyActionsBuilder aab = new ApplyActionsBuilder();
@@ -619,7 +710,7 @@ public class InstructionUtils {
 
     public static InstructionBuilder createSetIcmpCodeInstruction(InstructionBuilder ib, short code) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
@@ -629,6 +720,7 @@ public class InstructionUtils {
         setFieldBuilder.setIcmpv4Match(icmpv4match.build());
 
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+        ab.setOrder(0);
         ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
         ApplyActionsBuilder aab = new ApplyActionsBuilder();
@@ -648,7 +740,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createSetIcmpTypeInstruction(InstructionBuilder ib, short type) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
         Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
@@ -658,7 +750,8 @@ public class InstructionUtils {
         setFieldBuilder.setIcmpv4Match(icmpv4match.build());
 
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
-        ab.setKey(new ActionKey(1));
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
         ApplyActionsBuilder aab = new ApplyActionsBuilder();
         aab.setAction(actionList);
@@ -680,9 +773,11 @@ public class InstructionUtils {
         DecNwTtl decNwTtl = decNwTtlBuilder.build();
         ActionBuilder ab = new ActionBuilder();
         ab.setAction(new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build());
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
 
         // Add our drop action to a list
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         actionList.add(ab.build());
 
         // Create an Apply Action
@@ -703,7 +798,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createSrcArpMacInstructions(InstructionBuilder ib, MacAddress macsrc) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
@@ -713,6 +808,7 @@ public class InstructionUtils {
         arpmatch.setArpSourceHardwareAddress(arpsrc.build());
         setFieldBuilder.setLayer3Match(arpmatch.build());
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+        ab.setOrder(0);
         ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
@@ -732,7 +828,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createDstArpMacInstructions(InstructionBuilder ib, MacAddress macdst) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
 
@@ -741,6 +837,7 @@ public class InstructionUtils {
         arpdst.setAddress(macdst);
         setFieldBuilder.setLayer3Match(arpmatch.build());
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+        ab.setOrder(0);
         ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
@@ -760,7 +857,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createDstArpIpInstructions(InstructionBuilder ib, Ipv4Prefix dstiparp) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
 
@@ -768,6 +865,7 @@ public class InstructionUtils {
         arpmatch.setArpTargetTransportAddress(dstiparp);
         setFieldBuilder.setLayer3Match(arpmatch.build());
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+        ab.setOrder(0);
         ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
@@ -787,7 +885,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createSrcArpIpInstructions(InstructionBuilder ib, Ipv4Prefix srciparp) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
         SetFieldBuilder setFieldBuilder = new SetFieldBuilder();
 
@@ -795,6 +893,7 @@ public class InstructionUtils {
         arpmatch.setArpSourceTransportAddress(srciparp);
         setFieldBuilder.setLayer3Match(arpmatch.build());
         ab.setAction(new SetFieldCaseBuilder().setSetField(setFieldBuilder.build()).build());
+        ab.setOrder(0);
         ab.setKey(new ActionKey(0));
         actionList.add(ab.build());
 
@@ -814,7 +913,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createTunnelIpv4SrcInstructions(InstructionBuilder ib, Ipv4Prefix srcIp) {
 
-        List<Action> actionList = new ArrayList<Action>();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         // Build the tunnel endpoint source IPv4 address
@@ -848,7 +947,7 @@ public class InstructionUtils {
      */
     public static InstructionBuilder createTunnelIpv4DstInstructions(InstructionBuilder ib, Ipv4Prefix dstIp) {
 
-        List<Action> actionList = new ArrayList<Action>();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         // Build the tunnel endpoint dst IPv4 address
@@ -903,17 +1002,68 @@ public class InstructionUtils {
         return ib;
     }
 
-    public static ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action>
-                  actionList (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action... actions) {
+    public static InstructionBuilder createDlSrcInstructions(InstructionBuilder ib, MacAddress macAddress) {
+
+        List<Action> actionList = new ArrayList<>();
+        ActionBuilder ab = new ActionBuilder();
+
+        SetDlSrcActionBuilder dlSrcActionBuilder= new SetDlSrcActionBuilder();
+
+        dlSrcActionBuilder.setAddress(macAddress);
+
+        ab.setAction(new SetDlSrcActionCaseBuilder().setSetDlSrcAction(dlSrcActionBuilder.build()).build());
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
+        actionList.add(ab.build());
+
+
+        // Create an Apply Action
+        ApplyActionsBuilder aab = new ApplyActionsBuilder();
+        aab.setAction(actionList);
+
+        // Wrap our Apply Action in an Instruction
+        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+        return ib;
+    }
+
+    public static InstructionBuilder createDlDstInstructions(InstructionBuilder ib, MacAddress macAddress) {
+
+        List<Action> actionList = new ArrayList<>();
+        ActionBuilder ab = new ActionBuilder();
+
+        SetDlDstActionBuilder dlDstActionBuilder= new SetDlDstActionBuilder();
 
-        ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> alist
+        dlDstActionBuilder.setAddress(macAddress);
+
+        ab.setAction(new SetDlDstActionCaseBuilder().setSetDlDstAction(dlDstActionBuilder.build()).build());
+        ab.setOrder(0);
+        ab.setKey(new ActionKey(0));
+        actionList.add(ab.build());
+
+        // Create an Apply Action
+        ApplyActionsBuilder aab = new ApplyActionsBuilder();
+        aab.setAction(actionList);
+
+        // Wrap our Apply Action in an Instruction
+        ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+
+        return ib;
+    }
+
+    public static List<Action>
+                  actionList(org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action... actions) {
+
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> alist
             = new ArrayList<>();
         int count = 0;
         for (org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action : actions) {
             alist.add(new ActionBuilder()
-            .setOrder(Integer.valueOf(count++))
-            .setAction(action)
-            .build());
+                .setOrder(count)
+                .setKey(new ActionKey(count))
+                .setAction(action)
+                .build());
+            count++;
         }
         return alist;
     }
@@ -929,14 +1079,16 @@ public class InstructionUtils {
     }
 
     public static Instructions getInstructions(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction... instructions) {
-        ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> ins
+        List<Instruction> ins
             = new ArrayList<>();
         int order = 0;
         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction i : instructions) {
             ins.add(new InstructionBuilder()
-                .setOrder(order++)
+                .setOrder(order)
+                .setKey(new InstructionKey(order))
                 .setInstruction(i)
                 .build());
+            order++;
         }
         return new InstructionsBuilder().setInstruction(ins).build();
     }
@@ -945,6 +1097,37 @@ public class InstructionUtils {
         return getInstructions(applyActionIns(dropAction()));
     }
 
+    /**
+     * Extracts the existing instructions (if any) from the flow.
+     *
+     * @param flow The flow.
+     * @return The instructions in the flow (empty if none).
+     */
+    public static List<Instruction> extractExistingInstructions(Flow flow) {
+        if (flow != null) {
+            Instructions ins = flow.getInstructions();
+            if (ins != null) {
+                return ins.getInstruction();
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Configures the flow builder to have the single given instruction.
+     *
+     * @param flowBuilder The flow builder.
+     * @param instruction The instruction.
+     * @return The flow builder.
+     */
+    public static FlowBuilder setFlowBuilderInstruction(FlowBuilder flowBuilder, Instruction instruction) {
+        flowBuilder.setInstructions(
+                new InstructionsBuilder()
+                        .setInstruction(Collections.singletonList(instruction))
+                        .build());
+        return flowBuilder;
+    }
+
     /**
      * Get a list of Instructions containing Nicira extensions that can have
      * additional OF/OXM instructions added to the returned Instruction list
@@ -954,7 +1137,7 @@ public class InstructionUtils {
      */
     public static List<Instruction> getInstructionList(
             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction... instructions) {
-        ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction> ins
+        List<Instruction> ins
                 = new ArrayList<>();
         int order = 0;
         for (org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction i : instructions) {
@@ -965,4 +1148,4 @@ public class InstructionUtils {
         }
         return ins;
     }
-}
\ No newline at end of file
+}