@Override
    public OFPortDesc readFrom(ByteBuf bb) throws OFParseError {
      OFPort portNo = OFPort.read4Bytes(bb);
      // pad: 4 bytes
      bb.skipBytes(4);
      MacAddress hwAddr = MacAddress.read6Bytes(bb);
      // pad: 2 bytes
      bb.skipBytes(2);
      String name = ChannelUtils.readFixedLengthString(bb, 16);
      Set<OFPortConfig> config = OFPortConfigSerializerVer12.readFrom(bb);
      Set<OFPortState> state = OFPortStateSerializerVer12.readFrom(bb);
      Set<OFPortFeatures> curr = OFPortFeaturesSerializerVer12.readFrom(bb);
      Set<OFPortFeatures> advertised = OFPortFeaturesSerializerVer12.readFrom(bb);
      Set<OFPortFeatures> supported = OFPortFeaturesSerializerVer12.readFrom(bb);
      Set<OFPortFeatures> peer = OFPortFeaturesSerializerVer12.readFrom(bb);
      long currSpeed = U32.f(bb.readInt());
      long maxSpeed = U32.f(bb.readInt());

      OFPortDescVer12 portDescVer12 =
          new OFPortDescVer12(
              portNo,
              hwAddr,
              name,
              config,
              state,
              curr,
              advertised,
              supported,
              peer,
              currSpeed,
              maxSpeed);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", portDescVer12);
      return portDescVer12;
    }
    @Override
    public OFOxmInPhyPort readFrom(ByteBuf bb) throws OFParseError {
      // fixed value property typeLen == 0x80000204L
      int typeLen = bb.readInt();
      if (typeLen != (int) 0x80000204)
        throw new OFParseError("Wrong typeLen: Expected=0x80000204L(0x80000204L), got=" + typeLen);
      OFPort value = OFPort.read4Bytes(bb);

      OFOxmInPhyPortVer13 oxmInPhyPortVer13 = new OFOxmInPhyPortVer13(value);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", oxmInPhyPortVer13);
      return oxmInPhyPortVer13;
    }
    @Override
    public OFBsnSetLacpReply readFrom(ChannelBuffer bb) throws OFParseError {
      int start = bb.readerIndex();
      // fixed value property version == 5
      byte version = bb.readByte();
      if (version != (byte) 0x5)
        throw new OFParseError("Wrong version: Expected=OFVersion.OF_14(5), got=" + version);
      // fixed value property type == 4
      byte type = bb.readByte();
      if (type != (byte) 0x4)
        throw new OFParseError("Wrong type: Expected=OFType.EXPERIMENTER(4), got=" + type);
      int length = U16.f(bb.readShort());
      if (length != 24) throw new OFParseError("Wrong length: Expected=24(24), got=" + length);
      if (bb.readableBytes() + (bb.readerIndex() - start) < length) {
        // Buffer does not have all data yet
        bb.readerIndex(start);
        return null;
      }
      if (logger.isTraceEnabled()) logger.trace("readFrom - length={}", length);
      long xid = U32.f(bb.readInt());
      // fixed value property experimenter == 0x5c16c7L
      int experimenter = bb.readInt();
      if (experimenter != 0x5c16c7)
        throw new OFParseError(
            "Wrong experimenter: Expected=0x5c16c7L(0x5c16c7L), got=" + experimenter);
      // fixed value property subtype == 0x2aL
      int subtype = bb.readInt();
      if (subtype != 0x2a)
        throw new OFParseError("Wrong subtype: Expected=0x2aL(0x2aL), got=" + subtype);
      long status = U32.f(bb.readInt());
      OFPort portNo = OFPort.read4Bytes(bb);

      OFBsnSetLacpReplyVer14 bsnSetLacpReplyVer14 = new OFBsnSetLacpReplyVer14(xid, status, portNo);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", bsnSetLacpReplyVer14);
      return bsnSetLacpReplyVer14;
    }
    @Override
    public OFPortStatsRequest readFrom(ByteBuf bb) throws OFParseError {
      int start = bb.readerIndex();
      // fixed value property version == 4
      byte version = bb.readByte();
      if (version != (byte) 0x4)
        throw new OFParseError("Wrong version: Expected=OFVersion.OF_13(4), got=" + version);
      // fixed value property type == 18
      byte type = bb.readByte();
      if (type != (byte) 0x12)
        throw new OFParseError("Wrong type: Expected=OFType.STATS_REQUEST(18), got=" + type);
      int length = U16.f(bb.readShort());
      if (length != 24) throw new OFParseError("Wrong length: Expected=24(24), got=" + length);
      if (bb.readableBytes() + (bb.readerIndex() - start) < length) {
        // Buffer does not have all data yet
        bb.readerIndex(start);
        return null;
      }
      if (logger.isTraceEnabled()) logger.trace("readFrom - length={}", length);
      long xid = U32.f(bb.readInt());
      // fixed value property statsType == 4
      short statsType = bb.readShort();
      if (statsType != (short) 0x4)
        throw new OFParseError("Wrong statsType: Expected=OFStatsType.PORT(4), got=" + statsType);
      Set<OFStatsRequestFlags> flags = OFStatsRequestFlagsSerializerVer13.readFrom(bb);
      // pad: 4 bytes
      bb.skipBytes(4);
      OFPort portNo = OFPort.read4Bytes(bb);
      // pad: 4 bytes
      bb.skipBytes(4);

      OFPortStatsRequestVer13 portStatsRequestVer13 =
          new OFPortStatsRequestVer13(xid, flags, portNo);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", portStatsRequestVer13);
      return portStatsRequestVer13;
    }