@Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { if (!channel.isConnected()) { // In testing, I see decode being called AFTER decode last. // This check avoids that from reading corrupted frames return null; } // Note that a single call to decode results in reading a single // OFMessage from the channel buffer, which is passed on to, and processed // by, the controller (in OFChannelHandler). // This is different from earlier behavior (with the original openflowj), // where we parsed all the messages in the buffer, before passing on // a list of the parsed messages to the controller. // The performance *may or may not* not be as good as before. OFMessageReader<OFMessage> reader = OFFactories.getGenericReader(); OFMessage message = reader.readFrom(buffer); return message; }
/** * Send NX role request message to the switch requesting the specified * role. * * @param role role to request */ private int sendNxRoleRequest(RoleState role) throws IOException { // Convert the role enum to the appropriate role to send OFNiciraControllerRole roleToSend = OFNiciraControllerRole.ROLE_OTHER; switch (role) { case MASTER: roleToSend = OFNiciraControllerRole.ROLE_MASTER; break; case SLAVE: case EQUAL: default: // ensuring that the only two roles sent to 1.0 switches with // Nicira role support, are MASTER and SLAVE roleToSend = OFNiciraControllerRole.ROLE_OTHER; log.debug("Sending Nx Role.SLAVE to switch {}.", sw); } int xid = sw.getNextTransactionId(); OFExperimenter roleRequest = OFFactories.getFactory(OFVersion.OF_10) .buildNiciraControllerRoleRequest() .setXid(xid) .setRole(roleToSend) .build(); sw.sendRoleRequest(roleRequest); return xid; }
@Test public void groupStatsEvent() { TestOpenFlowGroupProviderService testProviderService = (TestOpenFlowGroupProviderService) providerService; OFGroupStatsReply.Builder rep1 = OFFactories.getFactory(OFVersion.OF_13).buildGroupStatsReply(); rep1.setXid(1); controller.processPacket(dpid1, rep1.build()); OFGroupDescStatsReply.Builder rep2 = OFFactories.getFactory(OFVersion.OF_13).buildGroupDescStatsReply(); assertNull("group entries is not set yet", testProviderService.getGroupEntries()); rep2.setXid(2); controller.processPacket(dpid1, rep2.build()); assertNotNull("group entries should be set", testProviderService.getGroupEntries()); }
/** * Parse set_vlan_id actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. Data with a leading 0x is permitted. * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionSetVlanVid decode_set_vlan_id(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("((?:0x)?\\d+)").matcher(actionToDecode); if (n.matches()) { if (n.group(1) != null) { try { VlanVid vlanid = VlanVid.ofVlan(get_short(n.group(1))); OFActionSetVlanVid.Builder ab = OFFactories.getFactory(version).actions().buildSetVlanVid(); ab.setVlanVid(vlanid); log.debug("action {}", ab.build()); return ab.build(); } catch (NumberFormatException e) { log.debug("Invalid VLAN in: {} (error ignored)", actionToDecode); return null; } } } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } return null; }
/** * Parse set_vlan_pcp actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. Data with a leading 0x is permitted. * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionSetVlanPcp decode_set_vlan_priority(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("((?:0x)?\\d+)").matcher(actionToDecode); if (n.matches()) { if (n.group(1) != null) { try { VlanPcp prior = VlanPcp.of(get_byte(n.group(1))); OFActionSetVlanPcp.Builder ab = OFFactories.getFactory(version).actions().buildSetVlanPcp(); ab.setVlanPcp(prior); log.debug("action {}", ab.build()); return ab.build(); } catch (NumberFormatException e) { log.debug("Invalid VLAN priority in: {} (error ignored)", actionToDecode); return null; } } } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } return null; }
/** * Parse set_dl_src actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. * * TODO should consider using MacAddress's built-in parser.... * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionSetDlSrc decode_set_src_mac(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("(?:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+))").matcher(actionToDecode); if (n.matches()) { MacAddress macaddr = MacAddress.of(get_mac_addr(n, actionToDecode, log)); if (macaddr != null) { OFActionSetDlSrc.Builder ab = OFFactories.getFactory(version).actions().buildSetDlSrc(); ab.setDlAddr(macaddr); log.debug("action {}", ab.build()); return ab.build(); } } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } return null; }
/** * Parse set_dl_dst actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. * * TODO should consider using MacAddress's built-in parser.... * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionSetDlDst decode_set_dst_mac(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("(?:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+)\\:(\\p{XDigit}+))").matcher(actionToDecode); if (n.matches()) { MacAddress macaddr = MacAddress.of(get_mac_addr(n, actionToDecode, log)); if (macaddr != null) { OFActionSetDlDst.Builder ab = OFFactories.getFactory(version).actions().buildSetDlDst(); ab.setDlAddr(macaddr); log.debug("action {}", ab.build()); return ab.build(); } } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } return null; }
/** * Parse set_tos actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. A leading 0x is permitted. * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionSetNwTos decode_set_tos_bits(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("((?:0x)?\\d+)").matcher(actionToDecode); if (n.matches()) { if (n.group(1) != null) { try { byte tosbits = get_byte(n.group(1)); OFActionSetNwTos.Builder ab = OFFactories.getFactory(version).actions().buildSetNwTos(); ab.setNwTos(tosbits); log.debug("action {}", ab.build()); return ab.build(); } catch (NumberFormatException e) { log.debug("Invalid dst-port in: {} (error ignored)", actionToDecode); return null; } } } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } return null; }
/** * Parse set_tp_src actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. A leading 0x is permitted. * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionSetTpSrc decode_set_src_port(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("((?:0x)?\\d+)").matcher(actionToDecode); if (n.matches()) { if (n.group(1) != null) { try { TransportPort portnum = TransportPort.of(get_int(n.group(1))); OFActionSetTpSrc.Builder ab = OFFactories.getFactory(version).actions().buildSetTpSrc(); ab.setTpPort(portnum); log.debug("action {}", ab.build()); return ab.build(); } catch (NumberFormatException e) { log.debug("Invalid src-port in: {} (error ignored)", actionToDecode); return null; } } } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } return null; }
/** * Parse set_tp_dst actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. A leading 0x is permitted. * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFAction decode_set_dst_port(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("((?:0x)?\\d+)").matcher(actionToDecode); if (n.matches()) { if (n.group(1) != null) { try { TransportPort portnum = TransportPort.of(get_int(n.group(1))); OFActionSetTpDst.Builder ab = OFFactories.getFactory(version).actions().buildSetTpDst(); ab.setTpPort(portnum); log.debug("action {}", ab.build()); return ab.build(); } catch (NumberFormatException e) { log.debug("Invalid dst-port in: {} (error ignored)", actionToDecode); return null; } } } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } return null; }
/** * Convert the string representation of an OFInstructionGotoTable to * an OFInstructionGotoTable. The instruction will be set within the * OFFlowMod.Builder provided. Notice nothing is returned, but the * side effect is the addition of an instruction in the OFFlowMod.Builder. * @param fmb; The FMB in which to append the new instruction * @param instStr; The string to parse the instruction from * @param log */ public static void gotoTableFromString(OFFlowMod.Builder fmb, String 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; } OFInstructionGotoTable.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildGotoTable(); // 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()); }
/** * Convert the string representation of an OFInstructionClearActions to * an OFInstructionClearActions. The instruction will be set within the * OFFlowMod.Builder provided. Notice nothing is returned, but the * side effect is the addition of an instruction in the OFFlowMod.Builder. * @param fmb; The FMB in which to append the new instruction * @param instStr; The string to parse the instruction from * @param log */ public static void clearActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { if (fmb.getVersion().compareTo(OFVersion.OF_11) < 0) { log.error("Clear Actions Instruction not supported in OpenFlow 1.0"); return; } if (inst != null && inst.trim().isEmpty()) { /* Allow the empty string, since this is what specifies clear (i.e. key clear does not have any defined values). */ OFInstructionClearActions i = OFFactories.getFactory(fmb.getVersion()).instructions().clearActions(); log.debug("Appending ClearActions instruction: {}", i); appendInstruction(fmb, i); log.debug("All instructions after append: {}", fmb.getInstructions()); } else { log.error("Got non-empty or null string, but ClearActions should not have any String sub-fields: {}", inst); } }
private OFPacketIn createPacketIn(String srcMAC, String dstMAC, String srcIp, String dstIp, short vlan) { IPacket testPacket = new Ethernet() .setDestinationMACAddress(dstMAC) .setSourceMACAddress(srcMAC) .setVlanID(vlan) .setEtherType(EthType.IPv4) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress(srcIp) .setDestinationAddress(dstIp) .setPayload(new UDP() .setSourcePort((short) 5000) .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); byte[] testPacketSerialized = testPacket.serialize(); OFPacketIn pi; // build out input packet pi = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() .setBufferId(OFBufferId.NO_BUFFER) .setData(testPacketSerialized) .setReason(OFPacketInReason.NO_MATCH) .build(); return pi; }
/** * Parse set_tp_dst actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. A leading 0x is permitted. * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFAction decode_set_dst_port(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("((?:0x)?\\d+)").matcher(actionToDecode); if (n.matches()) { if (n.group(1) != null) { try { TransportPort portnum = TransportPort.of(get_short(n.group(1))); OFActionSetTpDst.Builder ab = OFFactories.getFactory(version).actions().buildSetTpDst(); ab.setTpPort(portnum); log.debug("action {}", ab.build()); return ab.build(); } catch (NumberFormatException e) { log.debug("Invalid dst-port in: {} (error ignored)", actionToDecode); return null; } } } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } return null; }
/** * Convert the string representation of an OFInstructionMeter to * an OFInstructionMeter. The instruction will be set within the * OFFlowMod.Builder provided. Notice nothing is returned, but the * side effect is the addition of an instruction in the OFFlowMod.Builder. * @param fmb; The FMB in which to append the new instruction * @param instStr; The string to parse the instruction from * @param log */ public static void meterFromString(OFFlowMod.Builder fmb, String inst, Logger log) { if (inst == null || inst.isEmpty()) { return; } 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; } OFInstructionMeter.Builder ib = OFFactories.getFactory(fmb.getVersion()).instructions().buildMeter(); 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()); }
private int sendOF13RoleRequest(RoleState role) throws IOException { // Convert the role enum to the appropriate role to send OFControllerRole roleToSend = OFControllerRole.ROLE_NOCHANGE; switch (role) { case EQUAL: roleToSend = OFControllerRole.ROLE_EQUAL; break; case MASTER: roleToSend = OFControllerRole.ROLE_MASTER; break; case SLAVE: roleToSend = OFControllerRole.ROLE_SLAVE; break; default: log.warn("Sending default role.noChange to switch {}." + " Should only be used for queries.", sw); } int xid = sw.getNextTransactionId(); OFRoleRequest rrm = OFFactories.getFactory(OFVersion.OF_13) .buildRoleRequest() .setRole(roleToSend) .setXid(xid) //FIXME fix below when we actually use generation ids .setGenerationId(U64.ZERO) .build(); sw.sendRoleRequest(rrm); return xid; }
@Test public void groupModFailure() { TestOpenFlowGroupProviderService testProviderService = (TestOpenFlowGroupProviderService) providerService; GroupId groupId = new DefaultGroupId(1); List<GroupBucket> bucketList = Lists.newArrayList(); TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder(); builder.setOutput(PortNumber.portNumber(1)); GroupBucket bucket = DefaultGroupBucket.createSelectGroupBucket(builder.build()); bucketList.add(bucket); GroupBuckets buckets = new GroupBuckets(bucketList); List<GroupOperation> operationList = Lists.newArrayList(); GroupOperation operation = GroupOperation.createAddGroupOperation(groupId, GroupDescription.Type.SELECT, buckets); operationList.add(operation); GroupOperations operations = new GroupOperations(operationList); provider.performGroupOperation(deviceId, operations); OFGroupModFailedErrorMsg.Builder errorBuilder = OFFactories.getFactory(OFVersion.OF_13).errorMsgs().buildGroupModFailedErrorMsg(); OFGroupMod.Builder groupBuilder = OFFactories.getFactory(OFVersion.OF_13).buildGroupModify(); groupBuilder.setGroupType(OFGroupType.ALL); groupBuilder.setGroup(OFGroup.of(1)); errorBuilder.setCode(OFGroupModFailedCode.GROUP_EXISTS); errorBuilder.setXid(provider.getXidAndAdd(0) - 1); controller.processPacket(dpid1, errorBuilder.build()); assertNotNull("Operation failed should not be null", testProviderService.failedOperation); }
/** * Parse string and numerical port representations. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. Data can be any signed integer * as a string or the strings 'controller', 'local', 'ingress-port', 'normal', * or 'flood'. * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionOutput decode_output(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("((all)|(controller)|(local)|(ingress-port)|(normal)|(flood))").matcher(actionToDecode); OFActionOutput.Builder ab = OFFactories.getFactory(version).actions().buildOutput(); OFPort port = OFPort.ANY; if (n.matches()) { if (n.group(1) != null && n.group(1).equals("all")) port = OFPort.ALL; else if (n.group(1) != null && n.group(1).equals("controller")) port = OFPort.CONTROLLER; else if (n.group(1) != null && n.group(1).equals("local")) port = OFPort.LOCAL; else if (n.group(1) != null && n.group(1).equals("ingress-port")) port = OFPort.IN_PORT; else if (n.group(1) != null && n.group(1).equals("normal")) port = OFPort.NORMAL; else if (n.group(1) != null && n.group(1).equals("flood")) port = OFPort.FLOOD; ab.setPort(port); ab.setMaxLen(Integer.MAX_VALUE); log.debug("action {}", ab.build()); return ab.build(); } else { try { port = OFPort.of(Integer.parseInt(actionToDecode)); ab.setPort(port); ab.setMaxLen(Integer.MAX_VALUE); return ab.build(); } catch (NumberFormatException e) { log.error("Could not parse Integer port: '{}'", actionToDecode); return null; } } }
/** * Parse set_nw_src actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. * * TODO should consider using IPv4AddressWithMask's built-in parser.... * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionSetNwSrc decode_set_src_ip(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("(?:(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+))").matcher(actionToDecode); if (n.matches()) { IPv4Address ipaddr = IPv4Address.of(get_ip_addr(n, actionToDecode, log)); OFActionSetNwSrc.Builder ab = OFFactories.getFactory(version).actions().buildSetNwSrc(); ab.setNwAddr(ipaddr); log.debug("action {}", ab.build()); return ab.build(); } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } }
/** * Parse set_nw_dst actions. * The key and delimiter for the action should be omitted, and only the * data should be presented to this decoder. * * TODO should consider using IPv4AddressWithMask's built-in parser.... * * @param actionToDecode; The action as a string to decode * @param version; The OF version to create the action for * @param log * @return */ private static OFActionSetNwDst decode_set_dst_ip(String actionToDecode, OFVersion version, Logger log) { Matcher n = Pattern.compile("(?:(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+))").matcher(actionToDecode); if (n.matches()) { IPv4Address ipaddr = IPv4Address.of(get_ip_addr(n, actionToDecode, log)); OFActionSetNwDst.Builder ab = OFFactories.getFactory(version).actions().buildSetNwDst(); ab.setNwAddr(ipaddr); log.debug("action {}", ab.build()); return ab.build(); } else { log.debug("Invalid action: '{}'", actionToDecode); return null; } }
/** * Retains all fields in the Match parent. Converts the parent to an * equivalent Match of OFVersion version. No polite check is done to verify * if MatchFields in parent are supported in a Match of OFVersion * version. An exception will be thrown if there are any unsupported * fields during the conversion process. * * Note that a Match.Builder is returned. This is a convenience for cases * where MatchFields might be modified, added, or removed prior to being * built (e.g. in Forwarding/Routing between switches of different OFVersions). * Simply build the returned Match.Builder if you would like to treat this * function as a strict copy-to-version. * * @param parent, the Match to convert * @param version, the OFVersion to convert parent to * @return a Match.Builder of the newly-converted Match */ @SuppressWarnings("unchecked") public static Match.Builder convertToVersion(Match parent, OFVersion version) { /* Builder retains a parent MatchField list, but list will not be used to * build the new match if the builder's set methods have been invoked; only * additions will be built, and all parent MatchFields will be ignored, * even if they were not modified by the new builder. Create a builder, and * walk through m's list of non-wildcarded MatchFields. Set them all in the * new builder by invoking a set method for each. This will make them persist * in the Match built from this builder if the user decides to add or subtract * from the MatchField list. */ Match.Builder mb = OFFactories.getFactory(version).buildMatch(); Iterator<MatchField<?>> itr = parent.getMatchFields().iterator(); // only get exact or masked fields (not fully wildcarded) while(itr.hasNext()) { @SuppressWarnings("rawtypes") MatchField mf = itr.next(); if (parent.isExact(mf)) { mb.setExact(mf, parent.get(mf)); } else if (parent.isPartiallyMasked(mf)) { mb.setMasked(mf, parent.getMasked(mf)); } else { // it's either exact, masked, or wildcarded // itr only contains exact and masked MatchFields // we should never get here } } return mb; }
/** * Convert the string representation of an OFInstructionWriteActions to * an OFInstructionWriteActions. The instruction will be set within the * OFFlowMod.Builder provided. Notice nothing is returned, but the * side effect is the addition of an instruction in the OFFlowMod.Builder. * @param fmb; The FMB in which to append the new instruction * @param instStr; The string to parse the instruction from * @param log */ public static void writeActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { 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); ib.setActions(tmpFmb.getActions()); log.debug("Appending WriteActions instruction: {}", ib.build()); appendInstruction(fmb, ib.build()); log.debug("All instructions after append: {}", fmb.getInstructions()); }
/** * Convert the string representation of an OFInstructionApplyActions to * an OFInstructionApplyActions. The instruction will be set within the * OFFlowMod.Builder provided. Notice nothing is returned, but the * side effect is the addition of an instruction in the OFFlowMod.Builder. * @param fmb; The FMB in which to append the new instruction * @param instStr; The string to parse the instruction from * @param log */ public static void applyActionsFromString(OFFlowMod.Builder fmb, String inst, Logger log) { 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); ib.setActions(tmpFmb.getActions()); log.debug("Appending ApplyActions instruction: {}", ib.build()); appendInstruction(fmb, ib.build()); log.debug("All instructions after append: {}", fmb.getInstructions()); }
public static OFFlowAdd toFlowAdd(OFFlowMod fm) { OFVersion version = fm.getVersion(); OFFlowAdd.Builder b = OFFactories.getFactory(version).buildFlowAdd(); if (b.getVersion().compareTo(OFVersion.OF_10) == 0) { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) // cookie-mask not supported .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) // instructions not supported .setMatch(fm.getMatch()) // out-group not supported .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) // table-id not supported .setXid(fm.getXid()) .build(); } else { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) .setCookieMask(fm.getCookieMask()) // added in OF1.1 .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) .setInstructions(fm.getInstructions()) // added in OF1.1 .setMatch(fm.getMatch()) .setOutGroup(fm.getOutGroup()) // added in OF1.1 .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) .setTableId(fm.getTableId()) .setXid(fm.getXid()) .build(); } }
public static OFFlowDelete toFlowDelete(OFFlowMod fm) { OFVersion version = fm.getVersion(); OFFlowDelete.Builder b = OFFactories.getFactory(version).buildFlowDelete(); if (b.getVersion().compareTo(OFVersion.OF_10) == 0) { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) // cookie-mask not supported .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) // instructions not supported .setMatch(fm.getMatch()) // out-group not supported .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) // table-id not supported .setXid(fm.getXid()) .build(); } else { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) .setCookieMask(fm.getCookieMask()) // added in OF1.1 .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) .setInstructions(fm.getInstructions()) // added in OF1.1 .setMatch(fm.getMatch()) .setOutGroup(fm.getOutGroup()) // added in OF1.1 .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) .setTableId(fm.getTableId()) .setXid(fm.getXid()) .build(); } }
public static OFFlowDeleteStrict toFlowDeleteStrict(OFFlowMod fm) { OFVersion version = fm.getVersion(); OFFlowDeleteStrict.Builder b = OFFactories.getFactory(version).buildFlowDeleteStrict(); if (b.getVersion().compareTo(OFVersion.OF_10) == 0) { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) // cookie-mask not supported .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) // instructions not supported .setMatch(fm.getMatch()) // out-group not supported .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) // table-id not supported .setXid(fm.getXid()) .build(); } else { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) .setCookieMask(fm.getCookieMask()) // added in OF1.1 .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) .setInstructions(fm.getInstructions()) // added in OF1.1 .setMatch(fm.getMatch()) .setOutGroup(fm.getOutGroup()) // added in OF1.1 .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) .setTableId(fm.getTableId()) .setXid(fm.getXid()) .build(); } }
public static OFFlowModify toFlowModify(OFFlowMod fm) { OFVersion version = fm.getVersion(); OFFlowModify.Builder b = OFFactories.getFactory(version).buildFlowModify(); if (b.getVersion().compareTo(OFVersion.OF_10) == 0) { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) // cookie-mask not supported .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) // instructions not supported .setMatch(fm.getMatch()) // out-group not supported .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) // table-id not supported .setXid(fm.getXid()) .build(); } else { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) .setCookieMask(fm.getCookieMask()) // added in OF1.1 .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) .setInstructions(fm.getInstructions()) // added in OF1.1 .setMatch(fm.getMatch()) .setOutGroup(fm.getOutGroup()) // added in OF1.1 .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) .setTableId(fm.getTableId()) .setXid(fm.getXid()) .build(); } }
public static OFFlowModifyStrict toFlowModifyStrict(OFFlowMod fm) { OFVersion version = fm.getVersion(); OFFlowModifyStrict.Builder b = OFFactories.getFactory(version).buildFlowModifyStrict(); if (b.getVersion().compareTo(OFVersion.OF_10) == 0) { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) // cookie-mask not supported .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) // instructions not supported .setMatch(fm.getMatch()) // out-group not supported .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) // table-id not supported .setXid(fm.getXid()) .build(); } else { return b.setActions(fm.getActions()) .setBufferId(fm.getBufferId()) .setCookie(fm.getCookie()) .setCookieMask(fm.getCookieMask()) // added in OF1.1 .setFlags(fm.getFlags()) .setHardTimeout(fm.getHardTimeout()) .setIdleTimeout(fm.getIdleTimeout()) .setInstructions(fm.getInstructions()) // added in OF1.1 .setMatch(fm.getMatch()) .setOutGroup(fm.getOutGroup()) // added in OF1.1 .setOutPort(fm.getOutPort()) .setPriority(fm.getPriority()) .setTableId(fm.getTableId()) .setXid(fm.getXid()) .build(); } }
@Override void processOFNiciraControllerRoleRequest(OFNiciraControllerRoleRequest m) { OFControllerRole role; switch (m.getRole()) { case ROLE_MASTER: role = OFControllerRole.ROLE_MASTER; break; case ROLE_SLAVE: role = OFControllerRole.ROLE_SLAVE; break; case ROLE_OTHER: role = OFControllerRole.ROLE_EQUAL; break; default: log.error("Attempted to change to invalid Nicira role {}.", m.getRole().toString()); return; } /* * This will get converted back to the correct factory of the switch later. * We will use OFRoleRequest though to simplify the API between OF versions. */ sendRoleRequest(OFFactories.getFactory(OFVersion.OF_13).buildRoleRequest() .setGenerationId(U64.ZERO) .setXid(m.getXid()) .setRole(role) .build()); }
/** * Create a new unconnected OFChannelHandler. * @param controller * @param broker * @throws SwitchHandshakeHandlerException */ OFSwitchHandshakeHandler(@Nonnull IOFConnectionBackend connection, @Nonnull OFFeaturesReply featuresReply, @Nonnull IOFSwitchManager switchManager, @Nonnull RoleManager roleManager, @Nonnull Timer timer) { Preconditions.checkNotNull(connection, "connection"); Preconditions.checkNotNull(featuresReply, "featuresReply"); Preconditions.checkNotNull(switchManager, "switchManager"); Preconditions.checkNotNull(roleManager, "roleManager"); Preconditions.checkNotNull(timer, "timer"); Preconditions.checkArgument(connection.getAuxId().equals(OFAuxId.MAIN), "connection must be MAIN connection but is %s", connection); this.switchManager = switchManager; this.roleManager = roleManager; this.mainConnection = connection; this.auxConnections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>(); this.featuresReply = featuresReply; this.timer = timer; this.switchManagerCounters = switchManager.getCounters(); this.factory = OFFactories.getFactory(featuresReply.getVersion()); this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_NS); setState(new InitState()); this.pendingPortStatusMsg = new ArrayList<OFPortStatus>(); connection.setListener(this); }
@Before public void setUp() throws Exception { super.setUp(); mockFloodlightProvider = getMockFloodlightProvider(); hub = new Hub(); mockFloodlightProvider.addOFMessageListener(OFType.PACKET_IN, hub); hub.setFloodlightProvider(mockFloodlightProvider); // Build our test packet this.testPacket = new Ethernet() .setDestinationMACAddress("00:11:22:33:44:55") .setSourceMACAddress("00:44:33:22:11:00") .setEtherType(EthType.IPv4) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress("192.168.1.1") .setDestinationAddress("192.168.1.2") .setPayload(new UDP() .setSourcePort((short) 5000) .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); this.testPacketSerialized = testPacket.serialize(); // Build the PacketIn this.packetIn = (OFPacketIn) OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() .setBufferId(OFBufferId.NO_BUFFER) .setMatch(OFFactories.getFactory(OFVersion.OF_13).buildMatch() .setExact(MatchField.IN_PORT, OFPort.of(1)) .build()) .setData(this.testPacketSerialized) .setReason(OFPacketInReason.NO_MATCH) .setTotalLen((short) this.testPacketSerialized.length).build(); }
@Test public void testFloodNoBufferId() throws Exception { // Mock up our expected behavior IOFSwitch mockSwitch = createMock(IOFSwitch.class); EasyMock.expect(mockSwitch.getOFFactory()).andReturn(OFFactories.getFactory(OFVersion.OF_13)).anyTimes(); // build our expected flooded packetOut OFActionOutput ao = OFFactories.getFactory(OFVersion.OF_13).actions().buildOutput().setPort(OFPort.FLOOD).build(); List<OFAction> al = new ArrayList<OFAction>(); al.add(ao); OFPacketOut po = OFFactories.getFactory(OFVersion.OF_13).buildPacketOut() .setActions(al) .setBufferId(OFBufferId.NO_BUFFER) .setXid(1) .setInPort(OFPort.of(1)) .setData(this.testPacketSerialized).build(); Capture<OFMessage> wc1 = new Capture<OFMessage>(CaptureType.ALL); expect(mockSwitch.write(capture(wc1))).andReturn(true).anyTimes(); // Start recording the replay on the mocks replay(mockSwitch); // Get the listener and trigger the packet in IOFMessageListener listener = mockFloodlightProvider.getListeners().get( OFType.PACKET_IN).get(0); listener.receive(mockSwitch, this.packetIn, parseAndAnnotate(this.packetIn)); // Verify the replay matched our expectations verify(mockSwitch); assertTrue(wc1.hasCaptured()); OFMessage m = wc1.getValue(); assertTrue(OFMessageUtils.equalsIgnoreXid(m, po)); }
@Test public void testFloodBufferId() throws Exception { MockFloodlightProvider mockFloodlightProvider = getMockFloodlightProvider(); this.packetIn = this.packetIn.createBuilder() .setBufferId(OFBufferId.of(10)) .setXid(1) .build(); OFActionOutput ao = OFFactories.getFactory(OFVersion.OF_13).actions().buildOutput().setPort(OFPort.FLOOD).build(); List<OFAction> al = new ArrayList<OFAction>(); al.add(ao); // build our expected flooded packetOut OFPacketOut po = OFFactories.getFactory(OFVersion.OF_13).buildPacketOut() .setActions(al) .setXid(1) .setBufferId(OFBufferId.of(10)) .setInPort(OFPort.of(1)) .build(); // Mock up our expected behavior IOFSwitch mockSwitch = createMock(IOFSwitch.class); EasyMock.expect(mockSwitch.getOFFactory()).andReturn(OFFactories.getFactory(OFVersion.OF_13)).anyTimes(); Capture<OFPacketOut> wc1 = new Capture<OFPacketOut>(CaptureType.ALL); expect(mockSwitch.write(capture(wc1))).andReturn(true).anyTimes(); // Start recording the replay on the mocks replay(mockSwitch); // Get the listener and trigger the packet in IOFMessageListener listener = mockFloodlightProvider.getListeners().get( OFType.PACKET_IN).get(0); listener.receive(mockSwitch, this.packetIn, parseAndAnnotate(this.packetIn)); // Verify the replay matched our expectations verify(mockSwitch); assertTrue(wc1.hasCaptured()); OFMessage m = wc1.getValue(); assertEquals(po, m); }