@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 OFOxmBsnInnerEthDst readFrom(ByteBuf bb) throws OFParseError {
      // fixed value property typeLen == 0x32c06L
      int typeLen = bb.readInt();
      if (typeLen != 0x32c06)
        throw new OFParseError("Wrong typeLen: Expected=0x32c06L(0x32c06L), got=" + typeLen);
      MacAddress value = MacAddress.read6Bytes(bb);

      OFOxmBsnInnerEthDstVer14 oxmBsnInnerEthDstVer14 = new OFOxmBsnInnerEthDstVer14(value);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", oxmBsnInnerEthDstVer14);
      return oxmBsnInnerEthDstVer14;
    }
    @Override
    public OFOxmArpTha readFrom(ChannelBuffer bb) throws OFParseError {
      // fixed value property typeLen == 0x80003206L
      int typeLen = bb.readInt();
      if (typeLen != (int) 0x80003206)
        throw new OFParseError("Wrong typeLen: Expected=0x80003206L(0x80003206L), got=" + typeLen);
      MacAddress value = MacAddress.read6Bytes(bb);

      OFOxmArpThaVer13 oxmArpThaVer13 = new OFOxmArpThaVer13(value);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", oxmArpThaVer13);
      return oxmArpThaVer13;
    }
    @Override
    public OFOxmEthSrc readFrom(ByteBuf bb) throws OFParseError {
      // fixed value property typeLen == 0x80000806L
      int typeLen = bb.readInt();
      if (typeLen != (int) 0x80000806)
        throw new OFParseError("Wrong typeLen: Expected=0x80000806L(0x80000806L), got=" + typeLen);
      MacAddress value = MacAddress.read6Bytes(bb);

      OFOxmEthSrcVer12 oxmEthSrcVer12 = new OFOxmEthSrcVer12(value);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", oxmEthSrcVer12);
      return oxmEthSrcVer12;
    }
    @Override
    public OFBsnTlvActorSystemMac readFrom(ChannelBuffer bb) throws OFParseError {
      int start = bb.readerIndex();
      // fixed value property type == 0x29
      short type = bb.readShort();
      if (type != (short) 0x29)
        throw new OFParseError("Wrong type: Expected=0x29(0x29), got=" + type);
      int length = U16.f(bb.readShort());
      if (length != 10) throw new OFParseError("Wrong length: Expected=10(10), 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);
      MacAddress value = MacAddress.read6Bytes(bb);

      OFBsnTlvActorSystemMacVer14 bsnTlvActorSystemMacVer14 =
          new OFBsnTlvActorSystemMacVer14(value);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", bsnTlvActorSystemMacVer14);
      return bsnTlvActorSystemMacVer14;
    }
    @Override
    public OFActionSetDlSrc readFrom(ByteBuf bb) throws OFParseError {
      int start = bb.readerIndex();
      // fixed value property type == 4
      short type = bb.readShort();
      if (type != (short) 0x4)
        throw new OFParseError("Wrong type: Expected=OFActionType.SET_DL_SRC(4), got=" + type);
      int length = U16.f(bb.readShort());
      if (length != 16) throw new OFParseError("Wrong length: Expected=16(16), 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);
      MacAddress dlAddr = MacAddress.read6Bytes(bb);
      // pad: 6 bytes
      bb.skipBytes(6);

      OFActionSetDlSrcVer10 actionSetDlSrcVer10 = new OFActionSetDlSrcVer10(dlAddr);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", actionSetDlSrcVer10);
      return actionSetDlSrcVer10;
    }