/** * Send hello message to the switch using the handshake transactions ids. * @throws IOException */ private void sendHandshakeHelloMessage() throws IOException { // The OF protocol requires us to start things off by sending the highest // version of the protocol supported. // bitmap represents OF1.0 (ofp_version=0x01) and OF1.3 (ofp_version=0x04) // see Sec. 7.5.1 of the OF1.3.4 spec U32 bitmap = U32.ofRaw(0x00000012); OFHelloElem hem = factory13.buildHelloElemVersionbitmap() .setBitmaps(Collections.singletonList(bitmap)) .build(); OFMessage.Builder mb = factory13.buildHello() .setXid(this.handshakeTransactionIds--) .setElements(Collections.singletonList(hem)); log.info("Sending OF_13 Hello to {}", channel.getRemoteAddress()); channel.write(Collections.singletonList(mb.build())); }
public OFChannelInitializer(IOFSwitchManager switchManager, INewOFConnectionListener connectionListener, IDebugCounterService debugCounters, Timer timer, List<U32> ofBitmaps, OFFactory defaultFactory, String keyStore, String keyStorePassword) { super(); this.switchManager = switchManager; this.connectionListener = connectionListener; this.timer = timer; this.debugCounters = debugCounters; this.defaultFactory = defaultFactory; this.ofBitmaps = ofBitmaps; this.keyStore = keyStore; this.keyStorePassword = keyStorePassword; }
/** * Creates a handler for interacting with the switch channel * * @param controller * the controller * @param newConnectionListener * the class that listens for new OF connections (switchManager) * @param pipeline * the channel pipeline * @param threadPool * the thread pool * @param idleTimer * the hash wheeled timer used to send idle messages (echo). * passed to constructor to modify in case of aux connection. * @param debugCounters */ OFChannelHandler(@Nonnull IOFSwitchManager switchManager, @Nonnull INewOFConnectionListener newConnectionListener, @Nonnull ChannelPipeline pipeline, @Nonnull IDebugCounterService debugCounters, @Nonnull Timer timer, @Nonnull List<U32> ofBitmaps, @Nonnull OFFactory defaultFactory) { Preconditions.checkNotNull(switchManager, "switchManager"); Preconditions.checkNotNull(newConnectionListener, "connectionOpenedListener"); Preconditions.checkNotNull(pipeline, "pipeline"); Preconditions.checkNotNull(timer, "timer"); Preconditions.checkNotNull(debugCounters, "debugCounters"); this.pipeline = pipeline; this.debugCounters = debugCounters; this.newConnectionListener = newConnectionListener; this.counters = switchManager.getCounters(); this.state = new InitState(); this.timer = timer; this.ofBitmaps = ofBitmaps; this.factory = defaultFactory; log.debug("constructor on OFChannelHandler {}", String.format("%08x", System.identityHashCode(this))); }
/** * 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; }
protected OFTableFeaturesStatsReply createTableFeaturesStatsReply() { OFTableFeaturesStatsReply statsReply = factory.buildTableFeaturesStatsReply() .setEntries(Collections.singletonList(factory.buildTableFeatures() .setConfig(0) .setMaxEntries(100) .setMetadataMatch(U64.NO_MASK) .setMetadataWrite(U64.NO_MASK) .setName("MyTable") .setTableId(TableId.of(1)) .setProperties(Collections.singletonList((OFTableFeatureProp)factory.buildTableFeaturePropMatch() .setOxmIds(Collections.singletonList(U32.of(100))) .build()) ).build() ) ).build(); return statsReply; }
@Override public OFOxm<?> mapSelector(OFFactory factory, ExtensionSelector extensionSelector) { ExtensionSelectorType type = extensionSelector.type(); if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) { NiciraMatchNshSpi niciraNshSpi = (NiciraMatchNshSpi) extensionSelector; return factory.oxms().nsp(U32.of(niciraNshSpi.nshSpi().servicePathId())); } if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) { NiciraMatchNshSi niciraNshSi = (NiciraMatchNshSi) extensionSelector; return factory.oxms().nsi(U8.of(niciraNshSi.nshSi().serviceIndex())); } if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_ENCAP_ETH_TYPE.type())) { NiciraMatchEncapEthType niciraEncapEthType = (NiciraMatchEncapEthType) extensionSelector; return factory.oxms().encapEthType(U16.of(niciraEncapEthType.encapEthType())); } if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())) { // TODO } if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type())) { // TODO } if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type())) { // TODO } if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) { // TODO } return null; }
/** * Based on the list of OFVersions provided as input (or from Loxi), * create a list of bitmaps for use in version negotiation during a * cross-version OpenFlow handshake where both parties support * OpenFlow versions >= 1.3.1. * * Type Set is used as input to guarantee all unique versions. * * @param ofVersions, the list of bitmaps. Supply to an OFHello message. * @return list of bitmaps for the versions of OpenFlow we support */ private List<U32> computeOurVersionBitmaps(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."); } int pos = 1; /* initial bitmap in list */ int size = 32; /* size of a U32 */ int tempBitmap = 0; /* maintain the current bitmap we're working on */ List<U32> bitmaps = new ArrayList<U32>(); ArrayList<OFVersion> sortedVersions = new ArrayList<OFVersion>(ofVersions); Collections.sort(sortedVersions); for (OFVersion v : sortedVersions) { /* Move on to another bitmap */ if (v.getWireVersion() > pos * size - 1 ) { bitmaps.add(U32.ofRaw(tempBitmap)); tempBitmap = 0; pos++; } tempBitmap = tempBitmap | (1 << (v.getWireVersion() % size)); } if (tempBitmap != 0) { bitmaps.add(U32.ofRaw(tempBitmap)); } log.info("Computed OpenFlow version bitmap as {}", Arrays.asList(tempBitmap)); return bitmaps; }
private OFAction buildL2Modification(Instruction i) { L2ModificationInstruction l2m = (L2ModificationInstruction) i; L2ModificationInstruction.ModEtherInstruction eth; OFOxm<?> oxm = null; switch (l2m.subtype()) { case ETH_DST: eth = (L2ModificationInstruction.ModEtherInstruction) l2m; oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong())); break; case ETH_SRC: eth = (L2ModificationInstruction.ModEtherInstruction) l2m; oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong())); break; case VLAN_ID: L2ModificationInstruction.ModVlanIdInstruction vlanId = (L2ModificationInstruction.ModVlanIdInstruction) l2m; oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort())); break; case VLAN_PCP: L2ModificationInstruction.ModVlanPcpInstruction vlanPcp = (L2ModificationInstruction.ModVlanPcpInstruction) l2m; oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp())); break; case VLAN_POP: return factory.actions().popVlan(); case VLAN_PUSH: L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction = (L2ModificationInstruction.PushHeaderInstructions) l2m; return factory.actions().pushVlan( EthType.of(pushVlanInstruction.ethernetType().toShort())); case MPLS_PUSH: L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions = (L2ModificationInstruction.PushHeaderInstructions) l2m; return factory.actions().pushMpls(EthType.of(pushHeaderInstructions .ethernetType().toShort())); case MPLS_POP: L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions = (L2ModificationInstruction.PushHeaderInstructions) l2m; return factory.actions().popMpls(EthType.of(popHeaderInstructions .ethernetType().toShort())); case MPLS_LABEL: L2ModificationInstruction.ModMplsLabelInstruction mplsLabel = (L2ModificationInstruction.ModMplsLabelInstruction) l2m; oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label().toInt())); break; case MPLS_BOS: L2ModificationInstruction.ModMplsBosInstruction mplsBos = (L2ModificationInstruction.ModMplsBosInstruction) l2m; oxm = factory.oxms() .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE : OFBooleanValue.FALSE); break; case DEC_MPLS_TTL: return factory.actions().decMplsTtl(); case TUNNEL_ID: L2ModificationInstruction.ModTunnelIdInstruction tunnelId = (L2ModificationInstruction.ModTunnelIdInstruction) l2m; oxm = factory.oxms().tunnelId(U64.of(tunnelId.tunnelId())); break; default: log.warn("Unimplemented action type {}.", l2m.subtype()); break; } if (oxm != null) { return factory.actions().buildSetField().setField(oxm).build(); } return null; }
/** * Only bits 0-23 of index are used. Bits 24-31 are ignored. * @param index * @return */ public static OFGroup createMPLSInterfaceLabel(U32 index) { //9 return OFGroup.of(0 | (index.getRaw() & 0x00ffFFff) | (MPLSSubType.MPLS_INTERFACE << 24) | (OFDPAGroupType.MPLS_LABEL << 28)); }
/** * Only bits 0-23 of index are used. Bits 24-31 are ignored. * @param index * @return */ public static OFGroup createMPLSL2VPNLabel(U32 index) { //9 return OFGroup.of(0 | (index.getRaw() & 0x00ffFFff) | (MPLSSubType.MPLS_L2_VPN_LABEL << 24) | (OFDPAGroupType.MPLS_LABEL << 28)); }
/** * Only bits 0-23 of index are used. Bits 24-31 are ignored. * @param index * @return */ public static OFGroup createMPLSL3VPNLabel(U32 index) { //9 return OFGroup.of(0 | (index.getRaw() & 0x00ffFFff) | (MPLSSubType.MPLS_L3_VPN_LABEL << 24) | (OFDPAGroupType.MPLS_LABEL << 28)); }
/** * Only bits 0-23 of index are used. Bits 24-31 are ignored. * @param index * @return */ public static OFGroup createMPLSTunnelLable1(U32 index) { //9 return OFGroup.of(0 | (index.getRaw() & 0x00ffFFff) | (MPLSSubType.MPLS_TUNNEL_LABEL_1 << 24) | (OFDPAGroupType.MPLS_LABEL << 28)); }
/** * Only bits 0-23 of index are used. Bits 24-31 are ignored. * @param index * @return */ public static OFGroup createMPLSTunnelLabel2(U32 index) { //9 return OFGroup.of(0 | (index.getRaw() & 0x00ffFFff) | (MPLSSubType.MPLS_TUNNEL_LABEL_2 << 24) | (OFDPAGroupType.MPLS_LABEL << 28)); }
/** * Only bits 0-23 of index are used. Bits 24-31 are ignored. * @param index * @return */ public static OFGroup createMPLSSwapLabel(U32 index) { //9 return OFGroup.of(0 | (index.getRaw() & 0x00ffFFff) | (MPLSSubType.MPLS_SWAP_LABEL << 24) | (OFDPAGroupType.MPLS_LABEL << 28)); }
/** * Only bits 0-23 of index are used. Bits 24-31 are ignored. * @param index * @return */ public static OFGroup createMPLSForwardingFastFailover(U32 index) { //10 return OFGroup.of(0 | (index.getRaw() & 0x00ffFFff) | (MPLSSubType.MPLS_FAST_FAILOVER << 24) | (OFDPAGroupType.MPLS_FORWARDING << 28)); }
/** * Only bits 0-23 of index are used. Bits 24-31 are ignored. * @param index * @return */ public static OFGroup createMPLSForwardingECMP(U32 index) { //10 return OFGroup.of(0 | (index.getRaw() & 0x00ffFFff) | (MPLSSubType.MPLS_ECMP << 24) | (OFDPAGroupType.MPLS_FORWARDING << 28)); }
/** * Only bits 0-23 of index are used. Bits 24-31 are ignored. * @param index * @return */ public static OFGroup createMPLSForwardingL2Tag(U32 index) { //10 return OFGroup.of(0 | (index.getRaw() & 0x00ffFFff) | (MPLSSubType.MPLS_L2_TAG << 24) | (OFDPAGroupType.MPLS_FORWARDING << 28)); }