/** * 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; }
@Override void processOFHello(OFHello m) throws IOException { OFVersion version = m.getVersion(); /* Choose the lower of the two supported versions. */ if (version.compareTo(factory.getVersion()) < 0) { factory = OFFactories.getFactory(version); } /* else The controller's version is < or = the switch's, so keep original controller factory. */ OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class); decoder.setVersion(version); setState(new WaitFeaturesReplyState()); }
@Override void processOFHello(OFHello m) throws IOException { OFVersion theirVersion = m.getVersion(); OFVersion commonVersion = null; /* First, check if there's a version bitmap supplied. WE WILL ALWAYS HAVE a controller-provided version bitmap. */ if (theirVersion.compareTo(OFVersion.OF_13) >= 0 && !m.getElements().isEmpty()) { List<U32> bitmaps = new ArrayList<U32>(); List<OFHelloElem> elements = m.getElements(); /* Grab all bitmaps supplied */ for (OFHelloElem e : elements) { if (e instanceof OFHelloElemVersionbitmap) { bitmaps.addAll(((OFHelloElemVersionbitmap) e).getBitmaps()); } else { log.warn("Unhandled OFHelloElem {}", e); } } /* Lookup highest, common supported OpenFlow version */ commonVersion = computeOFVersionFromBitmap(bitmaps); if (commonVersion == null) { log.error( "Could not negotiate common OpenFlow version for {} with greatest version bitmap algorithm.", channel.remoteAddress()); channel.disconnect(); return; } else { log.info( "Negotiated OpenFlow version of {} for {} with greatest version bitmap algorithm.", commonVersion.toString(), channel.remoteAddress()); factory = OFFactories.getFactory(commonVersion); OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class); decoder.setVersion(commonVersion); } } /* If there's not a bitmap present, choose the lower of the two supported versions. */ else if (theirVersion.compareTo(factory.getVersion()) < 0) { log.info( "Negotiated down to switch OpenFlow version of {} for {} using lesser hello header algorithm.", theirVersion.toString(), channel.remoteAddress()); factory = OFFactories.getFactory(theirVersion); OFMessageDecoder decoder = pipeline.get(OFMessageDecoder.class); decoder.setVersion(theirVersion); } /* else The controller's version is < or = the switch's, so keep original controller factory. */ else if (theirVersion .equals(factory.getVersion())) { log.info( "Negotiated equal OpenFlow version of {} for {} using lesser hello header algorithm.", factory.getVersion().toString(), channel.remoteAddress()); } else { log.info( "Negotiated down to controller OpenFlow version of {} for {} using lesser hello header algorithm.", factory.getVersion().toString(), channel.remoteAddress()); } setState(new WaitFeaturesReplyState()); }