From cc15d70b9699cb572a30fd8a7c1311a6d290ee4f Mon Sep 17 00:00:00 2001 From: sanjivininaikar <sanjivininaikar@tataelxsi.co.in> Date: Mon, 22 Dec 2014 17:03:48 +0530 Subject: [PATCH] Update InstructionUtils.java --- .../util/InstructionUtils.java | 702 ++++++++++++++++++ 1 file changed, 702 insertions(+) diff --git a/src/main/java/net/floodlightcontroller/util/InstructionUtils.java b/src/main/java/net/floodlightcontroller/util/InstructionUtils.java index 626c847e5..b7ae193ec 100644 --- a/src/main/java/net/floodlightcontroller/util/InstructionUtils.java +++ b/src/main/java/net/floodlightcontroller/util/InstructionUtils.java @@ -348,4 +348,706 @@ public class InstructionUtils { } +} +package net.floodlightcontroller.util; + +import java.util.ArrayList; +import java.util.List; + +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionClearActions; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionExperimenter; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionMeter; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteMetadata; +import org.projectfloodlight.openflow.types.TableId; +import org.projectfloodlight.openflow.types.U64; +import org.slf4j.Logger; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +/** + * Convert OFInstructions to and from dpctl/ofctl-style strings. + * Used primarily by the static flow pusher to store and retreive + * flow entries. + * + * @author Ryan Izard <ryan.izard@bigswitch.com, rizard@g.clemson.edu> + * + */ +public class InstructionUtils { + public static final String STR_GOTO_TABLE = "goto_table"; + public static final String STR_WRITE_METADATA = "instruction_write_metadata"; + public static final String STR_WRITE_ACTIONS = "instruction_write_actions"; + public static final String STR_APPLY_ACTIONS = "instruction_apply_actions"; + public static final String STR_CLEAR_ACTIONS = "instruction_clear_actions"; + public static final String STR_GOTO_METER = "instruction_goto_meter"; + public static final String STR_EXPERIMENTER = "instruction_experimenter"; + + private static final String STR_SUB_WRITE_METADATA_METADATA = "metadata"; + private static final String STR_SUB_WRITE_METADATA_MASK = "mask"; + private static final String STR_SUB_GOTO_METER_METER_ID = "meter_id"; + private static final String STR_SUB_EXPERIMENTER_VALUE = "experimenter"; + + + /** + * Adds the instructions to the list of OFInstructions in the OFFlowMod. Any pre-existing + * instruction of the same type is replaced with OFInstruction inst. + * @param fmb, the flow mod to append the instruction to + * @param inst, the instuction to append + */ + public static void appendInstruction(OFFlowMod.Builder fmb, OFInstruction inst) { + List<OFInstruction> newIl = new ArrayList<OFInstruction>(); + List<OFInstruction> oldIl = fmb.getInstructions(); + if (oldIl != null) { // keep any existing instructions that were added earlier + newIl.addAll(fmb.getInstructions()); + } + + for (OFInstruction i : newIl) { // remove any duplicates. Only one of each instruction. + if (i.getType() == inst.getType()) { + newIl.remove(i); + } + } + newIl.add(inst); + fmb.setInstructions(newIl); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionGotoTable to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String gotoTableToString(OFInstructionGotoTable inst, Logger log) { + return Short.toString(inst.getTableId().getValue()); + } + + /** + * Convert the string representation of an OFInstructionGotoTable to + * an OFInstructionGotoTable. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void gotoTableFromString(OFFlowMod.Builder fmb, String instStr, Logger log) { + if (instStr == null || instStr.equals("")) { + return; + } + // Split into pairs of key=value + String[] keyValue = instStr.split("="); + if (keyValue.length != 2) { + throw new IllegalArgumentException("[Key, Value] " + keyValue + " does not have form 'key=value' parsing " + instStr); + } + + OFInstructionGotoTable.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildGotoTable(); + ib.setTableId(TableId.of(Integer.parseInt(keyValue[1]))).build(); + + log.debug("Appending GotoTable instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); } + + /** + * Convert an OFInstructionMetadata to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String writeMetadataToString(OFInstructionWriteMetadata inst, Logger log) { + /* + * U64.toString() looks like it formats with a leading 0x. getLong() will allow us to work with just the value + * For the rest api though, will the user provide a hex value or a long? I'd guess a hex value would be more useful. + */ + return STR_SUB_WRITE_METADATA_METADATA + "=" + Long.toString(inst.getMetadata().getValue()) + "," + STR_SUB_WRITE_METADATA_MASK + "=" + Long.toString(inst.getMetadataMask().getValue()); + } + + /** + * Convert the string representation of an OFInstructionMetadata to + * an OFInstructionMetadata. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void writeMetadataFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + if (inst == null || inst.equals("")) { + return; + } + // Split into pairs of key=value + String[] tokens = inst.split(","); + if (tokens.length != 2) { + throw new IllegalArgumentException("Tokens " + tokens + " does not have form '[t1, t2]' parsing " + inst); + } + + OFInstructionWriteMetadata.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildWriteMetadata(); + + // Process tokens (should be metadata or its mask) + for (int i = 0; i < tokens.length; i++) { + String[] keyValue = tokens[0].split("="); + if (keyValue.length != 2) { + throw new IllegalArgumentException("[Key, Value] " + keyValue + " does not have form 'key=value' parsing " + inst); + } + switch (keyValue[0]) { + case STR_SUB_WRITE_METADATA_METADATA: + ib.setMetadata(U64.of(Long.parseLong(keyValue[1]))); + break; + case STR_SUB_WRITE_METADATA_MASK: + ib.setMetadataMask(U64.of(Long.parseLong(keyValue[1]))); + default: + log.error("Invalid String key for OFInstructionWriteMetadata: {}", keyValue[0]); + } + } + log.debug("Appending WriteMetadata instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionWriteActions to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String writeActionsToString(OFInstructionWriteActions inst, Logger log) throws Exception { + return ActionUtils.actionsToString(inst.getActions(), log); + } + + /** + * Convert the string representation of an OFInstructionWriteActions to + * an OFInstructionWriteActions. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void writeActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + OFFlowMod.Builder tmpFmb = OFFactories.getFactory(fmb.getVersion()).buildFlowModify(); // ActionUtils.fromString() will use setActions(), which should not be used for OF1.3; use temp to avoid overwriting any applyActions data + OFInstructionWriteActions.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildWriteActions(); + ActionUtils.fromString(tmpFmb, inst, log); + ib.setActions(tmpFmb.getActions()); + log.debug("Appending WriteActions instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionApplyActions to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String applyActionsToString(OFInstructionApplyActions inst, Logger log) throws Exception { + return ActionUtils.actionsToString(inst.getActions(), log); + } + + /** + * Convert the string representation of an OFInstructionApplyActions to + * an OFInstructionApplyActions. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void applyActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + OFFlowMod.Builder tmpFmb = OFFactories.getFactory(fmb.getVersion()).buildFlowModify(); + OFInstructionApplyActions.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildApplyActions(); + ActionUtils.fromString(tmpFmb, inst, log); + ib.setActions(tmpFmb.getActions()); + log.debug("Appending ApplyActions instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionClearActions to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String clearActionsToString(OFInstructionClearActions inst, Logger log) { + return ""; // No data for this instruction. The presence of it's key indicates it is to be applied. + } + + /** + * Convert the string representation of an OFInstructionClearActions to + * an OFInstructionClearActions. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void clearActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + if (inst != null && inst.isEmpty()) { + OFInstructionClearActions i = OFFactories.getFactory(fmb.getVersion()).instructions().clearActions(); + log.debug("Appending ClearActions instruction: {}", i); + appendInstruction(fmb, i); + log.debug("All instructions after append: {}", fmb.getInstructions()); + } else { + log.error("Got non-empty or null string, but ClearActions should not have any String sub-fields: {}", inst); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionMeter to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String meterToString(OFInstructionMeter inst, Logger log) { + return STR_SUB_GOTO_METER_METER_ID + "=" + Long.toString(inst.getMeterId()); + } + + /** + * Convert the string representation of an OFInstructionMeter to + * an OFInstructionMeter. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void meterFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + if (inst == null || inst.isEmpty()) { + return; + } + + OFInstructionMeter.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildMeter(); + + String[] keyValue = inst.split("="); + if (keyValue.length != 2) { + throw new IllegalArgumentException("[Key, Value] " + keyValue + " does not have form 'key=value' parsing " + inst); + } + switch (keyValue[0]) { + case STR_SUB_GOTO_METER_METER_ID: + ib.setMeterId(Long.parseLong(keyValue[1])); + break; + default: + log.error("Invalid String key for OFInstructionMeter: {}", keyValue[0]); + } + + log.debug("Appending (Goto)Meter instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionExperimenter to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String experimenterToString(OFInstructionExperimenter inst, Logger log) { + return STR_SUB_EXPERIMENTER_VALUE + "=" + Long.toString(inst.getExperimenter()); + } + + /** + * Convert the string representation of an OFInstructionExperimenter to + * an OFInstructionExperimenter. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void experimenterFromString(OFFlowMod.Builder fmb, String inst, Logger log) throws NotImplementedException { + throw new NotImplementedException(); + /* + if (inst == null || inst.equals("")) { + return; // TODO @Ryan quietly fail? + } + + OFInstructionExperimenter.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildExperimenter(); + + String[] keyValue = inst.split("="); + if (keyValue.length != 2) { + throw new IllegalArgumentException("[Key, Value] " + keyValue + " does not have form 'key=value' parsing " + inst); + } + switch (keyValue[0]) { + case STR_SUB_GOTO_METER_METER_ID: + ib.setExperimenter(Long.parseLong(keyValue[1])); + break; + default: + log.error("Invalid String key for OFInstructionExperimenter: {}", keyValue[0]); + } + + appendInstruction(fmb, ib.build()); + */ + } + + +} +package net.floodlightcontroller.util; + +import java.util.ArrayList; +import java.util.List; + +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionClearActions; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionExperimenter; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionMeter; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteMetadata; +import org.projectfloodlight.openflow.types.TableId; +import org.projectfloodlight.openflow.types.U64; +import org.slf4j.Logger; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +/** + * Convert OFInstructions to and from dpctl/ofctl-style strings. + * Used primarily by the static flow pusher to store and retreive + * flow entries. + * + * @author Ryan Izard <ryan.izard@bigswitch.com, rizard@g.clemson.edu> + * + */ +public class InstructionUtils { + public static final String STR_GOTO_TABLE = "goto_table"; + public static final String STR_WRITE_METADATA = "instruction_write_metadata"; + public static final String STR_WRITE_ACTIONS = "instruction_write_actions"; + public static final String STR_APPLY_ACTIONS = "instruction_apply_actions"; + public static final String STR_CLEAR_ACTIONS = "instruction_clear_actions"; + public static final String STR_GOTO_METER = "instruction_goto_meter"; + public static final String STR_EXPERIMENTER = "instruction_experimenter"; + + private static final String STR_SUB_WRITE_METADATA_METADATA = "metadata"; + private static final String STR_SUB_WRITE_METADATA_MASK = "mask"; + private static final String STR_SUB_GOTO_METER_METER_ID = "meter_id"; + private static final String STR_SUB_EXPERIMENTER_VALUE = "experimenter"; + + + /** + * Adds the instructions to the list of OFInstructions in the OFFlowMod. Any pre-existing + * instruction of the same type is replaced with OFInstruction inst. + * @param fmb, the flow mod to append the instruction to + * @param inst, the instuction to append + */ + public static void appendInstruction(OFFlowMod.Builder fmb, OFInstruction inst) { + List<OFInstruction> newIl = new ArrayList<OFInstruction>(); + List<OFInstruction> oldIl = fmb.getInstructions(); + if (oldIl != null) { // keep any existing instructions that were added earlier + newIl.addAll(fmb.getInstructions()); + } + + for (OFInstruction i : newIl) { // remove any duplicates. Only one of each instruction. + if (i.getType() == inst.getType()) { + newIl.remove(i); + } + } + newIl.add(inst); + fmb.setInstructions(newIl); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionGotoTable to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String gotoTableToString(OFInstructionGotoTable inst, Logger log) { + return Short.toString(inst.getTableId().getValue()); + } + + /** + * Convert the string representation of an OFInstructionGotoTable to + * an OFInstructionGotoTable. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void gotoTableFromString(OFFlowMod.Builder fmb, String instStr, Logger log) { + if (instStr == null || instStr.equals("")) { + return; + } + // Split into pairs of key=value + String[] keyValue = instStr.split("="); + if (keyValue.length != 2) { + throw new IllegalArgumentException("[Key, Value] " + keyValue + " does not have form 'key=value' parsing " + instStr); + } + + OFInstructionGotoTable.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildGotoTable(); + ib.setTableId(TableId.of(Integer.parseInt(keyValue[1]))).build(); + + log.debug("Appending GotoTable instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); } + + /** + * Convert an OFInstructionMetadata to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String writeMetadataToString(OFInstructionWriteMetadata inst, Logger log) { + /* + * U64.toString() looks like it formats with a leading 0x. getLong() will allow us to work with just the value + * For the rest api though, will the user provide a hex value or a long? I'd guess a hex value would be more useful. + */ + return STR_SUB_WRITE_METADATA_METADATA + "=" + Long.toString(inst.getMetadata().getValue()) + "," + STR_SUB_WRITE_METADATA_MASK + "=" + Long.toString(inst.getMetadataMask().getValue()); + } + + /** + * Convert the string representation of an OFInstructionMetadata to + * an OFInstructionMetadata. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void writeMetadataFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + if (inst == null || inst.equals("")) { + return; + } + // Split into pairs of key=value + String[] tokens = inst.split(","); + if (tokens.length != 2) { + throw new IllegalArgumentException("Tokens " + tokens + " does not have form '[t1, t2]' parsing " + inst); + } + + OFInstructionWriteMetadata.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildWriteMetadata(); + + // Process tokens (should be metadata or its mask) + for (int i = 0; i < tokens.length; i++) { + String[] keyValue = tokens[0].split("="); + if (keyValue.length != 2) { + throw new IllegalArgumentException("[Key, Value] " + keyValue + " does not have form 'key=value' parsing " + inst); + } + switch (keyValue[0]) { + case STR_SUB_WRITE_METADATA_METADATA: + ib.setMetadata(U64.of(Long.parseLong(keyValue[1]))); + break; + case STR_SUB_WRITE_METADATA_MASK: + ib.setMetadataMask(U64.of(Long.parseLong(keyValue[1]))); + default: + log.error("Invalid String key for OFInstructionWriteMetadata: {}", keyValue[0]); + } + } + log.debug("Appending WriteMetadata instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionWriteActions to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String writeActionsToString(OFInstructionWriteActions inst, Logger log) throws Exception { + return ActionUtils.actionsToString(inst.getActions(), log); + } + + /** + * Convert the string representation of an OFInstructionWriteActions to + * an OFInstructionWriteActions. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void writeActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + OFFlowMod.Builder tmpFmb = OFFactories.getFactory(fmb.getVersion()).buildFlowModify(); // ActionUtils.fromString() will use setActions(), which should not be used for OF1.3; use temp to avoid overwriting any applyActions data + OFInstructionWriteActions.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildWriteActions(); + ActionUtils.fromString(tmpFmb, inst, log); + ib.setActions(tmpFmb.getActions()); + log.debug("Appending WriteActions instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionApplyActions to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String applyActionsToString(OFInstructionApplyActions inst, Logger log) throws Exception { + return ActionUtils.actionsToString(inst.getActions(), log); + } + + /** + * Convert the string representation of an OFInstructionApplyActions to + * an OFInstructionApplyActions. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void applyActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + OFFlowMod.Builder tmpFmb = OFFactories.getFactory(fmb.getVersion()).buildFlowModify(); + OFInstructionApplyActions.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildApplyActions(); + ActionUtils.fromString(tmpFmb, inst, log); + ib.setActions(tmpFmb.getActions()); + log.debug("Appending ApplyActions instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionClearActions to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String clearActionsToString(OFInstructionClearActions inst, Logger log) { + return ""; // No data for this instruction. The presence of it's key indicates it is to be applied. + } + + /** + * Convert the string representation of an OFInstructionClearActions to + * an OFInstructionClearActions. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void clearActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + if (inst != null && inst.isEmpty()) { + OFInstructionClearActions i = OFFactories.getFactory(fmb.getVersion()).instructions().clearActions(); + log.debug("Appending ClearActions instruction: {}", i); + appendInstruction(fmb, i); + log.debug("All instructions after append: {}", fmb.getInstructions()); + } else { + log.error("Got non-empty or null string, but ClearActions should not have any String sub-fields: {}", inst); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionMeter to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String meterToString(OFInstructionMeter inst, Logger log) { + return STR_SUB_GOTO_METER_METER_ID + "=" + Long.toString(inst.getMeterId()); + } + + /** + * Convert the string representation of an OFInstructionMeter to + * an OFInstructionMeter. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void meterFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + if (inst == null || inst.isEmpty()) { + return; + } + + OFInstructionMeter.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildMeter(); + + String[] keyValue = inst.split("="); + if (keyValue.length != 2) { + throw new IllegalArgumentException("[Key, Value] " + keyValue + " does not have form 'key=value' parsing " + inst); + } + switch (keyValue[0]) { + case STR_SUB_GOTO_METER_METER_ID: + ib.setMeterId(Long.parseLong(keyValue[1])); + break; + default: + log.error("Invalid String key for OFInstructionMeter: {}", keyValue[0]); + } + + log.debug("Appending (Goto)Meter instruction: {}", ib.build()); + appendInstruction(fmb, ib.build()); + log.debug("All instructions after append: {}", fmb.getInstructions()); } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Convert an OFInstructionExperimenter to string form. The string will be formatted + * in a dpctl/ofctl-style syntax. + * @param inst; The instruction to convert to a string + * @param log + * @return + */ + public static String experimenterToString(OFInstructionExperimenter inst, Logger log) { + return STR_SUB_EXPERIMENTER_VALUE + "=" + Long.toString(inst.getExperimenter()); + } + + /** + * Convert the string representation of an OFInstructionExperimenter to + * an OFInstructionExperimenter. The instruction will be set within the + * OFFlowMod.Builder provided. Notice nothing is returned, but the + * side effect is the addition of an instruction in the OFFlowMod.Builder. + * @param fmb; The FMB in which to append the new instruction + * @param instStr; The string to parse the instruction from + * @param log + */ + public static void experimenterFromString(OFFlowMod.Builder fmb, String inst, Logger log) throws NotImplementedException { + throw new NotImplementedException(); + /* + if (inst == null || inst.equals("")) { + return; // TODO @Ryan quietly fail? + } + + OFInstructionExperimenter.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildExperimenter(); + + String[] keyValue = inst.split("="); + if (keyValue.length != 2) { + throw new IllegalArgumentException("[Key, Value] " + keyValue + " does not have form 'key=value' parsing " + inst); + } + switch (keyValue[0]) { + case STR_SUB_GOTO_METER_METER_ID: + ib.setExperimenter(Long.parseLong(keyValue[1])); + break; + default: + log.error("Invalid String key for OFInstructionExperimenter: {}", keyValue[0]); + } + + appendInstruction(fmb, ib.build()); + */ + } + + } -- GitLab