/**
   * 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;
  }
Exemple #2
0
    @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());
    }