/** * Generates a DHCP request OFPacketIn. * @param hostMac The host MAC address of for the request. * @return An OFPacketIn that contains a DHCP request packet. */ public static OFPacketIn DhcpDiscoveryRequestOFPacketIn(IOFSwitch sw, MacAddress hostMac) { byte[] serializedPacket = DhcpDiscoveryRequestEthernet(hostMac).serialize(); OFFactory factory = sw.getOFFactory(); OFPacketIn.Builder packetInBuilder = factory.buildPacketIn(); if (factory.getVersion() == OFVersion.OF_10) { packetInBuilder .setInPort(OFPort.of(1)) .setData(serializedPacket) .setReason(OFPacketInReason.NO_MATCH); } else { packetInBuilder .setMatch(factory.buildMatch().setExact(MatchField.IN_PORT, OFPort.of(1)).build()) .setData(serializedPacket) .setReason(OFPacketInReason.NO_MATCH); } return packetInBuilder.build(); }
/** * 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; }
/** * Writes an OFPacketOut message to a switch. * @param sw The switch to write the PacketOut to. * @param packetInMessage The corresponding PacketIn. * @param egressPort The switchport to output the PacketOut. */ private void writePacketOutForPacketIn(IOFSwitch sw, OFPacketIn packetInMessage, OFPort egressPort) { OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); // Set buffer_id, in_port, actions_len pob.setBufferId(packetInMessage.getBufferId()); pob.setInPort(packetInMessage.getVersion().compareTo(OFVersion.OF_12) < 0 ? packetInMessage.getInPort() : packetInMessage.getMatch().get(MatchField.IN_PORT)); // set actions List<OFAction> actions = new ArrayList<OFAction>(1); actions.add(sw.getOFFactory().actions().buildOutput().setPort(egressPort).setMaxLen(0xffFFffFF).build()); pob.setActions(actions); // set data - only if buffer_id == -1 if (packetInMessage.getBufferId() == OFBufferId.NO_BUFFER) { byte[] packetData = packetInMessage.getData(); pob.setData(packetData); } // and write it out counterPacketOut.increment(); sw.write(pob.build()); }
/** * Find the max version supplied in the supported * versions list and use it as the default, which * will subsequently be used in our hello message * header's version field. * * The factory can be later "downgraded" to a lower * version depending on what's computed during the * version-negotiation part of the handshake. * * Assumption: The Set of OFVersion ofVersions * variable has been set already and is NOT EMPTY. * * @return the highest-version OFFactory we support */ private OFFactory computeInitialFactory(Set<OFVersion> ofVersions) { /* This should NEVER happen. Double-checking. */ if (ofVersions == null || ofVersions.isEmpty()) { throw new IllegalStateException("OpenFlow version list should never be null or empty at this point. Make sure it's set in the OFSwitchManager."); } OFVersion highest = null; for (OFVersion v : ofVersions) { if (highest == null) { highest = v; } else if (v.compareTo(highest) > 0) { highest = v; } } /* * This assumes highest != null, which * it won't be if the list of versions * is not empty. */ return OFFactories.getFactory(highest); }
/** * 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); } }
/** * 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_short(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; }
@Override public void setFeaturesReply(OFFeaturesReply featuresReply) { if (portManager.getPorts().isEmpty() && featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) { /* ports are updated via port status message, so we * only fill in ports on initial connection. */ List<OFPortDesc> OFPortDescs = featuresReply.getPorts(); portManager.updatePorts(OFPortDescs); } this.capabilities = featuresReply.getCapabilities(); this.buffers = featuresReply.getNBuffers(); if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0 ) { // FIXME:LOJI: OF1.3 has per table actions. This needs to be modeled / handled here this.actions = featuresReply.getActions(); } this.tables = featuresReply.getNTables(); }
public static void serializeFeaturesReply(OFFeaturesReply fr, JsonGenerator jGen) throws IOException, JsonProcessingException { /* Common to All OF Versions */ jGen.writeStringField("capabilities", fr.getCapabilities().toString()); jGen.writeStringField("dpid", fr.getDatapathId().toString()); jGen.writeNumberField("buffers", fr.getNBuffers()); jGen.writeNumberField("tables", fr.getNTables()); jGen.writeStringField("version", fr.getVersion().toString()); if (fr.getVersion().compareTo(OFVersion.OF_13) < 0) { // OF1.3+ break this out into port_config serializePortDesc(fr.getPorts(), jGen); } if (fr.getVersion().compareTo(OFVersion.OF_10) == 0) { String actions = "["; for (OFActionType action : fr.getActions()) { actions = actions + action.toString() + ", "; } actions = actions.substring(0, actions.length() - 2); // remove ending space+comma actions = actions + "]"; jGen.writeStringField("actions", actions); } }
/** * 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; }
@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()); }
/** * 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 OFMessage createHubPacketOut(IOFSwitch sw, OFMessage msg) { OFPacketIn pi = (OFPacketIn) msg; OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); pob.setBufferId(pi.getBufferId()).setXid(pi.getXid()).setInPort((pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT))); // set actions OFActionOutput.Builder actionBuilder = sw.getOFFactory().actions().buildOutput(); actionBuilder.setPort(OFPort.FLOOD); pob.setActions(Collections.singletonList((OFAction) actionBuilder.build())); // set data if it is included in the packetin if (pi.getBufferId() == OFBufferId.NO_BUFFER) { byte[] packetData = pi.getData(); pob.setData(packetData); } return pob.build(); }
/** * 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_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; }
/** * Return a string describing this switch based on the already available * information (DPID and/or remote socket) * @return */ private String getConnectionInfoString() { String channelString; if (channel == null || channel.getRemoteAddress() == null) { channelString = "?"; } else { channelString = channel.getRemoteAddress().toString(); if(channelString.startsWith("/")) channelString = channelString.substring(1); } String dpidString; if (featuresReply == null) { dpidString = "?"; } else { StringBuilder b = new StringBuilder(); b.append(featuresReply.getDatapathId()); if(featuresReply.getVersion().compareTo(OFVersion.OF_13) >= 0) { b.append("(").append(featuresReply.getAuxiliaryId()).append(")"); } dpidString = b.toString(); } return String.format("[%s from %s]", dpidString, channelString ); }
/** * 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; }
/** * If the packet-in switch port is disabled for all data traffic, then * the packet will be dropped. Otherwise, the packet will follow the * normal processing chain. * @param sw * @param pi * @param cntx * @return */ protected Command dropFilter(DatapathId sw, OFPacketIn pi, FloodlightContext cntx) { Command result = Command.CONTINUE; OFPort inPort = (pi.getVersion().compareTo(OFVersion.OF_12) < 0 ? pi.getInPort() : pi.getMatch().get(MatchField.IN_PORT)); // If the input port is not allowed for data traffic, drop everything. // BDDP packets will not reach this stage. if (isAllowed(sw, inPort) == false) { if (log.isTraceEnabled()) { log.trace("Ignoring packet because of topology " + "restriction on switch={}, port={}", sw.getLong(), inPort.getPortNumber()); result = Command.STOP; } } return result; }
/** * Determine the highest supported version of OpenFlow in common * between both our OFVersion bitmap and the switch's. * * @param theirs, the version bitmaps of the switch * @return the highest OFVersion in common b/t the two */ private OFVersion computeOFVersionFromBitmap(List<U32> theirs) { Iterator<U32> theirsItr = theirs.iterator(); Iterator<U32> oursItr = ofBitmaps.iterator(); OFVersion version = null; int pos = 0; int size = 32; while (theirsItr.hasNext() && oursItr.hasNext()) { int t = theirsItr.next().getRaw(); int o = oursItr.next().getRaw(); int common = t & o; /* Narrow down the results to the common bits */ for (int i = 0; i < size; i++) { /* Iterate over and locate the 1's */ int tmp = common & (1 << i); /* Select the bit of interest, 0-31 */ if (tmp != 0) { /* Is the version of this bit in common? */ for (OFVersion v : OFVersion.values()) { /* Which version does this bit represent? */ if (v.getWireVersion() == i + (size * pos)) { version = v; } } } } pos++; /* OFVersion position. 1-31 = 1, 32 - 63 = 2, etc. Inc at end so it starts at 0. */ } return version; }
/** * Return a string describing this switch based on the already available * information (DPID and/or remote socket) * @return */ private String getConnectionInfoString() { String channelString; if (channel == null || channel.remoteAddress() == null) { channelString = "?"; } else { channelString = channel.remoteAddress().toString(); if(channelString.startsWith("/")) channelString = channelString.substring(1); } String dpidString; if (featuresReply == null) { dpidString = "?"; } else { StringBuilder b = new StringBuilder(); b.append(featuresReply.getDatapathId()); if(featuresReply.getVersion().compareTo(OFVersion.OF_13) >= 0) { b.append("(").append(featuresReply.getAuxiliaryId()).append(")"); } dpidString = b.toString(); } return String.format("[%s from %s]", dpidString, channelString ); }
/** * Updates testUDPPacketIn and testUDPPacketSrld from testUDPPacket * To be called after testUDPPacket has been mangled. */ private void updateUDPPacketIn() { this.testUDPPacketSrld = this.testUDPPacket.serialize(); // Build the PacketIn this.testUDPPacketIn = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() .setBufferId(OFBufferId.NO_BUFFER) .setMatch(OFFactories.getFactory(OFVersion.OF_13).buildMatch().setExact(MatchField.IN_PORT, OFPort.of(3)).build()) .setData(this.testUDPPacketSrld) .setReason(OFPacketInReason.NO_MATCH) .build(); }
@Override public void startDriverHandshake() { if (factory().getVersion() == OFVersion.OF_10) { OFFlowAdd.Builder fmBuilder = factory().buildFlowAdd(); fmBuilder.setPriority(LOWEST_PRIORITY); sendHandshakeMessage(fmBuilder.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); mockSwitch.write(capture(wc1)); // 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)); }
@Override public Boolean supportNxRole() { if (this.factory().getVersion() == OFVersion.OF_10) { return true; } return false; }
@Override public Optional<Long> cookie() { checkPermission(PACKET_READ); if (pktin.getVersion() != OFVersion.OF_10) { return Optional.of(pktin.getCookie().getValue()); } else { return Optional.empty(); } }
@Before public void setUp() throws Exception { // Build our test packet IDebugCounterService debugCounter = new DebugCounterServiceImpl(); switchManager = createMock(IOFSwitchManager.class); SwitchManagerCounters counters = new SwitchManagerCounters(debugCounter); expect(switchManager.getCounters()).andReturn(counters).anyTimes(); replay(switchManager); factory = OFFactories.getFactory(OFVersion.OF_13); testMessage = factory.buildRoleReply() .setXid(1) .setRole(OFControllerRole.ROLE_MASTER) .build(); IOFConnectionBackend conn = EasyMock.createNiceMock(IOFConnectionBackend.class); capturedMessage = new Capture<OFMessage>(); conn.write(EasyMock.capture(capturedMessage)); expectLastCall().anyTimes(); expect(conn.getOFFactory()).andReturn(factory).anyTimes(); expect(conn.getAuxId()).andReturn(OFAuxId.MAIN).anyTimes(); EasyMock.replay(conn); IOFConnectionBackend auxConn = EasyMock.createNiceMock(IOFConnectionBackend.class); expect(auxConn.getOFFactory()).andReturn(factory).anyTimes(); expect(auxConn.getAuxId()).andReturn(OFAuxId.of(1)).anyTimes(); EasyMock.replay(auxConn); sw = new OFSwitchTest(conn, switchManager); sw.registerConnection(auxConn); sw.setControllerRole(OFControllerRole.ROLE_MASTER); /* must supply role now, otherwise write() will be blocked if not master/equal/other */ switches = new ConcurrentHashMap<DatapathId, IOFSwitchBackend>(); switches.put(sw.getId(), sw); reset(switchManager); //expect(switchManager.getSwitch(sw.getId())).andReturn(sw).anyTimes(); }
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; }
@Override void processOFHello(OFChannelHandler h, OFHello m) throws IOException { // TODO We could check for the optional bitmap, but for now // we are just checking the version number. if (m.getVersion().getWireVersion() >= OFVersion.OF_13.getWireVersion()) { log.debug("Received {} Hello from {} - switching to OF " + "version 1.3", m.getVersion(), h.channel.getRemoteAddress()); h.sendHandshakeHelloMessage(); h.ofVersion = OFVersion.OF_13; } else if (m.getVersion().getWireVersion() >= OFVersion.OF_10.getWireVersion()) { log.debug("Received {} Hello from {} - switching to OF " + "version 1.0", m.getVersion(), h.channel.getRemoteAddress()); OFHello hi = h.factory10.buildHello() .setXid(h.handshakeTransactionIds--) .build(); h.channel.write(Collections.singletonList(hi)); h.ofVersion = OFVersion.OF_10; } else { log.error("Received Hello of version {} from switch at {}. " + "This controller works with OF1.0 and OF1.3 " + "switches. Disconnecting switch ...", m.getVersion(), h.channel.getRemoteAddress()); h.channel.disconnect(); return; } h.sendHandshakeFeaturesRequestMessage(); h.setState(WAIT_FEATURES_REPLY); }
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(); } }
/** * Send featuresRequest msg to the switch using the handshake transactions ids. * @throws IOException */ private void sendHandshakeFeaturesRequestMessage() throws IOException { OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10; OFMessage m = factory.buildFeaturesRequest() .setXid(this.handshakeTransactionIds--) .build(); channel.write(Collections.singletonList(m)); }
/** * Send the configuration requests to tell the switch we want full * packets. * @throws IOException */ private void sendHandshakeSetConfig() throws IOException { OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10; //log.debug("Sending CONFIG_REQUEST to {}", channel.getRemoteAddress()); List<OFMessage> msglist = new ArrayList<OFMessage>(3); // Ensure we receive the full packet via PacketIn // FIXME: We don't set the reassembly flags. // Only send config to switches to send full packets, if they have a buffer. // Saves a packet & OFSetConfig can't be handled by certain switches. if(this.featuresReply.getNBuffers() > 0) { OFSetConfig sc = factory .buildSetConfig() .setMissSendLen((short) 0xffff) .setXid(this.handshakeTransactionIds--) .build(); msglist.add(sc); } // Barrier OFBarrierRequest br = factory .buildBarrierRequest() .setXid(this.handshakeTransactionIds--) .build(); msglist.add(br); // Verify (need barrier?) OFGetConfigRequest gcr = factory .buildGetConfigRequest() .setXid(this.handshakeTransactionIds--) .build(); msglist.add(gcr); channel.write(msglist); }
private Collection<PortStatistics> buildPortStatistics(DeviceId deviceId, List<OFPortStatsEntry> entries) { HashSet<PortStatistics> stats = Sets.newHashSet(); for (OFPortStatsEntry entry : entries) { try { if (entry == null || entry.getPortNo() == null || entry.getPortNo().getPortNumber() < 0) { continue; } DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder(); DefaultPortStatistics stat = builder.setDeviceId(deviceId) .setPort(entry.getPortNo().getPortNumber()) .setPacketsReceived(entry.getRxPackets().getValue()) .setPacketsSent(entry.getTxPackets().getValue()) .setBytesReceived(entry.getRxBytes().getValue()) .setBytesSent(entry.getTxBytes().getValue()) .setPacketsRxDropped(entry.getRxDropped().getValue()) .setPacketsTxDropped(entry.getTxDropped().getValue()) .setPacketsRxErrors(entry.getRxErrors().getValue()) .setPacketsTxErrors(entry.getTxErrors().getValue()) .setDurationSec(entry.getVersion() == OFVersion.OF_10 ? 0 : entry.getDurationSec()) .setDurationNano(entry.getVersion() == OFVersion.OF_10 ? 0 : entry.getDurationNsec()) .build(); stats.add(stat); } catch (Exception e) { LOG.warn("Unable to process port stats", e); } } return Collections.unmodifiableSet(stats); }
/** * Build a portDescription from a given a port description describing some * Optical port. * * @param port description property type. * @param port the port to build from. * @return portDescription for the port. */ private PortDescription buildPortDescription(PortDescPropertyType ptype, OFPortOptical port) { checkArgument(port.getDesc().size() >= 1); // Minimally functional fixture. This needs to be fixed as we add better support. PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber()); boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) && !port.getConfig().contains(OFPortConfig.PORT_DOWN); SparseAnnotations annotations = makePortAnnotation(port.getName(), port.getHwAddr().toString()); if (port.getVersion() == OFVersion.OF_13 && ptype == PortDescPropertyType.OPTICAL_TRANSPORT) { // At this point, not much is carried in the optical port message. LOG.debug("Optical transport port message {}", port.toString()); } else { // removable once 1.4+ support complete. LOG.debug("Unsupported optical port properties"); } OFPortDescPropOpticalTransport desc = port.getDesc().get(0); switch (desc.getPortSignalType()) { // FIXME: use constants once loxi has full optical extensions case 2: // OMS port // Assume complete optical spectrum and 50 GHz grid // LINC-OE is only supported optical OF device for now return omsPortDescription(portNo, enabled, Spectrum.U_BAND_MIN, Spectrum.O_BAND_MAX, Frequency.ofGHz(50), annotations); case 5: // OCH port OchSignal signal = new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, 0, 4); return ochPortDescription(portNo, enabled, OduSignalType.ODU4, true, signal, annotations); default: break; } return new DefaultPortDescription(portNo, enabled, FIBER, 0, annotations); }
private boolean isGroupSupported(OpenFlowSwitch sw) { if (sw.factory().getVersion() == OFVersion.OF_10 || sw.factory().getVersion() == OFVersion.OF_11 || sw.factory().getVersion() == OFVersion.OF_12) { return false; } return true; }
@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); }
private boolean isMeterSupported(OpenFlowSwitch sw) { if (sw.factory().getVersion() == OFVersion.OF_10 || sw.factory().getVersion() == OFVersion.OF_11 || sw.factory().getVersion() == OFVersion.OF_12 || sw.softwareDescription().equals("OF-DPA 2.0")) { return false; } return true; }