diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/OFActionListSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/OFActionListSerializer.java index bb17f34f94..5756d5487a 100644 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/OFActionListSerializer.java +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/OFActionListSerializer.java @@ -41,11 +41,21 @@ import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv4Code; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv4Type; + +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv6Code; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv6Type; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpDscp; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpEcn; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpProto; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4Dst; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4Src; + +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6Dst; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6Flabel; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6NdSll; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6NdTarget; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6NdTll; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6Src; import org.projectfloodlight.openflow.protocol.oxm.OFOxmMetadata; import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsBos; import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel; @@ -203,7 +213,13 @@ public static void serializeActions(JsonGenerator jsonGenerator, List jsonGenerator.writeStringField(MatchUtils.STR_ARP_SPA, ((OFOxmArpSpa) ((OFActionSetField) a).getField()).getValue().toString()); // ipaddress formats string already } else if (((OFActionSetField)a).getField() instanceof OFOxmArpTpa) { jsonGenerator.writeStringField(MatchUtils.STR_ARP_DPA, ((OFOxmArpTpa) ((OFActionSetField) a).getField()).getValue().toString()); - } + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6NdSll) { + jsonGenerator.writeStringField(MatchUtils.STR_IPV6_ND_SSL, ((OFOxmIpv6NdSll) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6NdTll) { + jsonGenerator.writeStringField(MatchUtils.STR_IPV6_ND_TTL, ((OFOxmIpv6NdTll) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6NdTarget) { + jsonGenerator.writeStringField(MatchUtils.STR_IPV6_ND_TARGET, ((OFOxmIpv6NdTarget) ((OFActionSetField) a).getField()).getValue().toString()); + } /* DATA LAYER */ else if (((OFActionSetField)a).getField() instanceof OFOxmEthType) { jsonGenerator.writeNumberField(MatchUtils.STR_DL_TYPE, ((OFOxmEthType) ((OFActionSetField) a).getField()).getValue().getValue()); @@ -220,7 +236,11 @@ else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Code) { jsonGenerator.writeNumberField(MatchUtils.STR_ICMP_CODE, ((OFOxmIcmpv4Code) ((OFActionSetField) a).getField()).getValue().getCode()); } else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Type) { jsonGenerator.writeNumberField(MatchUtils.STR_ICMP_TYPE, ((OFOxmIcmpv4Type) ((OFActionSetField) a).getField()).getValue().getType()); - } + } else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv6Code) { + jsonGenerator.writeNumberField(MatchUtils.STR_ICMPV6_CODE, ((OFOxmIcmpv6Code) ((OFActionSetField) a).getField()).getValue().getRaw()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv6Type) { + jsonGenerator.writeNumberField(MatchUtils.STR_ICMPV6_TYPE, ((OFOxmIcmpv6Type) ((OFActionSetField) a).getField()).getValue().getRaw()); + } /* NETWORK LAYER */ else if (((OFActionSetField)a).getField() instanceof OFOxmIpProto) { jsonGenerator.writeNumberField(MatchUtils.STR_NW_PROTO, ((OFOxmIpProto) ((OFActionSetField) a).getField()).getValue().getIpProtocolNumber()); @@ -228,7 +248,13 @@ else if (((OFActionSetField)a).getField() instanceof OFOxmIpProto) { jsonGenerator.writeStringField(MatchUtils.STR_NW_SRC, ((OFOxmIpv4Src) ((OFActionSetField) a).getField()).getValue().toString()); } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Dst) { jsonGenerator.writeStringField(MatchUtils.STR_NW_DST, ((OFOxmIpv4Dst) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIpEcn) { + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6Src) { + jsonGenerator.writeStringField(MatchUtils.STR_IPV6_SRC, ((OFOxmIpv6Src) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6Dst) { + jsonGenerator.writeStringField(MatchUtils.STR_IPV6_DST, ((OFOxmIpv6Dst) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6Flabel) { + jsonGenerator.writeStringField(MatchUtils.STR_IPV6_FLOW_LABEL, ((OFOxmIpv6Flabel) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpEcn) { jsonGenerator.writeNumberField(MatchUtils.STR_NW_ECN, ((OFOxmIpEcn) ((OFActionSetField) a).getField()).getValue().getEcnValue()); } else if (((OFActionSetField)a).getField() instanceof OFOxmIpDscp) { jsonGenerator.writeNumberField(MatchUtils.STR_NW_DSCP, ((OFOxmIpDscp) ((OFActionSetField) a).getField()).getValue().getDscpValue()); diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java index 8dcb12baf8..4399c95abc 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java @@ -24,6 +24,7 @@ import net.floodlightcontroller.core.annotations.LogMessageCategory; import net.floodlightcontroller.core.util.AppCookie; +import net.floodlightcontroller.staticflowentry.web.StaticFlowEntryPusherResource; import net.floodlightcontroller.util.ActionUtils; import net.floodlightcontroller.util.InstructionUtils; @@ -137,7 +138,7 @@ public static String getEntryNameFromJson(String fmJson) throws IOException{ * @param name The name of this static flow entry * @return A Map representation of the storage entry */ - public static Map flowModToStorageEntry(OFFlowMod fm, String sw, String name) { + public static Map flowModToStorageEntry(OFFlowMod fm, String sw, String name) throws Exception { Map entry = new HashMap(); entry.put(StaticFlowEntryPusher.COLUMN_NAME, name); entry.put(StaticFlowEntryPusher.COLUMN_SWITCH, sw); @@ -271,6 +272,35 @@ public static Map flowModToStorageEntry(OFFlowMod fm, String sw, 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; + case IPV6_DST: + entry.put(StaticFlowEntryPusher.COLUMN_NW6_DST, match.get(MatchField.IPV6_DST).toString()); + break; + case IPV6_FLABEL: + entry.put(StaticFlowEntryPusher.COLUMN_IPV6_FLOW_LABEL, match.get(MatchField.IPV6_FLABEL).toString()); + break; + case ICMPV6_TYPE: + entry.put(StaticFlowEntryPusher.COLUMN_ICMP6_TYPE, String.valueOf(match.get(MatchField.ICMPV6_TYPE).getValue())); + break; + case ICMPV6_CODE: + entry.put(StaticFlowEntryPusher.COLUMN_ICMP6_CODE, match.get(MatchField.ICMPV6_CODE).getValue()); + break; + case IPV6_ND_SLL: + entry.put(StaticFlowEntryPusher.COLUMN_ND_SLL, match.get(MatchField.IPV6_ND_SLL).toString()); + break; + case IPV6_ND_TLL: + entry.put(StaticFlowEntryPusher.COLUMN_ND_TLL, match.get(MatchField.IPV6_ND_TLL).toString()); + break; + case IPV6_ND_TARGET: + entry.put(StaticFlowEntryPusher.COLUMN_ND_TARGET, match.get(MatchField.IPV6_ND_TARGET).toString()); + break; + +//sanjivini + case MPLS_LABEL: entry.put(StaticFlowEntryPusher.COLUMN_MPLS_LABEL, match.get(MatchField.MPLS_LABEL).getValue()); break; @@ -293,6 +323,10 @@ public static Map flowModToStorageEntry(OFFlowMod fm, String sw, } // end switch-case } // end while + int result = StaticFlowEntryPusherResource.checkActions(entry); + if (result == -1) + throw new Exception("Invalid action/instructions"); + return entry; } @@ -458,6 +492,34 @@ public static Map jsonToStorageEntry(String fmJson) throws IOExc case StaticFlowEntryPusher.COLUMN_ARP_DPA: entry.put(StaticFlowEntryPusher.COLUMN_ARP_DPA, jp.getText()); break; + +//sanjivini + case StaticFlowEntryPusher.COLUMN_NW6_SRC: + entry.put(StaticFlowEntryPusher.COLUMN_NW6_SRC, jp.getText()); + break; + case StaticFlowEntryPusher.COLUMN_NW6_DST: + entry.put(StaticFlowEntryPusher.COLUMN_NW6_DST, jp.getText()); + break; + case StaticFlowEntryPusher.COLUMN_IPV6_FLOW_LABEL: + entry.put(StaticFlowEntryPusher.COLUMN_IPV6_FLOW_LABEL, jp.getText()); + break; + case StaticFlowEntryPusher.COLUMN_ICMP6_TYPE: + entry.put(StaticFlowEntryPusher.COLUMN_ICMP6_TYPE, jp.getText()); + break; + case StaticFlowEntryPusher.COLUMN_ICMP6_CODE: + entry.put(StaticFlowEntryPusher.COLUMN_ICMP6_CODE, jp.getText()); + break; + case StaticFlowEntryPusher.COLUMN_ND_SLL: + entry.put(StaticFlowEntryPusher.COLUMN_ND_SLL, jp.getText()); + break; + case StaticFlowEntryPusher.COLUMN_ND_TLL: + entry.put(StaticFlowEntryPusher.COLUMN_ND_TLL, jp.getText()); + break; + case StaticFlowEntryPusher.COLUMN_ND_TARGET: + entry.put(StaticFlowEntryPusher.COLUMN_ND_TARGET, jp.getText()); + break; +//sanjivini + 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 489a8f949e..9153b12451 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java @@ -131,6 +131,18 @@ public class StaticFlowEntryPusher public static final String COLUMN_ARP_DHA = MatchUtils.STR_ARP_DHA; 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 + 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; + public static final String COLUMN_ICMP6_TYPE = MatchUtils.STR_ICMPV6_TYPE; + public static final String COLUMN_ICMP6_CODE = MatchUtils.STR_ICMPV6_CODE; + 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; @@ -164,6 +176,13 @@ public class StaticFlowEntryPusher COLUMN_ICMP_TYPE, COLUMN_ICMP_CODE, COLUMN_ARP_OPCODE, COLUMN_ARP_SHA, COLUMN_ARP_DHA, COLUMN_ARP_SPA, COLUMN_ARP_DPA, + +//sanjivini + //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_MPLS_LABEL, COLUMN_MPLS_TC, COLUMN_MPLS_BOS, COLUMN_METADATA, COLUMN_TUNNEL_ID, COLUMN_PBB_ISID, /* end newly added matches */ @@ -408,6 +427,13 @@ void parseRow(Map row, Map> entri log.debug("ignoring flow entry {} on switch {} with illegal OFMatch() key: " + match, entryName, switchName); return; } +//sanjivini + catch (Exception e) { + log.error("OF version incompatible for the match: " + match); + e.printStackTrace(); + return; + } +//sanjivini entries.get(switchName).put(entryName, fmb.build()); // add the FlowMod message to the table } @@ -754,8 +780,13 @@ public void startUp(FloodlightModuleContext context) { @Override public void addFlow(String name, OFFlowMod fm, DatapathId swDpid) { - Map fmMap = StaticFlowEntries.flowModToStorageEntry(fm, swDpid.toString(), name); - storageSourceService.insertRowAsync(TABLE_NAME, fmMap); + try { + Map fmMap = StaticFlowEntries.flowModToStorageEntry(fm, swDpid.toString(), name); + storageSourceService.insertRowAsync(TABLE_NAME, fmMap); + } catch (Exception e) { + log.error("Error! Check the fields specified for the flow.Make sure IPv4 fields are not mixed with IPv6 fields or all " + + "mandatory fields are specified. "); + } } @Override diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java b/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java index c4945a46e7..c2cd26aa66 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/web/StaticFlowEntryPusherResource.java @@ -32,6 +32,7 @@ import net.floodlightcontroller.staticflowentry.StaticFlowEntries; import net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher; import net.floodlightcontroller.storage.IStorageSourceService; +import net.floodlightcontroller.util.MatchUtils; /** * Pushes a static flow entry to the storage source @@ -43,137 +44,236 @@ public class StaticFlowEntryPusherResource extends ServerResource { protected static Logger log = LoggerFactory.getLogger(StaticFlowEntryPusherResource.class); /** - * Checks to see if the user matches IP information without - * checking for the correct ether-type (2048). - * @param rows The Map that is a string representation of - * the static flow. - * @reutrn True if they checked the ether-type, false otherwise + * Validates if all the mandatory fields are set properly while adding an IPv6 flow + * @param Map containing the fields of the flow + * @return state indicating whether a flow is valid or not */ - private boolean checkMatchIp(Map rows) { - boolean matchEther = false; - String val = (String) rows.get(StaticFlowEntryPusher.COLUMN_DL_TYPE); - if (val != null) { - int type = 0; - // check both hex and decimal - if (val.startsWith("0x")) { - type = Integer.parseInt(val.substring(2), 16); + private int checkFlow(Map rows) { + //Declaring & Initializing flags + int state = 0; + boolean dl_type = false; + boolean nw_proto = false; + boolean nw_layer = false; + boolean icmp6_type = false; + boolean icmp6_code = false; + boolean nd_target = false; + boolean nd_sll = false; + boolean nd_tll = false; + boolean ip6 = false; + boolean ip4 = false; + + int eth_type = -1; + int nw_protocol = -1; + int icmp_type = -1; + + //Determine the dl_type if set + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_DL_TYPE)) { + if (((String) rows.get(StaticFlowEntryPusher.COLUMN_DL_TYPE)).startsWith("0x")) { + eth_type = Integer.parseInt(((String) rows.get(StaticFlowEntryPusher.COLUMN_DL_TYPE)).replaceFirst("0x", ""), 16); + dl_type = true; + } else { + eth_type = Integer.parseInt((String) rows.get(StaticFlowEntryPusher.COLUMN_DL_TYPE)); + dl_type = true; + } + if (eth_type == 0x86dd) { /* or 34525 */ + ip6 = true; + dl_type = true; + } else if (eth_type == 0x800 || /* or 2048 */ + eth_type == 0x806 || /* or 2054 */ + eth_type == 0x8035) { /* or 32821*/ + ip4 = true; + dl_type = true; + } + //else { + // state = 2; + // return state; + //} + } + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_DST) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_SRC)) { + nw_layer = true; + ip4 = true; + } + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_ICMP_CODE) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_ICMP_TYPE) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_ARP_DHA) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_ARP_SHA) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_ARP_SPA) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_ARP_DPA) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_ARP_OPCODE)) { + ip4 = true; + } + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_IPV6_FLOW_LABEL) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_NW6_SRC) || + rows.containsKey(StaticFlowEntryPusher.COLUMN_NW6_DST)) { + nw_layer = true; + ip6 = true; + } + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_PROTO)) { + nw_proto = true; + if (((String) rows.get(StaticFlowEntryPusher.COLUMN_NW_PROTO)).startsWith("0x")) { + nw_protocol = Integer.parseInt(((String) rows.get(StaticFlowEntryPusher.COLUMN_NW_PROTO)).replaceFirst("0x", ""), 16); } else { - try { - type = Integer.parseInt(val); - } catch (NumberFormatException e) { /* fail silently */} + nw_protocol = Integer.parseInt((String) rows.get(StaticFlowEntryPusher.COLUMN_NW_PROTO)); } - if (type == 2048) matchEther = true; } + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_ICMP6_CODE)) { + icmp6_code = true; + ip6 = true; + } + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_ICMP6_TYPE)) { + icmp6_type = true; + ip6 = true; + if (((String) rows.get(StaticFlowEntryPusher.COLUMN_ICMP_TYPE)).startsWith("0x")) { + icmp_type = Integer.parseInt(((String) rows.get(StaticFlowEntryPusher.COLUMN_ICMP6_TYPE)).replaceFirst("0x", ""), 16); + } else { + icmp_type = Integer.parseInt((String) rows.get(StaticFlowEntryPusher.COLUMN_ICMP6_TYPE)); + } + } + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_ND_SLL)) { + nd_sll = true; + ip6 = true; + } + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_ND_TLL)) { + nd_tll = true; + ip6 = true; + } + if (rows.containsKey(StaticFlowEntryPusher.COLUMN_ND_TARGET)) { + nd_target = true; + ip6 = true; + } - if ((rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_DST) || - rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_SRC) || - rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_PROTO) || - rows.containsKey(StaticFlowEntryPusher.COLUMN_NW_TOS)) && - (matchEther == false)) - return false; + if (nw_layer == true || nw_proto == true) { + if (dl_type == true) { + if (!(ip4 == true || ip6 == true)) { + //invalid dl_type + state = 2; + return state; + } + } + else { + //dl_type not set + state = 1; + return state; + } + } + if (icmp6_type == true || icmp6_code == true ) { + if (nw_proto == true) { + if (nw_protocol != 0x3A) { /* or 58 */ + //invalid nw_proto + state = 4; + return state; + } + } + else { + //nw_proto not set + state = 3; + return state; + } + } + + if (nd_sll == true || nd_tll == true || nd_target == true) { + if (icmp6_type == true) { + //icmp_type must be set to 135/136 to set ipv6_nd_target + if (nd_target == true) { + if (!(icmp_type == 135 || icmp_type == 136)) { + //invalid icmp6_type + state = 6; + return state; + } + } + //icmp_type must be set to 136 to set ipv6_nd_tll + else if (nd_tll == true) { + if (!(icmp_type == 136)) { + //invalid icmp6_type + state = 6; + return state; + } + } + //icmp_type must be set to 135 to set ipv6_nd_sll + else if (nd_sll == true) { + if (!(icmp_type == 135)) { + //invalid icmp6_type + state = 6; + return state; + } + } + } + else { + //icmp6_type not set + state = 5; + return state; + } + } + + int result = checkActions(rows); + + if ((ip4 == true && ip6 == true) || (result == -1) || + (result == 1 && ip6 == true) || (result == 2 && ip4 == true)) { + //ipv4 & ipv6 conflict + state = 7; + return state; + } + + return state; - return true; } /** - * The check for flow entry validity will happen only when the SFP's - * storage listener detects the row entry is inserted. This, unfortunately, - * is after the REST API returns the message to the user who's inserting - * the flow. + * Validates actions/instructions * - * This function will perform the same error checking that will happen - * automatically later when the OFFlowMod is composed and built. This is - * somewhat redundant, since the flow entry will only be sent to the - * switch if it's valid, but this is the only way to tell the user something - * wasn't correct in their flow definition. + * -1 --> IPv4/IPv6 conflict + * 0 --> no IPv4 or IPv6 actions + * 1 --> IPv4 only actions + * 2 --> IPv6 only actions * - * @param row - * @return A String describing the error if there is one; the empty string if all checks - * - private String validateFlowEntry(Map row) { - /* - * First, build the match string and try to turn it into a - * Match.Builder with all the fields set. Then, before the - * it's built, check all prerequisites. - * - IOFSwitchService switchService = (IOFSwitchService) getContext() - .getAttributes() - .get(IOFSwitchService.class.getCanonicalName()); - String switchName = (String) row.get(StaticFlowEntryPusher.COLUMN_SWITCH); - String entryName = (String) row.get(StaticFlowEntryPusher.COLUMN_NAME); - String matchString; - DatapathId dpid; - - try { - dpid = DatapathId.of(switchName); - } catch (NumberFormatException e) { - return "Invalid switch DPID " + switchName + "."; - } - - IOFSwitch theSwitch = switchService.getSwitch(DatapathId.of(switchName)); - - if (theSwitch == null) { - return "Switch " + switchName + " is not connected to the controller."; - } - - for (String key : row.keySet()) { - // get the correct builder for the OF version supported by the switch - OFFlowModify.Builder fmb = theSwitch.getOFFactory().buildFlowModify(); - - StaticFlowEntries.initDefaultFlowMod(fmb, entryName); - - if (row.get(key) == null - || key.equals(StaticFlowEntryPusher.COLUMN_SWITCH) - || key.equals(StaticFlowEntryPusher.COLUMN_NAME) - || key.equals("id") - || key.equals(StaticFlowEntryPusher.COLUMN_HARD_TIMEOUT) - || key.equals(StaticFlowEntryPusher.COLUMN_IDLE_TIMEOUT)) { - continue; - } - - if (key.equals(StaticFlowEntryPusher.COLUMN_ACTIVE)) { - if (!Boolean.valueOf((String) row.get(StaticFlowEntryPusher.COLUMN_ACTIVE))) { - log.debug("Flow entry is inactive; verifying it anyway."); - } - } else if (key.equals(StaticFlowEntryPusher.COLUMN_TABLE_ID)) { - if (fmb.getVersion() != OFVersion.OF_10) { // all except 1.0 support tables - fmb.setTableId(TableId.of(Integer.parseInt((String) row.get(key)))); // support multiple flow tables for OF1.1+ - } else { - return "Tables not supported in OpenFlow 1.0."; - } - } else if (key.equals(StaticFlowEntryPusher.COLUMN_ACTIONS)) { - ActionUtils.fromString(fmb, (String) row.get(StaticFlowEntryPusher.COLUMN_ACTIONS), log); - } else if (key.equals(StaticFlowEntryPusher.COLUMN_COOKIE)) { - fmb.setCookie(StaticFlowEntries.computeEntryCookie(Integer.valueOf((String) row.get(StaticFlowEntryPusher.COLUMN_COOKIE)), entryName)); - } else if (key.equals(StaticFlowEntryPusher.COLUMN_PRIORITY)) { - fmb.setPriority(U16.t(Integer.valueOf((String) row.get(StaticFlowEntryPusher.COLUMN_PRIORITY)))); - } else if (key.equals(StaticFlowEntryPusher.COLUMN_INSTR_APPLY_ACTIONS)) { - InstructionUtils.applyActionsFromString(fmb, (String) row.get(StaticFlowEntryPusher.COLUMN_INSTR_APPLY_ACTIONS), log); - } else if (key.equals(StaticFlowEntryPusher.COLUMN_INSTR_CLEAR_ACTIONS)) { - InstructionUtils.clearActionsFromString(fmb, (String) row.get(StaticFlowEntryPusher.COLUMN_INSTR_CLEAR_ACTIONS), log); - } else if (key.equals(StaticFlowEntryPusher.COLUMN_INSTR_EXPERIMENTER)) { - InstructionUtils.experimenterFromString(fmb, (String) row.get(StaticFlowEntryPusher.COLUMN_INSTR_EXPERIMENTER), log); - } else if (key.equals(StaticFlowEntryPusher.COLUMN_INSTR_GOTO_METER)) { - InstructionUtils.meterFromString(fmb, (String) row.get(StaticFlowEntryPusher.COLUMN_INSTR_GOTO_METER), log); - } else if (key.equals(StaticFlowEntryPusher.COLUMN_INSTR_GOTO_TABLE)) { - InstructionUtils.gotoTableFromString(fmb, (String) row.get(StaticFlowEntryPusher.COLUMN_INSTR_GOTO_TABLE), log); - } else if (key.equals(StaticFlowEntryPusher.COLUMN_INSTR_WRITE_ACTIONS)) { - InstructionUtils.writeActionsFromString(fmb, (String) row.get(StaticFlowEntryPusher.COLUMN_INSTR_WRITE_ACTIONS), log); - } else if (key.equals(StaticFlowEntryPusher.COLUMN_INSTR_WRITE_METADATA)) { - InstructionUtils.writeMetadataFromString(fmb, (String) row.get(StaticFlowEntryPusher.COLUMN_INSTR_WRITE_METADATA), log); - } else { // the rest of the keys are for Match().fromString() - if (matchString.length() > 0) { - matchString.append(","); - } - matchString.append(key + "=" + row.get(key).toString()); + * @param Map containing the fields of the flow + * @return state indicating whether a flow is valid or not + */ + public static int checkActions(Map entry) { + + boolean ip6 = false; + boolean ip4 = false; + String actions = null; + + if (entry.containsKey(StaticFlowEntryPusher.COLUMN_ACTIONS) || + entry.containsKey(StaticFlowEntryPusher.COLUMN_INSTR_APPLY_ACTIONS) || + entry.containsKey(StaticFlowEntryPusher.COLUMN_INSTR_WRITE_ACTIONS)) { + if (entry.containsKey(StaticFlowEntryPusher.COLUMN_ACTIONS)) { + actions = (String) entry.get(StaticFlowEntryPusher.COLUMN_ACTIONS); + } + else if (entry.containsKey(StaticFlowEntryPusher.COLUMN_INSTR_APPLY_ACTIONS)) { + actions = (String) entry.get(StaticFlowEntryPusher.COLUMN_INSTR_APPLY_ACTIONS); + } + else if (entry.containsKey(StaticFlowEntryPusher.COLUMN_INSTR_WRITE_ACTIONS)) { + actions = (String) entry.get(StaticFlowEntryPusher.COLUMN_INSTR_WRITE_ACTIONS); } - } - String match = matchString.toString(); - fmb.setMatch(MatchUtils.fromString(match, fmb.getVersion())); + if (actions.contains(MatchUtils.STR_ICMPV6_CODE) || actions.contains(MatchUtils.STR_ICMPV6_TYPE) || + actions.contains(MatchUtils.STR_IPV6_DST) || actions.contains(MatchUtils.STR_IPV6_SRC) || + actions.contains(MatchUtils.STR_IPV6_FLOW_LABEL) || actions.contains(MatchUtils.STR_IPV6_ND_SSL) || + actions.contains(MatchUtils.STR_IPV6_ND_TARGET) || actions.contains(MatchUtils.STR_IPV6_ND_TTL)) { + ip6 = true; + } + if (actions.contains(MatchUtils.STR_NW_SRC) || actions.contains(MatchUtils.STR_NW_DST) || + actions.contains(MatchUtils.STR_ARP_OPCODE) || actions.contains(MatchUtils.STR_ARP_SHA) || + actions.contains(MatchUtils.STR_ARP_DHA) || actions.contains(MatchUtils.STR_ARP_SPA) || + actions.contains(MatchUtils.STR_ARP_DPA) || actions.contains(MatchUtils.STR_ICMP_CODE) || + actions.contains(MatchUtils.STR_ICMP_TYPE)) { + ip4 = true; + } + } - return ""; - } */ + if (ip6 == false && ip4 == false) { + return 0; // no actions involving ipv4 or ipv6 + } else if (ip6 == false && ip4 == true) { + return 1; //ipv4 + } else if (ip6 == true && ip4 == false) { + return 2; //ipv6 + } else { + return -1; // conflict of ipv4 and ipv6 actions + } + } /** * Takes a Static Flow Pusher string in JSON format and parses it into @@ -195,19 +295,39 @@ public String store(String fmJson) { try { rowValues = StaticFlowEntries.jsonToStorageEntry(fmJson); String status = null; - if (!checkMatchIp(rowValues)) { + + int state = checkFlow(rowValues); + if (state == 1) { status = "Warning! Must specify eth_type of IPv4/IPv6 to " + "match on IPv4/IPv6 fields! The flow has been discarded."; log.error(status); - } else { - status = "Entry pushed"; + } else if (state == 2) { + status = "Warning! eth_type not recognized! The flow has been discarded."; + log.error(status); + } else if (state == 3) { + status = "Warning! Must specify ip_proto to match! The flow has been discarded."; + log.error(status); + } else if (state == 4) { + status = "Warning! ip_proto invalid! The flow has been discarded."; + log.error(status); + } else if (state == 5) { + status = "Warning! Must specify icmp6_type to match! The flow has been discarded."; + log.error(status); + } else if (state == 6) { + status = "Warning! icmp6_type invalid! The flow has been discarded."; + log.error(status); + } else if (state == 7) { + status = "Warning! IPv4 & IPv6 fields cannot be specified in the same flow! The flow has been discarded."; + log.error(status); + } else if (state == 0) { + status = "Entry pushed"; + storageSource.insertRowAsync(StaticFlowEntryPusher.TABLE_NAME, rowValues); } - storageSource.insertRowAsync(StaticFlowEntryPusher.TABLE_NAME, rowValues); return ("{\"status\" : \"" + status + "\"}"); } catch (IOException e) { log.error("Error parsing push flow mod request: " + fmJson, e); return "{\"status\" : \"Error! Could not parse flod mod, see log for details.\"}"; - } + } } @Delete diff --git a/src/main/java/net/floodlightcontroller/util/ActionUtils.java b/src/main/java/net/floodlightcontroller/util/ActionUtils.java index c37d8b5548..f496304ec7 100644 --- a/src/main/java/net/floodlightcontroller/util/ActionUtils.java +++ b/src/main/java/net/floodlightcontroller/util/ActionUtils.java @@ -46,11 +46,19 @@ import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv4Code; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv4Type; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv6Code; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv6Type; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpDscp; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpEcn; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpProto; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4Dst; import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4Src; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6Dst; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6Flabel; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6NdSll; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6NdTarget; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6NdTll; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6Src; import org.projectfloodlight.openflow.protocol.oxm.OFOxmMetadata; import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel; import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsTc; @@ -67,6 +75,8 @@ import org.projectfloodlight.openflow.types.ICMPv4Code; import org.projectfloodlight.openflow.types.ICMPv4Type; import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.IPv6Address; +import org.projectfloodlight.openflow.types.IPv6FlowLabel; import org.projectfloodlight.openflow.types.IpDscp; import org.projectfloodlight.openflow.types.IpEcn; import org.projectfloodlight.openflow.types.IpProtocol; @@ -134,192 +144,208 @@ public class ActionUtils { */ /** - * Returns a String representation of all the OpenFlow actions. - * @param actions; A list of OFActions to encode into one string - * @return A dpctl-style string of the actions - */ - @LogMessageDoc(level="ERROR", - message="Could not decode action {action}", - explanation="A static flow entry contained an invalid action", - recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) - public static String actionsToString(List actions, Logger log) { - StringBuilder sb = new StringBuilder(); - for (OFAction a : actions) { - if (sb.length() > 0) { - sb.append(','); - } - switch(a.getType()) { - case OUTPUT: - sb.append(STR_OUTPUT + "=" + Integer.toString(((OFActionOutput)a).getPort().getPortNumber())); - break; - case ENQUEUE: - long queue = ((OFActionEnqueue)a).getQueueId(); - OFPort port = ((OFActionEnqueue)a).getPort(); - sb.append(STR_ENQUEUE + "=" + Integer.toString(port.getPortNumber()) + ":0x" + String.format("%02x", queue)); - break; - case STRIP_VLAN: - sb.append(STR_VLAN_STRIP); - break; - case POP_VLAN: - sb.append(STR_VLAN_POP); - break; - case PUSH_VLAN: - sb.append(STR_VLAN_PUSH + "=" + Integer.toString(((OFActionPushVlan)a).getEthertype().getValue())); - break; - case SET_VLAN_VID: - sb.append(STR_VLAN_SET_VID + "=" + Short.toString(((OFActionSetVlanVid)a).getVlanVid().getVlan())); - break; - case SET_VLAN_PCP: - sb.append(STR_VLAN_SET_PCP + "=" + Byte.toString(((OFActionSetVlanPcp)a).getVlanPcp().getValue())); - break; - case SET_QUEUE: - sb.append(STR_QUEUE_SET + "=" + Long.toString(((OFActionSetQueue)a).getQueueId())); - case SET_DL_SRC: - sb.append(STR_DL_SRC_SET + "=" + ((OFActionSetDlSrc)a).getDlAddr().toString()); - break; - case SET_DL_DST: - sb.append(STR_DL_DST_SET + "=" + ((OFActionSetDlDst)a).getDlAddr().toString()); - break; - case SET_NW_ECN: - sb.append(STR_NW_ECN_SET + "=" + Byte.toString(((OFActionSetNwEcn)a).getNwEcn().getEcnValue())); - break; - case SET_NW_TOS: - sb.append(STR_NW_TOS_SET + "=" + Short.toString(((OFActionSetNwTos)a).getNwTos())); - break; - case SET_NW_TTL: - sb.append(STR_NW_TTL_SET + "=" + Short.toString(((OFActionSetNwTtl)a).getNwTtl())); - break; - case DEC_NW_TTL: - sb.append(STR_NW_TTL_DEC); - break; - case SET_MPLS_LABEL: - sb.append(STR_MPLS_LABEL_SET + "=" + Long.toString(((OFActionSetMplsLabel)a).getMplsLabel())); - break; - case SET_MPLS_TC: - sb.append(STR_MPLS_TC_SET + "=" + Short.toString(((OFActionSetMplsTc)a).getMplsTc())); - break; - case SET_MPLS_TTL: - sb.append(STR_MPLS_TTL_SET + "=" + Short.toString(((OFActionSetMplsTtl)a).getMplsTtl())); - break; - case DEC_MPLS_TTL: - sb.append(STR_MPLS_TTL_DEC); - break; - case PUSH_MPLS: - sb.append(STR_MPLS_PUSH + "=" + Integer.toString(((OFActionPushMpls)a).getEthertype().getValue())); - break; - case POP_MPLS: - sb.append(STR_MPLS_POP + "=" + Integer.toString(((OFActionPopMpls)a).getEthertype().getValue())); - break; - case SET_NW_SRC: - sb.append(STR_NW_SRC_SET + "=" + ((OFActionSetNwSrc)a).getNwAddr().toString()); - break; - case SET_NW_DST: - sb.append(STR_NW_DST_SET + "=" + ((OFActionSetNwDst)a).getNwAddr().toString()); - break; - case SET_TP_SRC: - sb.append(STR_TP_SRC_SET + "=" + ((OFActionSetTpSrc)a).getTpPort().toString()); - break; - case SET_TP_DST: - sb.append(STR_TP_DST_SET + "=" + ((OFActionSetTpDst)a).getTpPort().toString()); - break; - case COPY_TTL_IN: - sb.append(STR_TTL_IN_COPY); - break; - case COPY_TTL_OUT: - sb.append(STR_TTL_OUT_COPY); - break; - case PUSH_PBB: - sb.append(STR_PBB_PUSH + "=" + Integer.toString(((OFActionPushPbb)a).getEthertype().getValue())); - break; - case POP_PBB: - sb.append(STR_PBB_POP); - break; - case EXPERIMENTER: - sb.append(STR_EXPERIMENTER + "=" + Long.toString(((OFActionExperimenter)a).getExperimenter())); - break; - case GROUP: - sb.append(STR_GROUP + "=" + Integer.toString(((OFActionGroup)a).getGroup().getGroupNumber())); - break; - case SET_FIELD: - log.debug("Got Set-Field action. Setting " + ((OFActionSetField)a)); - /* ARP */ - if (((OFActionSetField)a).getField() instanceof OFOxmArpOp) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_OPCODE + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmArpOp) ((OFActionSetField) a).getField()).getValue().getOpcode())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmArpSha) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_SHA + MatchUtils.SET_FIELD_DELIM + ((OFOxmArpSha) ((OFActionSetField) a).getField()).getValue().toString()); // macaddress formats string already - } else if (((OFActionSetField)a).getField() instanceof OFOxmArpTha) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_DHA + MatchUtils.SET_FIELD_DELIM + ((OFOxmArpTha) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmArpSpa) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_SPA + MatchUtils.SET_FIELD_DELIM + ((OFOxmArpSpa) ((OFActionSetField) a).getField()).getValue().toString()); // ipaddress formats string already - } else if (((OFActionSetField)a).getField() instanceof OFOxmArpTpa) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_DPA + MatchUtils.SET_FIELD_DELIM + ((OFOxmArpTpa) ((OFActionSetField) a).getField()).getValue().toString()); - } - /* DATA LAYER */ - else if (((OFActionSetField)a).getField() instanceof OFOxmEthType) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_TYPE + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmEthType) ((OFActionSetField) a).getField()).getValue().getValue())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmEthSrc) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_SRC + MatchUtils.SET_FIELD_DELIM + ((OFOxmEthSrc) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmEthDst) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_DST + MatchUtils.SET_FIELD_DELIM + ((OFOxmEthDst) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmVlanVid) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_VLAN + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmVlanVid) ((OFActionSetField) a).getField()).getValue().getVlan())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmVlanPcp) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_VLAN_PCP + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmVlanPcp) ((OFActionSetField) a).getField()).getValue().getValue())); - } - /* ICMP */ - else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Code) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ICMP_CODE + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmIcmpv4Code) ((OFActionSetField) a).getField()).getValue().getCode())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Type) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ICMP_TYPE + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmIcmpv4Type) ((OFActionSetField) a).getField()).getValue().getType())); - } - /* NETWORK LAYER */ - else if (((OFActionSetField)a).getField() instanceof OFOxmIpProto) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_PROTO + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmIpProto) ((OFActionSetField) a).getField()).getValue().getIpProtocolNumber())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Src) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_SRC + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv4Src) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Dst) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_DST + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv4Dst) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIpEcn) { //TODO @Ryan ECN and DSCP need to have their own columns for OF1.3.... - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_ECN + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmIpEcn) ((OFActionSetField) a).getField()).getValue().getEcnValue())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIpDscp) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_DSCP + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmIpDscp) ((OFActionSetField) a).getField()).getValue().getDscpValue())); - } - /* TRANSPORT LAYER, TCP, UDP, and SCTP */ - else if (((OFActionSetField)a).getField() instanceof OFOxmTcpSrc) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_TCP_SRC + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmTcpSrc) ((OFActionSetField) a).getField()).getValue().getPort())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmTcpDst) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_TCP_DST + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmTcpDst) ((OFActionSetField) a).getField()).getValue().getPort())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmUdpSrc) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_UDP_SRC + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmUdpSrc) ((OFActionSetField) a).getField()).getValue().getPort())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmUdpDst) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_UDP_DST + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmUdpDst) ((OFActionSetField) a).getField()).getValue().getPort())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmSctpSrc) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_SCTP_SRC + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmSctpSrc) ((OFActionSetField) a).getField()).getValue().getPort())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmSctpDst) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_SCTP_DST + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmSctpDst) ((OFActionSetField) a).getField()).getValue().getPort())); - } - /* MPLS */ - else if (((OFActionSetField)a).getField() instanceof OFOxmMplsLabel) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_MPLS_LABEL + MatchUtils.SET_FIELD_DELIM + Long.toString(((OFOxmMplsLabel) ((OFActionSetField) a).getField()).getValue().getValue())); - } else if (((OFActionSetField)a).getField() instanceof OFOxmMplsTc) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_MPLS_TC + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmMplsTc) ((OFActionSetField) a).getField()).getValue().getValue())); - } // MPLS_BOS not implemented in loxi - /* METADATA */ - else if (((OFActionSetField)a).getField() instanceof OFOxmMetadata) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_METADATA + MatchUtils.SET_FIELD_DELIM + Long.toString(((OFOxmMetadata) ((OFActionSetField) a).getField()).getValue().getValue().getValue())); - } else { - log.error("Could not decode Set-Field action field: {}", ((OFActionSetField) a)); - } - break; - default: - log.error("Could not decode action: {}", a); - break; - } - - } - return sb.toString(); - } - + * Returns a String representation of all the OpenFlow actions. + * @param actions; A list of OFActions to encode into one string + * @return A dpctl-style string of the actions + */ + @LogMessageDoc(level="ERROR", + message="Could not decode action {action}", + explanation="A static flow entry contained an invalid action", + recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) + public static String actionsToString(List actions, Logger log) { + StringBuilder sb = new StringBuilder(); + for (OFAction a : actions) { + if (sb.length() > 0) { + sb.append(','); + } + switch(a.getType()) { + case OUTPUT: + sb.append(STR_OUTPUT + "=" + Integer.toString(((OFActionOutput)a).getPort().getPortNumber())); + break; + case ENQUEUE: + long queue = ((OFActionEnqueue)a).getQueueId(); + OFPort port = ((OFActionEnqueue)a).getPort(); + sb.append(STR_ENQUEUE + "=" + Integer.toString(port.getPortNumber()) + ":0x" + String.format("%02x", queue)); + break; + case STRIP_VLAN: + sb.append(STR_VLAN_STRIP); + break; + case POP_VLAN: + sb.append(STR_VLAN_POP); + break; + case PUSH_VLAN: + sb.append(STR_VLAN_PUSH + "=" + Integer.toString(((OFActionPushVlan)a).getEthertype().getValue())); + break; + case SET_VLAN_VID: + sb.append(STR_VLAN_SET_VID + "=" + Short.toString(((OFActionSetVlanVid)a).getVlanVid().getVlan())); + break; + case SET_VLAN_PCP: + sb.append(STR_VLAN_SET_PCP + "=" + Byte.toString(((OFActionSetVlanPcp)a).getVlanPcp().getValue())); + break; + case SET_QUEUE: + sb.append(STR_QUEUE_SET + "=" + Long.toString(((OFActionSetQueue)a).getQueueId())); + case SET_DL_SRC: + sb.append(STR_DL_SRC_SET + "=" + ((OFActionSetDlSrc)a).getDlAddr().toString()); + break; + case SET_DL_DST: + sb.append(STR_DL_DST_SET + "=" + ((OFActionSetDlDst)a).getDlAddr().toString()); + break; + case SET_NW_ECN: + sb.append(STR_NW_ECN_SET + "=" + Byte.toString(((OFActionSetNwEcn)a).getNwEcn().getEcnValue())); + break; + case SET_NW_TOS: + sb.append(STR_NW_TOS_SET + "=" + Short.toString(((OFActionSetNwTos)a).getNwTos())); + break; + case SET_NW_TTL: + sb.append(STR_NW_TTL_SET + "=" + Short.toString(((OFActionSetNwTtl)a).getNwTtl())); + break; + case DEC_NW_TTL: + sb.append(STR_NW_TTL_DEC); + break; + case SET_MPLS_LABEL: + sb.append(STR_MPLS_LABEL_SET + "=" + Long.toString(((OFActionSetMplsLabel)a).getMplsLabel())); + break; + case SET_MPLS_TC: + sb.append(STR_MPLS_TC_SET + "=" + Short.toString(((OFActionSetMplsTc)a).getMplsTc())); + break; + case SET_MPLS_TTL: + sb.append(STR_MPLS_TTL_SET + "=" + Short.toString(((OFActionSetMplsTtl)a).getMplsTtl())); + break; + case DEC_MPLS_TTL: + sb.append(STR_MPLS_TTL_DEC); + break; + case PUSH_MPLS: + sb.append(STR_MPLS_PUSH + "=" + Integer.toString(((OFActionPushMpls)a).getEthertype().getValue())); + break; + case POP_MPLS: + sb.append(STR_MPLS_POP + "=" + Integer.toString(((OFActionPopMpls)a).getEthertype().getValue())); + break; + case SET_NW_SRC: + sb.append(STR_NW_SRC_SET + "=" + ((OFActionSetNwSrc)a).getNwAddr().toString()); + break; + case SET_NW_DST: + sb.append(STR_NW_DST_SET + "=" + ((OFActionSetNwDst)a).getNwAddr().toString()); + break; + case SET_TP_SRC: + sb.append(STR_TP_SRC_SET + "=" + ((OFActionSetTpSrc)a).getTpPort().toString()); + break; + case SET_TP_DST: + sb.append(STR_TP_DST_SET + "=" + ((OFActionSetTpDst)a).getTpPort().toString()); + break; + case COPY_TTL_IN: + sb.append(STR_TTL_IN_COPY); + break; + case COPY_TTL_OUT: + sb.append(STR_TTL_OUT_COPY); + break; + case PUSH_PBB: + sb.append(STR_PBB_PUSH + "=" + Integer.toString(((OFActionPushPbb)a).getEthertype().getValue())); + break; + case POP_PBB: + sb.append(STR_PBB_POP); + break; + case EXPERIMENTER: + sb.append(STR_EXPERIMENTER + "=" + Long.toString(((OFActionExperimenter)a).getExperimenter())); + break; + case GROUP: + sb.append(STR_GROUP + "=" + Integer.toString(((OFActionGroup)a).getGroup().getGroupNumber())); + break; + case SET_FIELD: + log.debug("Got Set-Field action. Setting " + ((OFActionSetField)a)); + /* ARP */ + if (((OFActionSetField)a).getField() instanceof OFOxmArpOp) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_OPCODE + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmArpOp) ((OFActionSetField) a).getField()).getValue().getOpcode())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmArpSha) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_SHA + MatchUtils.SET_FIELD_DELIM + ((OFOxmArpSha) ((OFActionSetField) a).getField()).getValue().toString()); // macaddress formats string already + } else if (((OFActionSetField)a).getField() instanceof OFOxmArpTha) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_DHA + MatchUtils.SET_FIELD_DELIM + ((OFOxmArpTha) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmArpSpa) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_SPA + MatchUtils.SET_FIELD_DELIM + ((OFOxmArpSpa) ((OFActionSetField) a).getField()).getValue().toString()); // ipaddress formats string already + } else if (((OFActionSetField)a).getField() instanceof OFOxmArpTpa) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ARP_DPA + MatchUtils.SET_FIELD_DELIM + ((OFOxmArpTpa) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6NdSll) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_IPV6_ND_SSL + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv6NdSll) ((OFActionSetField) a).getField()).getValue().toString()); // macaddress formats string already + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6NdTll) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_IPV6_ND_TTL + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv6NdTll) ((OFActionSetField) a).getField()).getValue().toString()); // macaddress formats string already + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6NdTarget) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_IPV6_ND_TARGET + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv6NdTarget) ((OFActionSetField) a).getField()).getValue().toString()); + } + /* DATA LAYER */ + else if (((OFActionSetField)a).getField() instanceof OFOxmEthType) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_TYPE + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmEthType) ((OFActionSetField) a).getField()).getValue().getValue())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmEthSrc) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_SRC + MatchUtils.SET_FIELD_DELIM + ((OFOxmEthSrc) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmEthDst) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_DST + MatchUtils.SET_FIELD_DELIM + ((OFOxmEthDst) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmVlanVid) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_VLAN + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmVlanVid) ((OFActionSetField) a).getField()).getValue().getVlan())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmVlanPcp) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_DL_VLAN_PCP + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmVlanPcp) ((OFActionSetField) a).getField()).getValue().getValue())); + } + /* ICMP */ + else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Code) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ICMP_CODE + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmIcmpv4Code) ((OFActionSetField) a).getField()).getValue().getCode())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Type) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ICMP_TYPE + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmIcmpv4Type) ((OFActionSetField) a).getField()).getValue().getType())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv6Code) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ICMPV6_CODE + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmIcmpv6Code) ((OFActionSetField) a).getField()).getValue().getRaw())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv6Type) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_ICMPV6_TYPE + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmIcmpv6Type) ((OFActionSetField) a).getField()).getValue().getRaw())); + } + /* NETWORK LAYER */ + else if (((OFActionSetField)a).getField() instanceof OFOxmIpProto) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_PROTO + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmIpProto) ((OFActionSetField) a).getField()).getValue().getIpProtocolNumber())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Src) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_SRC + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv4Src) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Dst) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_DST + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv4Dst) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6Src) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_IPV6_SRC + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv6Src) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6Dst) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_IPV6_DST + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv6Dst) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv6Flabel) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_IPV6_FLOW_LABEL + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv6Flabel) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpEcn) { //TODO @Ryan ECN and DSCP need to have their own columns for OF1.3.... + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_ECN + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmIpEcn) ((OFActionSetField) a).getField()).getValue().getEcnValue())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpDscp) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_DSCP + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmIpDscp) ((OFActionSetField) a).getField()).getValue().getDscpValue())); + } + /* TRANSPORT LAYER, TCP, UDP, and SCTP */ + else if (((OFActionSetField)a).getField() instanceof OFOxmTcpSrc) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_TCP_SRC + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmTcpSrc) ((OFActionSetField) a).getField()).getValue().getPort())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmTcpDst) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_TCP_DST + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmTcpDst) ((OFActionSetField) a).getField()).getValue().getPort())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmUdpSrc) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_UDP_SRC + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmUdpSrc) ((OFActionSetField) a).getField()).getValue().getPort())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmUdpDst) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_UDP_DST + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmUdpDst) ((OFActionSetField) a).getField()).getValue().getPort())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmSctpSrc) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_SCTP_SRC + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmSctpSrc) ((OFActionSetField) a).getField()).getValue().getPort())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmSctpDst) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_SCTP_DST + MatchUtils.SET_FIELD_DELIM + Integer.toString(((OFOxmSctpDst) ((OFActionSetField) a).getField()).getValue().getPort())); + } + /* MPLS */ + else if (((OFActionSetField)a).getField() instanceof OFOxmMplsLabel) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_MPLS_LABEL + MatchUtils.SET_FIELD_DELIM + Long.toString(((OFOxmMplsLabel) ((OFActionSetField) a).getField()).getValue().getValue())); + } else if (((OFActionSetField)a).getField() instanceof OFOxmMplsTc) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_MPLS_TC + MatchUtils.SET_FIELD_DELIM + Short.toString(((OFOxmMplsTc) ((OFActionSetField) a).getField()).getValue().getValue())); + } // MPLS_BOS not implemented in loxi + /* METADATA */ + else if (((OFActionSetField)a).getField() instanceof OFOxmMetadata) { + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_METADATA + MatchUtils.SET_FIELD_DELIM + Long.toString(((OFOxmMetadata) ((OFActionSetField) a).getField()).getValue().getValue().getValue())); + } else { + log.error("Could not decode Set-Field action field: {}", ((OFActionSetField) a)); + } + break; + default: + log.error("Could not decode action: {}", a); + break; + } + + } + return sb.toString(); + } + /** * Parses OFFlowMod actions from strings. * @param fmb The OFFlowMod.Builder to set the actions for @@ -335,7 +361,7 @@ public static void fromString(OFFlowMod.Builder fmb, String bigString, Logger lo if (bigString != null) { bigString = bigString.toLowerCase(); String[] bigStringSplit = bigString.split(","); // split into separate action=value or action=key@value pairs - + String[] tmp; ArrayDeque actionToDecode = new ArrayDeque(); for (int i = 0; i < bigStringSplit.length; i++) { @@ -345,7 +371,7 @@ public static void fromString(OFFlowMod.Builder fmb, String bigString, Logger lo } actionToDecode.add(tmp); // actionToDecode contains [key, value] pairs. Create a queue of pairs to process. } - + while (!actionToDecode.isEmpty()) { String[] keyPair = actionToDecode.pollFirst(); String key; @@ -358,9 +384,9 @@ public static void fromString(OFFlowMod.Builder fmb, String bigString, Logger lo key = keyPair[0]; pair = keyPair[1]; } - + OFAction a = null; - + switch (key) { case STR_OUTPUT: a = decode_output(pair, fmb.getVersion(), log); @@ -415,6 +441,25 @@ public static void fromString(OFFlowMod.Builder fmb, String bigString, Logger lo .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()) + .build(); + break; + case MatchUtils.STR_IPV6_ND_TTL: + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpv6NdTll().setValue(MacAddress.of(actionData[1])).build()) + .build(); + break; + case MatchUtils.STR_IPV6_ND_TARGET: + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .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() @@ -477,9 +522,35 @@ public static void fromString(OFFlowMod.Builder fmb, String bigString, Logger lo } else { a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIcmpv4Type().setValue(ICMPv4Type.of(Short.parseShort(actionData[1]))).build()) - .build(); + .build(); } break; + + //sanjivini + case MatchUtils.STR_ICMPV6_CODE: + if (actionData[1].startsWith("0x")) { + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIcmpv6Code().setValue(U8.of(Short.parseShort(actionData[1].replaceFirst("0x", ""), 16))).build()) + .build(); + } else { + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIcmpv6Code().setValue(U8.of(Short.parseShort(actionData[1]))).build()) + .build(); + } + break; + case MatchUtils.STR_ICMPV6_TYPE: + if (actionData[1].startsWith("0x")) { + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIcmpv6Type().setValue(U8.of(Short.parseShort(actionData[1].replaceFirst("0x", ""), 16))).build()) + .build(); + } else { + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIcmpv6Type().setValue(U8.of(Short.parseShort(actionData[1]))).build()) + .build(); + } + break; + //sanjivini + case MatchUtils.STR_NW_PROTO: if (actionData[1].startsWith("0x")) { a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() @@ -501,6 +572,31 @@ public static void fromString(OFFlowMod.Builder fmb, String bigString, Logger lo .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()) + .build(); + break; + case MatchUtils.STR_IPV6_DST: + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpv6Dst().setValue(IPv6Address.of(actionData[1])).build()) + .build(); + break; + case MatchUtils.STR_IPV6_FLOW_LABEL: + if (actionData[1].startsWith("0x")) { + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpv6Flabel().setValue(IPv6FlowLabel.of(Integer.parseInt(actionData[1].replaceFirst("0x", ""), 16))).build()) + .build(); + } else { + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpv6Flabel().setValue(IPv6FlowLabel.of(Integer.parseInt(actionData[1]))).build()) + .build(); + } + break; + //sanjivini + case MatchUtils.STR_NW_ECN: if (actionData[1].startsWith("0x")) { a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() @@ -577,8 +673,8 @@ public static void fromString(OFFlowMod.Builder fmb, String bigString, Logger lo break; case MatchUtils.STR_MPLS_BOS: a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() - .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildMplsBos().setValue(OFBooleanValue.of(Boolean.parseBoolean(actionData[1]))).build()) // interprets anything other than "true" as false - .build(); + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildMplsBos().setValue(OFBooleanValue.of(Boolean.parseBoolean(actionData[1]))).build()) // interprets anything other than "true" as false + .build(); break; case MatchUtils.STR_METADATA: if (actionData[1].startsWith("0x")) { @@ -967,7 +1063,7 @@ private static OFActionSetDlSrc decode_set_src_mac(String actionToDecode, OFVers } return null; } - + /** * Parse set_dl_dst actions. * The key and delimiter for the action should be omitted, and only the diff --git a/src/main/java/net/floodlightcontroller/util/InstructionUtils.java b/src/main/java/net/floodlightcontroller/util/InstructionUtils.java index 013c87d360..43a6110ce7 100644 --- a/src/main/java/net/floodlightcontroller/util/InstructionUtils.java +++ b/src/main/java/net/floodlightcontroller/util/InstructionUtils.java @@ -28,7 +28,7 @@ * */ public class InstructionUtils { - public static final String STR_GOTO_TABLE = "goto_table"; + public static final String STR_GOTO_TABLE = "instruction_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"; @@ -169,7 +169,7 @@ public static void writeMetadataFromString(OFFlowMod.Builder fmb, String inst, L * @param log * @return */ - public static String writeActionsToString(OFInstructionWriteActions inst, Logger log) { + public static String writeActionsToString(OFInstructionWriteActions inst, Logger log) throws Exception { return ActionUtils.actionsToString(inst.getActions(), log); } @@ -200,7 +200,7 @@ public static void writeActionsFromString(OFFlowMod.Builder fmb, String inst, Lo * @param log * @return */ - public static String applyActionsToString(OFInstructionApplyActions inst, Logger log) { + public static String applyActionsToString(OFInstructionApplyActions inst, Logger log) throws Exception { return ActionUtils.actionsToString(inst.getActions(), log); } diff --git a/src/main/java/net/floodlightcontroller/util/MatchUtils.java b/src/main/java/net/floodlightcontroller/util/MatchUtils.java index ef7a94abed..f0828c9396 100644 --- a/src/main/java/net/floodlightcontroller/util/MatchUtils.java +++ b/src/main/java/net/floodlightcontroller/util/MatchUtils.java @@ -13,6 +13,9 @@ import org.projectfloodlight.openflow.types.ICMPv4Type; import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.IPv4AddressWithMask; +import org.projectfloodlight.openflow.types.IPv6Address; +import org.projectfloodlight.openflow.types.IPv6AddressWithMask; +import org.projectfloodlight.openflow.types.IPv6FlowLabel; import org.projectfloodlight.openflow.types.IpDscp; import org.projectfloodlight.openflow.types.IpEcn; import org.projectfloodlight.openflow.types.IpProtocol; @@ -330,6 +333,9 @@ public static String toString(Match match) { * 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[]"; } @@ -356,6 +362,14 @@ public static Match fromString(String match, OFVersion ofVersion) throws Illegal Match.Builder mb = OFFactories.getFactory(ofVersion).buildMatch(); +//sanjivini + + //Determine if the OF version is 1.0 before adding a flow + 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. @@ -396,6 +410,28 @@ public static Match fromString(String match, OFVersion ofVersion) throws Illegal case STR_NW_SRC: mb.setMasked(MatchField.IPV4_SRC, IPv4AddressWithMask.of(key_value[1])); break; + +//sanjivini + case STR_IPV6_DST: + if (ver10 == true) { + throw new IllegalArgumentException("OF Version incompatible"); + } + mb.setMasked(MatchField.IPV6_DST, IPv6AddressWithMask.of(key_value[1])); + break; + case STR_IPV6_SRC: + if (ver10 == true) { + throw new IllegalArgumentException("OF Version incompatible"); + } + mb.setMasked(MatchField.IPV6_SRC, IPv6AddressWithMask.of(key_value[1])); + break; + case STR_IPV6_FLOW_LABEL: + if (ver10 == true) { + throw new IllegalArgumentException("OF Version incompatible"); + } + mb.setExact(MatchField.IPV6_FLABEL, IPv6FlowLabel.of(Integer.parseInt(key_value[1]))); + break; +//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))); @@ -504,6 +540,45 @@ public static Match fromString(String match, OFVersion ofVersion) throws Illegal mb.setExact(MatchField.ICMPV4_CODE, ICMPv4Code.of(Short.parseShort(key_value[1]))); } break; + +//sanjivini + case STR_ICMPV6_TYPE: + if (ver10 == true) { + throw new IllegalArgumentException("OF Version incompatible"); + //throw new Exception("OF Version incompatible"); + } + mb.setExact(MatchField.ICMPV6_TYPE, U8.of(Short.parseShort(key_value[1]))); + break; + case STR_ICMPV6_CODE: + if (ver10 == true) { + throw new IllegalArgumentException("OF Version incompatible"); + //throw new Exception("OF Version incompatible"); + } + mb.setExact(MatchField.ICMPV6_CODE, U8.of(Short.parseShort(key_value[1]))); + break; + case STR_IPV6_ND_SSL: + if (ver10 == true) { + throw new IllegalArgumentException("OF Version incompatible"); + //throw new Exception("OF Version incompatible"); + } + mb.setExact(MatchField.IPV6_ND_SLL, MacAddress.of(key_value[1])); + break; + case STR_IPV6_ND_TTL: + if (ver10 == true) { + throw new IllegalArgumentException("OF Version incompatible"); + //throw new Exception("OF Version incompatible"); + } + mb.setExact(MatchField.IPV6_ND_TLL, MacAddress.of(key_value[1])); + break; + case STR_IPV6_ND_TARGET: + if (ver10 == true) { + throw new IllegalArgumentException("OF Version incompatible"); + //throw new Exception("OF Version incompatible"); + } + mb.setExact(MatchField.IPV6_ND_TARGET, IPv6Address.of(key_value[1])); + break; +//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)));