Clean up L2ForwardingService
[netvirt.git] / utils / mdsal-openflow / src / main / java / org / opendaylight / ovsdb / utils / mdsal / openflow / InstructionUtils.java
index 213123be2246704147ccd15ddb71298f04d674b3..4c59d45c555d382d70361647de70c6ff9620d4c6 100644 (file)
@@ -1,10 +1,9 @@
 /*
- * 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;
@@ -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;
@@ -57,6 +59,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 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;
@@ -67,35 +70,36 @@ 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._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
 
-import com.google.common.collect.Lists;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 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));
@@ -114,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 = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         OutputActionBuilder output = new OutputActionBuilder();
-        Uri value = new Uri("NORMAL");
-        output.setOutputNodeConnector(value);
+        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);
+
+        // 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();
+        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));
@@ -152,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);
@@ -187,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;
@@ -231,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) {
@@ -250,38 +288,67 @@ 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;
                 }
             }
         }
@@ -291,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
@@ -308,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 */
@@ -343,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();
@@ -370,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();
@@ -397,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();
@@ -413,6 +482,12 @@ public class InstructionUtils {
         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);
@@ -439,7 +514,7 @@ public class InstructionUtils {
         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
@@ -479,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();
 
@@ -510,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();
 
@@ -541,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();
 
@@ -572,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();
 
@@ -603,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();
 
@@ -635,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();
@@ -665,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();
@@ -702,7 +777,7 @@ public class InstructionUtils {
         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
@@ -723,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();
@@ -753,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();
 
@@ -782,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();
 
@@ -810,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();
 
@@ -838,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
@@ -872,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
@@ -929,7 +1004,7 @@ public class InstructionUtils {
 
     public static InstructionBuilder createDlSrcInstructions(InstructionBuilder ib, MacAddress macAddress) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         SetDlSrcActionBuilder dlSrcActionBuilder= new SetDlSrcActionBuilder();
@@ -954,7 +1029,7 @@ public class InstructionUtils {
 
     public static InstructionBuilder createDlDstInstructions(InstructionBuilder ib, MacAddress macAddress) {
 
-        List<Action> actionList = Lists.newArrayList();
+        List<Action> actionList = new ArrayList<>();
         ActionBuilder ab = new ActionBuilder();
 
         SetDlDstActionBuilder dlDstActionBuilder= new SetDlDstActionBuilder();
@@ -976,10 +1051,10 @@ 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 List<Action>
+                  actionList(org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action... actions) {
 
-        ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> alist
+        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) {
@@ -1004,7 +1079,7 @@ 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) {
@@ -1022,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
@@ -1031,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) {