diff --git a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java index 107ee8016321cae7974025e30a72e737db7e2fc2..eb15b903d56bbb418c7fd667aaeff742d8b4bc37 100644 --- a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java +++ b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java @@ -83,7 +83,6 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) public Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, IRoutingDecision decision, FloodlightContext cntx) { Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); - // We found a routing decision (i.e. Firewall is enabled... it's the only thing that makes RoutingDecisions) if (decision != null) { if (log.isTraceEnabled()) { diff --git a/src/main/java/net/floodlightcontroller/hub/Hub.java b/src/main/java/net/floodlightcontroller/hub/Hub.java index 5504e589eb99d0e89bf3d81158d8d0e98ab1bdea..28ea1162dd41bb4d4842b1463cfefa937eaffba3 100644 --- a/src/main/java/net/floodlightcontroller/hub/Hub.java +++ b/src/main/java/net/floodlightcontroller/hub/Hub.java @@ -77,7 +77,7 @@ public class Hub implements IFloodlightModule, IOFMessageListener { break; } sw.write(outMessage); - + return Command.CONTINUE; } @@ -99,7 +99,7 @@ public class Hub implements IFloodlightModule, IOFMessageListener { OFPacketIn pi = (OFPacketIn) msg; OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); pob.setBufferId(pi.getBufferId()).setXid(pi.getXid()).setInPort((pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT))); - + // set actions OFActionOutput.Builder actionBuilder = sw.getOFFactory().actions().buildOutput(); actionBuilder.setPort(OFPort.FLOOD); @@ -110,7 +110,7 @@ public class Hub implements IFloodlightModule, IOFMessageListener { byte[] packetData = pi.getData(); pob.setData(packetData); } - return pob.build(); + return pob.build(); } @Override diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java index 4399c95abcf833f5fae04b27f38285f0330e9f86..fec72f40add7fcc13d94894453a025f0074a1cfe 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java @@ -272,8 +272,6 @@ public class StaticFlowEntries { case ARP_TPA: entry.put(StaticFlowEntryPusher.COLUMN_ARP_DPA, match.get(MatchField.ARP_TPA).toString()); break; - -//sanjivini case IPV6_SRC: entry.put(StaticFlowEntryPusher.COLUMN_NW6_SRC, match.get(MatchField.IPV6_SRC).toString()); break; @@ -297,10 +295,7 @@ public class StaticFlowEntries { break; case IPV6_ND_TARGET: entry.put(StaticFlowEntryPusher.COLUMN_ND_TARGET, match.get(MatchField.IPV6_ND_TARGET).toString()); - break; - -//sanjivini - + break; case MPLS_LABEL: entry.put(StaticFlowEntryPusher.COLUMN_MPLS_LABEL, match.get(MatchField.MPLS_LABEL).getValue()); break; @@ -491,9 +486,7 @@ public class StaticFlowEntries { break; case StaticFlowEntryPusher.COLUMN_ARP_DPA: entry.put(StaticFlowEntryPusher.COLUMN_ARP_DPA, jp.getText()); - break; - -//sanjivini + break; case StaticFlowEntryPusher.COLUMN_NW6_SRC: entry.put(StaticFlowEntryPusher.COLUMN_NW6_SRC, jp.getText()); break; @@ -517,9 +510,7 @@ public class StaticFlowEntries { break; case StaticFlowEntryPusher.COLUMN_ND_TARGET: entry.put(StaticFlowEntryPusher.COLUMN_ND_TARGET, jp.getText()); - break; -//sanjivini - + break; case StaticFlowEntryPusher.COLUMN_MPLS_LABEL: entry.put(StaticFlowEntryPusher.COLUMN_MPLS_LABEL, jp.getText()); break; diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java index ded0cb5e34d53d257bc5328eb46b5c12ea76934b..b345bf2119d3131e2237be326a0c71e026bcad10 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java @@ -133,8 +133,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService, public static final String COLUMN_ARP_SPA = MatchUtils.STR_ARP_SPA; public static final String COLUMN_ARP_DPA = MatchUtils.STR_ARP_DPA; -//sanjivini - //IPv6 related columns + /* IPv6 related columns */ public static final String COLUMN_NW6_SRC = MatchUtils.STR_IPV6_SRC; public static final String COLUMN_NW6_DST = MatchUtils.STR_IPV6_DST; public static final String COLUMN_IPV6_FLOW_LABEL = MatchUtils.STR_IPV6_FLOW_LABEL; @@ -143,7 +142,6 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService, public static final String COLUMN_ND_SLL = MatchUtils.STR_IPV6_ND_SSL; public static final String COLUMN_ND_TLL = MatchUtils.STR_IPV6_ND_TTL; public static final String COLUMN_ND_TARGET = MatchUtils.STR_IPV6_ND_TARGET; -//sanjivini public static final String COLUMN_MPLS_LABEL = MatchUtils.STR_MPLS_LABEL; public static final String COLUMN_MPLS_TC = MatchUtils.STR_MPLS_TC; @@ -153,7 +151,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService, public static final String COLUMN_TUNNEL_ID = MatchUtils.STR_TUNNEL_ID; public static final String COLUMN_PBB_ISID = MatchUtils.STR_PBB_ISID; - /* end newly added matches TODO @Ryan should look into full IPv6 support */ + /* end newly added matches */ public static final String COLUMN_ACTIONS = "actions"; @@ -178,12 +176,9 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService, COLUMN_ARP_OPCODE, COLUMN_ARP_SHA, COLUMN_ARP_DHA, COLUMN_ARP_SPA, COLUMN_ARP_DPA, -//sanjivini - //IPv6 related matches + /* IPv6 related matches */ COLUMN_NW6_SRC, COLUMN_NW6_DST, COLUMN_ICMP6_TYPE, COLUMN_ICMP6_CODE, - COLUMN_IPV6_FLOW_LABEL, COLUMN_ND_SLL, COLUMN_ND_TLL, COLUMN_ND_TARGET, -//sanjivini - + COLUMN_IPV6_FLOW_LABEL, COLUMN_ND_SLL, COLUMN_ND_TLL, COLUMN_ND_TARGET, COLUMN_MPLS_LABEL, COLUMN_MPLS_TC, COLUMN_MPLS_BOS, COLUMN_METADATA, COLUMN_TUNNEL_ID, COLUMN_PBB_ISID, /* end newly added matches */ @@ -512,12 +507,14 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService, if (oldFlowMod.getMatch().equals(newFlowMod.getMatch()) && oldFlowMod.getCookie().equals(newFlowMod.getCookie()) && oldFlowMod.getPriority() == newFlowMod.getPriority()) { + log.debug("ModifyStrict SFP Flow"); entriesFromStorage.get(dpid).put(entry, newFlowMod); entry2dpid.put(entry, dpid); newFlowMod = FlowModUtils.toFlowModifyStrict(newFlowMod); outQueue.add(newFlowMod); /* DELETE_STRICT and then ADD b/c the match is now different */ } else { + log.debug("DeleteStrict and Add SFP Flow"); oldFlowMod = FlowModUtils.toFlowDeleteStrict(oldFlowMod); OFFlowAdd addTmp = FlowModUtils.toFlowAdd(newFlowMod); /* If the flow's dpid and the current switch we're looking at are the same, add to the queue. */ @@ -534,6 +531,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService, } /* Add a brand-new flow with ADD */ } else if (newFlowMod != null && oldFlowMod == null) { + log.debug("Add SFP Flow"); OFFlowAdd addTmp = FlowModUtils.toFlowAdd(newFlowMod); entriesFromStorage.get(dpid).put(entry, addTmp); entry2dpid.put(entry, dpid); diff --git a/src/main/java/net/floodlightcontroller/util/ActionUtils.java b/src/main/java/net/floodlightcontroller/util/ActionUtils.java index aa0e5b8adf8d78d829d63679659399e661165247..b09f592565825615f25954cf4ff6152710ae59c9 100644 --- a/src/main/java/net/floodlightcontroller/util/ActionUtils.java +++ b/src/main/java/net/floodlightcontroller/util/ActionUtils.java @@ -408,8 +408,9 @@ public class ActionUtils { case STR_FIELD_SET: /* ONLY OF1.1+ should get in here. These should only be header fields valid within a set-field. */ String[] actionData = pair.split(MatchUtils.SET_FIELD_DELIM); if (actionData.length != 2) { - throw new IllegalArgumentException("[Action, Data] " + keyPair + " does not have form 'action=data' parsing " + actionData); + throw new IllegalArgumentException("[Action, Data] " + keyPair + " does not have form 'action=data'" + actionData); } + switch (actionData[0]) { case MatchUtils.STR_ARP_OPCODE: if (actionData[1].startsWith("0x")) { @@ -442,8 +443,6 @@ public class ActionUtils { .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildArpTpa().setValue(IPv4Address.of(actionData[1])).build()) .build(); break; - - //sanjivini case MatchUtils.STR_IPV6_ND_SSL: a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpv6NdSll().setValue(MacAddress.of(actionData[1])).build()) @@ -459,8 +458,6 @@ public class ActionUtils { .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpv6NdTarget().setValue(IPv6Address.of(actionData[1])).build()) .build(); break; - //sanjivini - case MatchUtils.STR_DL_TYPE: if (actionData[1].startsWith("0x")) { a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() @@ -526,8 +523,6 @@ public class ActionUtils { .build(); } break; - - //sanjivini case MatchUtils.STR_ICMPV6_CODE: if (actionData[1].startsWith("0x")) { a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() @@ -550,8 +545,6 @@ public class ActionUtils { .build(); } break; - //sanjivini - case MatchUtils.STR_NW_PROTO: if (actionData[1].startsWith("0x")) { a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() @@ -573,8 +566,6 @@ public class ActionUtils { .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpv4Dst().setValue(IPv4Address.of(actionData[1])).build()) .build(); break; - - //sanjivini case MatchUtils.STR_IPV6_SRC: a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpv6Src().setValue(IPv6Address.of(actionData[1])).build()) @@ -596,8 +587,6 @@ public class ActionUtils { .build(); } break; - //sanjivini - case MatchUtils.STR_NW_ECN: if (actionData[1].startsWith("0x")) { a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() diff --git a/src/main/java/net/floodlightcontroller/util/InstructionUtils.java b/src/main/java/net/floodlightcontroller/util/InstructionUtils.java index 68516510a8cb2035d9ed5de955a4189c2d9433c0..1de33710366a6d2c8057498d5411780165dc92ce 100644 --- a/src/main/java/net/floodlightcontroller/util/InstructionUtils.java +++ b/src/main/java/net/floodlightcontroller/util/InstructionUtils.java @@ -35,12 +35,6 @@ public class InstructionUtils { 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. @@ -85,28 +79,29 @@ public class InstructionUtils { * @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("")) { + public static void gotoTableFromString(OFFlowMod.Builder fmb, String inst, Logger log) { + if (inst == null || inst.equals("")) { return; } - + if (fmb.getVersion().compareTo(OFVersion.OF_11) < 0) { log.error("Goto Table Instruction not supported in OpenFlow 1.0"); 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(); + + // Get the table ID + if (inst.startsWith("0x")) { + ib.setTableId(TableId.of(Integer.parseInt(inst.replaceFirst("0x", ""), 16))); + } else { + ib.setTableId(TableId.of(Integer.parseInt(inst))).build(); + } log.debug("Appending GotoTable instruction: {}", ib.build()); appendInstruction(fmb, ib.build()); - log.debug("All instructions after append: {}", fmb.getInstructions()); } + log.debug("All instructions after append: {}", fmb.getInstructions()); + } /** * Convert an OFInstructionMetadata to string form. The string will be formatted @@ -117,12 +112,15 @@ public class InstructionUtils { */ 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. + * U64.toString() formats with a leading 0x */ - return STR_SUB_WRITE_METADATA_METADATA + "=" + Long.toString(inst.getMetadata().getValue()) + "," + STR_SUB_WRITE_METADATA_MASK + "=" + Long.toString(inst.getMetadataMask().getValue()); + if (inst.getMetadataMask().equals(U64.NO_MASK)) { // don't give the mask if it's all 1's --> omit "/" + return inst.getMetadata().toString(); + } else { + return inst.getMetadata().toString() + "/" + inst.getMetadataMask().toString(); + } } - + /** * Convert the string representation of an OFInstructionMetadata to * an OFInstructionMetadata. The instruction will be set within the @@ -136,36 +134,42 @@ public class InstructionUtils { if (inst == null || inst.equals("")) { return; } - + if (fmb.getVersion().compareTo(OFVersion.OF_11) < 0) { log.error("Write Metadata Instruction not supported in OpenFlow 1.0"); 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]); + String[] keyValue = inst.split("/"); + if (keyValue.length > 2) { + throw new IllegalArgumentException("[Metadata, Mask] " + keyValue + " does not have form 'metadata/mask' or 'metadata' for parsing " + inst); + } else if (keyValue.length == 1) { + log.debug("No mask detected in OFInstructionWriteMetaData string."); + } else if (keyValue.length == 2) { + log.debug("Detected mask in OFInstructionWriteMetaData string."); + } + + // Get the metadata + if (keyValue[0].startsWith("0x")) { + ib.setMetadata(U64.of(Long.valueOf(keyValue[0].replaceFirst("0x", ""), 16))); + } else { + ib.setMetadata(U64.of(Long.valueOf(keyValue[0]))); + } + + // Get the optional mask + if (keyValue.length == 2) { + if (keyValue[1].startsWith("0x")) { + ib.setMetadataMask(U64.of(Long.valueOf(keyValue[1].replaceFirst("0x", ""), 16))); + } else { + ib.setMetadataMask(U64.of(Long.valueOf(keyValue[1]))); } + } else { + ib.setMetadataMask(U64.NO_MASK); } + log.debug("Appending WriteMetadata instruction: {}", ib.build()); appendInstruction(fmb, ib.build()); log.debug("All instructions after append: {}", fmb.getInstructions()); @@ -194,12 +198,12 @@ public class InstructionUtils { * @param log */ public static void writeActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { - + if (fmb.getVersion().compareTo(OFVersion.OF_11) < 0) { log.error("Write Actions Instruction not supported in OpenFlow 1.0"); return; } - + 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); @@ -231,12 +235,12 @@ public class InstructionUtils { * @param log */ public static void applyActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { - + if (fmb.getVersion().compareTo(OFVersion.OF_11) < 0) { log.error("Apply Actions Instruction not supported in OpenFlow 1.0"); return; } - + OFFlowMod.Builder tmpFmb = OFFactories.getFactory(fmb.getVersion()).buildFlowModify(); OFInstructionApplyActions.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildApplyActions(); ActionUtils.fromString(tmpFmb, inst, log); @@ -268,12 +272,12 @@ public class InstructionUtils { * @param log */ public static void clearActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { - + if (fmb.getVersion().compareTo(OFVersion.OF_11) < 0) { log.error("Clear Actions Instruction not supported in OpenFlow 1.0"); return; } - + if (inst != null && inst.isEmpty()) { OFInstructionClearActions i = OFFactories.getFactory(fmb.getVersion()).instructions().clearActions(); log.debug("Appending ClearActions instruction: {}", i); @@ -294,7 +298,7 @@ public class InstructionUtils { * @return */ public static String meterToString(OFInstructionMeter inst, Logger log) { - return STR_SUB_GOTO_METER_METER_ID + "=" + Long.toString(inst.getMeterId()); + return Long.toString(inst.getMeterId()); } /** @@ -310,7 +314,7 @@ public class InstructionUtils { if (inst == null || inst.isEmpty()) { return; } - + if (fmb.getVersion().compareTo(OFVersion.OF_13) < 0) { log.error("Goto Meter Instruction not supported in OpenFlow 1.0, 1.1, or 1.2"); return; @@ -318,21 +322,16 @@ public class InstructionUtils { 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]); - } + if (inst.startsWith("0x")) { + ib.setMeterId(Long.valueOf(inst.replaceFirst("0x", ""), 16)); + } else { + ib.setMeterId(Long.valueOf(inst)); + } log.debug("Appending (Goto)Meter instruction: {}", ib.build()); appendInstruction(fmb, ib.build()); - log.debug("All instructions after append: {}", fmb.getInstructions()); } + log.debug("All instructions after append: {}", fmb.getInstructions()); + } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -344,7 +343,7 @@ public class InstructionUtils { * @return */ public static String experimenterToString(OFInstructionExperimenter inst, Logger log) { - return STR_SUB_EXPERIMENTER_VALUE + "=" + Long.toString(inst.getExperimenter()); + return Long.toString(inst.getExperimenter()); } /** @@ -358,7 +357,7 @@ public class InstructionUtils { */ public static void experimenterFromString(OFFlowMod.Builder fmb, String inst, Logger log) { /* TODO This is a no-op right now. */ - + /* if (inst == null || inst.equals("")) { return; // TODO @Ryan quietly fail? diff --git a/src/main/java/net/floodlightcontroller/util/MatchUtils.java b/src/main/java/net/floodlightcontroller/util/MatchUtils.java index 7dc1ad464adfca9303e1668ad3ff7829e1e66171..6957010624f3ef5b055bb140189c8298a729d76c 100644 --- a/src/main/java/net/floodlightcontroller/util/MatchUtils.java +++ b/src/main/java/net/floodlightcontroller/util/MatchUtils.java @@ -24,11 +24,14 @@ import org.projectfloodlight.openflow.types.OFBooleanValue; import org.projectfloodlight.openflow.types.OFMetadata; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.OFVlanVidMatch; +import org.projectfloodlight.openflow.types.OFVlanVidMatchWithMask; import org.projectfloodlight.openflow.types.TransportPort; import org.projectfloodlight.openflow.types.U32; import org.projectfloodlight.openflow.types.U64; import org.projectfloodlight.openflow.types.U8; import org.projectfloodlight.openflow.types.VlanPcp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Utilities for working with Matches. Includes workarounds for @@ -46,6 +49,8 @@ import org.projectfloodlight.openflow.types.VlanPcp; * @author Rob Sherwood (rob.sherwood@stanford.edu) */ public class MatchUtils { + private static final Logger log = LoggerFactory.getLogger(MatchUtils.class); + /* List of Strings for marshalling and unmarshalling to human readable forms. * Classes that convert from Match and String should reference these fields for a * common string representation throughout the controller. The StaticFlowEntryPusher @@ -333,9 +338,9 @@ public class MatchUtils { * on unexpected key or value */ public static Match fromString(String match, OFVersion ofVersion) throws IllegalArgumentException { - + boolean ver10 = false; - + if (match.equals("") || match.equalsIgnoreCase("any") || match.equalsIgnoreCase("all") || match.equals("[]")) { match = "Match[]"; } @@ -362,17 +367,28 @@ public class MatchUtils { Match.Builder mb = OFFactories.getFactory(ofVersion).buildMatch(); -//sanjivini + //sanjivini //Determine if the OF version is 1.0 before adding a flow - if (ofVersion.equals(OFVersion.OF_10)) { - ver10 = true; - } -//sanjivini - + if (ofVersion.equals(OFVersion.OF_10)) { + ver10 = true; + } + //sanjivini + while (!llValues.isEmpty()) { IpProtocol ipProto = null; String[] key_value = llValues.pollFirst(); // pop off the first element; this completely removes it from the queue. + + /* Extract the data and its mask */ + String[] dataMask = key_value[1].split("/"); + if (dataMask.length > 2) { + throw new IllegalArgumentException("[Data, Mask] " + dataMask + " does not have form 'data/mask' or 'data'" + key_value[1]); + } else if (dataMask.length == 1) { + log.debug("No mask detected in Match string: {}", key_value[1]); + } else if (dataMask.length == 2) { + log.debug("Detected mask in Match string: {}", key_value[1]); + } + switch (key_value[0]) { case STR_IN_PORT: mb.setExact(MatchField.IN_PORT, OFPort.of(Integer.valueOf(key_value[1]))); @@ -391,10 +407,12 @@ public class MatchUtils { } break; case STR_DL_VLAN: - if (key_value[1].contains("0x")) { - mb.setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlan(Integer.valueOf(key_value[1].replaceFirst("0x", ""), 16))); + if (dataMask.length == 1) { + mb.setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlan(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0]))); } else { - mb.setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlan(Integer.valueOf(key_value[1]))); + mb.setMasked(MatchField.VLAN_VID, OFVlanVidMatchWithMask.of( + OFVlanVidMatch.ofVlan(dataMask[0].contains("0x") ? Integer.valueOf(dataMask[0].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[0])), + OFVlanVidMatch.ofVlan(dataMask[1].contains("0x") ? Integer.valueOf(dataMask[1].replaceFirst("0x", ""), 16) : Integer.valueOf(dataMask[1])))); } break; case STR_DL_VLAN_PCP: @@ -410,8 +428,8 @@ public class MatchUtils { case STR_NW_SRC: mb.setMasked(MatchField.IPV4_SRC, IPv4AddressWithMask.of(key_value[1])); break; - -//sanjivini + + //sanjivini case STR_IPV6_DST: if (ver10 == true) { throw new IllegalArgumentException("OF Version incompatible"); @@ -434,8 +452,8 @@ public class MatchUtils { mb.setExact(MatchField.IPV6_FLABEL, IPv6FlowLabel.of(Integer.parseInt(key_value[1]))); } break; -//sanjivini - + //sanjivini + case STR_NW_PROTO: if (key_value[1].startsWith("0x")) { mb.setExact(MatchField.IP_PROTO, IpProtocol.of(Short.valueOf(key_value[1].replaceFirst("0x", ""), 16))); @@ -544,8 +562,8 @@ public class MatchUtils { mb.setExact(MatchField.ICMPV4_CODE, ICMPv4Code.of(Short.parseShort(key_value[1]))); } break; - -//sanjivini + + //sanjivini case STR_ICMPV6_TYPE: if (ver10 == true) { throw new IllegalArgumentException("OF Version incompatible"); @@ -581,8 +599,8 @@ public class MatchUtils { } mb.setExact(MatchField.IPV6_ND_TARGET, IPv6Address.of(key_value[1])); break; -//sanjivini - + //sanjivini + case STR_ARP_OPCODE: if (key_value[1].startsWith("0x")) { mb.setExact(MatchField.ARP_OP, ArpOpcode.of(Integer.parseInt(key_value[1].replaceFirst("0x", ""), 16))); diff --git a/src/main/resources/logback-test.xml b/src/main/resources/logback-test.xml index c78003320228840936488f4a459e35369629a41e..1986dbd1507739c1ac37deeba32ea1399e340547 100644 --- a/src/main/resources/logback-test.xml +++ b/src/main/resources/logback-test.xml @@ -20,4 +20,5 @@ <logger name="net.floodlightcontroller.routing" level="INFO"></logger> <logger name="net.floodlightcontroller.core" level="INFO"></logger> <logger level="DEBUG" name="net.floodlightcontroller.firewall"></logger> + <logger level="INFO" name="net.floodlightcontroller.staticflowentry"></logger> </configuration>