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.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;
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;
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();
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));
/**
* 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();
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));
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();
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);
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();
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
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
*
* @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();
ActionBuilder ab = new ActionBuilder();
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);
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();
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();
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();
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();
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();
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();
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();
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);
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();
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());
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());
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());
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());
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);
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
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;
}
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();
}