/*
- * 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 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.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;
*/
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();
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();
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));
+ 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 Output Port Instruction
*
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);
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;
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) {
}
}
- 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;
}
}
}
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 -> vlan vid action
*
* @param ib Map InstructionBuilder without any instructions
* @param vlanId Integer representing a VLAN ID Integer representing a VLAN ID
*/
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 */
*/
public static InstructionBuilder createPopVlanInstructions(InstructionBuilder ib) {
- List<Action> actionList = Lists.newArrayList();
+ List<Action> actionList = new ArrayList<>();
ActionBuilder ab = new ActionBuilder();
PopVlanActionBuilder popVlanActionBuilder = new PopVlanActionBuilder();
*/
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();
*
* @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();
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);
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
*/
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();
*/
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();
*/
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();
*/
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();
*/
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();
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();
*/
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();
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
*/
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();
*/
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();
*/
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();
*/
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();
*/
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
*/
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
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();
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();
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) {
}
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) {
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
*/
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) {