@Override
    public OFBsnGentableEntryAdd readFrom(ChannelBuffer 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 == 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 < MINIMUM_LENGTH)
        throw new OFParseError(
            "Wrong length: Expected to be >= " + MINIMUM_LENGTH + ", was: " + 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 == 0x2eL
      int subtype = bb.readInt();
      if (subtype != 0x2e)
        throw new OFParseError("Wrong subtype: Expected=0x2eL(0x2eL), got=" + subtype);
      GenTableId tableId = GenTableId.read2Bytes(bb);
      int keyLength = U16.f(bb.readShort());
      U128 checksum = U128.read16Bytes(bb);
      List<OFBsnTlv> key = ChannelUtils.readList(bb, keyLength, OFBsnTlvVer13.READER);
      List<OFBsnTlv> value =
          ChannelUtils.readList(bb, length - (bb.readerIndex() - start), OFBsnTlvVer13.READER);

      OFBsnGentableEntryAddVer13 bsnGentableEntryAddVer13 =
          new OFBsnGentableEntryAddVer13(xid, tableId, checksum, key, value);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", bsnGentableEntryAddVer13);
      return bsnGentableEntryAddVer13;
    }
    @Override
    public OFFlowStatsEntry readFrom(ByteBuf bb) throws OFParseError {
      int start = bb.readerIndex();
      int length = U16.f(bb.readShort());
      if (length < MINIMUM_LENGTH)
        throw new OFParseError(
            "Wrong length: Expected to be >= " + MINIMUM_LENGTH + ", was: " + 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);
      TableId tableId = TableId.readByte(bb);
      // pad: 1 bytes
      bb.skipBytes(1);
      long durationSec = U32.f(bb.readInt());
      long durationNsec = U32.f(bb.readInt());
      int priority = U16.f(bb.readShort());
      int idleTimeout = U16.f(bb.readShort());
      int hardTimeout = U16.f(bb.readShort());
      Set<OFFlowModFlags> flags = OFFlowModFlagsSerializerVer14.readFrom(bb);
      int importance = U16.f(bb.readShort());
      // pad: 2 bytes
      bb.skipBytes(2);
      U64 cookie = U64.ofRaw(bb.readLong());
      U64 packetCount = U64.ofRaw(bb.readLong());
      U64 byteCount = U64.ofRaw(bb.readLong());
      Match match = ChannelUtilsVer14.readOFMatch(bb);
      List<OFInstruction> instructions =
          ChannelUtils.readList(bb, length - (bb.readerIndex() - start), OFInstructionVer14.READER);

      OFFlowStatsEntryVer14 flowStatsEntryVer14 =
          new OFFlowStatsEntryVer14(
              tableId,
              durationSec,
              durationNsec,
              priority,
              idleTimeout,
              hardTimeout,
              flags,
              importance,
              cookie,
              packetCount,
              byteCount,
              match,
              instructions);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", flowStatsEntryVer14);
      return flowStatsEntryVer14;
    }
    @Override
    public OFBsnGentableBucketStatsReply readFrom(ChannelBuffer 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 == 19
      byte type = bb.readByte();
      if (type != (byte) 0x13)
        throw new OFParseError("Wrong type: Expected=OFType.STATS_REPLY(19), got=" + type);
      int length = U16.f(bb.readShort());
      if (length < MINIMUM_LENGTH)
        throw new OFParseError(
            "Wrong length: Expected to be >= " + MINIMUM_LENGTH + ", was: " + 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 == 65535
      short statsType = bb.readShort();
      if (statsType != (short) 0xffff)
        throw new OFParseError(
            "Wrong statsType: Expected=OFStatsType.EXPERIMENTER(65535), got=" + statsType);
      Set<OFStatsReplyFlags> flags = OFStatsReplyFlagsSerializerVer13.readFrom(bb);
      // pad: 4 bytes
      bb.skipBytes(4);
      // 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 == 0x5L
      int subtype = bb.readInt();
      if (subtype != 0x5)
        throw new OFParseError("Wrong subtype: Expected=0x5L(0x5L), got=" + subtype);
      List<OFBsnGentableBucketStatsEntry> entries =
          ChannelUtils.readList(
              bb, length - (bb.readerIndex() - start), OFBsnGentableBucketStatsEntryVer13.READER);

      OFBsnGentableBucketStatsReplyVer13 bsnGentableBucketStatsReplyVer13 =
          new OFBsnGentableBucketStatsReplyVer13(xid, flags, entries);
      if (logger.isTraceEnabled())
        logger.trace("readFrom - read={}", bsnGentableBucketStatsReplyVer13);
      return bsnGentableBucketStatsReplyVer13;
    }
    @Override
    public OFBsnVlanCounterStatsEntry readFrom(ChannelBuffer bb) throws OFParseError {
      int start = bb.readerIndex();
      int length = U16.f(bb.readShort());
      if (length < MINIMUM_LENGTH)
        throw new OFParseError(
            "Wrong length: Expected to be >= " + MINIMUM_LENGTH + ", was: " + 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);
      int vlanVid = U16.f(bb.readShort());
      // pad: 4 bytes
      bb.skipBytes(4);
      List<U64> values = ChannelUtils.readList(bb, length - (bb.readerIndex() - start), U64.READER);

      OFBsnVlanCounterStatsEntryVer13 bsnVlanCounterStatsEntryVer13 =
          new OFBsnVlanCounterStatsEntryVer13(vlanVid, values);
      if (logger.isTraceEnabled())
        logger.trace("readFrom - read={}", bsnVlanCounterStatsEntryVer13);
      return bsnVlanCounterStatsEntryVer13;
    }
    @Override
    public OFMeterStatsReply readFrom(ByteBuf 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 == 19
      byte type = bb.readByte();
      if (type != (byte) 0x13)
        throw new OFParseError("Wrong type: Expected=OFType.STATS_REPLY(19), got=" + type);
      int length = U16.f(bb.readShort());
      if (length < MINIMUM_LENGTH)
        throw new OFParseError(
            "Wrong length: Expected to be >= " + MINIMUM_LENGTH + ", was: " + 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 == 9
      short statsType = bb.readShort();
      if (statsType != (short) 0x9)
        throw new OFParseError("Wrong statsType: Expected=OFStatsType.METER(9), got=" + statsType);
      Set<OFStatsReplyFlags> flags = OFStatsReplyFlagsSerializerVer14.readFrom(bb);
      // pad: 4 bytes
      bb.skipBytes(4);
      List<OFMeterStats> entries =
          ChannelUtils.readList(bb, length - (bb.readerIndex() - start), OFMeterStatsVer14.READER);

      OFMeterStatsReplyVer14 meterStatsReplyVer14 = new OFMeterStatsReplyVer14(xid, flags, entries);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", meterStatsReplyVer14);
      return meterStatsReplyVer14;
    }