@Override
 public void funnel(OFBadInstructionErrorMsgVer11 message, PrimitiveSink sink) {
   // fixed value property version = 2
   sink.putByte((byte) 0x2);
   // fixed value property type = 1
   sink.putByte((byte) 0x1);
   // FIXME: skip funnel of length
   sink.putLong(message.xid);
   // fixed value property errType = 3
   sink.putShort((short) 0x3);
   OFBadInstructionCodeSerializerVer11.putTo(message.code, sink);
   message.data.putTo(sink);
 }
    @Override
    public void write(ByteBuf bb, OFBadInstructionErrorMsgVer11 message) {
      int startIndex = bb.writerIndex();
      // fixed value property version = 2
      bb.writeByte((byte) 0x2);
      // fixed value property type = 1
      bb.writeByte((byte) 0x1);
      // length is length of variable message, will be updated at the end
      int lengthIndex = bb.writerIndex();
      bb.writeShort(U16.t(0));

      bb.writeInt(U32.t(message.xid));
      // fixed value property errType = 3
      bb.writeShort((short) 0x3);
      OFBadInstructionCodeSerializerVer11.writeTo(bb, message.code);
      message.data.writeTo(bb);

      // update length field
      int length = bb.writerIndex() - startIndex;
      bb.setShort(lengthIndex, length);
    }
    @Override
    public OFBadInstructionErrorMsg readFrom(ByteBuf bb) throws OFParseError {
      int start = bb.readerIndex();
      // fixed value property version == 2
      byte version = bb.readByte();
      if (version != (byte) 0x2)
        throw new OFParseError("Wrong version: Expected=OFVersion.OF_11(2), got=" + version);
      // fixed value property type == 1
      byte type = bb.readByte();
      if (type != (byte) 0x1)
        throw new OFParseError("Wrong type: Expected=OFType.ERROR(1), 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 errType == 3
      short errType = bb.readShort();
      if (errType != (short) 0x3)
        throw new OFParseError(
            "Wrong errType: Expected=OFErrorType.BAD_INSTRUCTION(3), got=" + errType);
      OFBadInstructionCode code = OFBadInstructionCodeSerializerVer11.readFrom(bb);
      OFErrorCauseData data =
          OFErrorCauseData.read(bb, length - (bb.readerIndex() - start), OFVersion.OF_11);

      OFBadInstructionErrorMsgVer11 badInstructionErrorMsgVer11 =
          new OFBadInstructionErrorMsgVer11(xid, code, data);
      if (logger.isTraceEnabled()) logger.trace("readFrom - read={}", badInstructionErrorMsgVer11);
      return badInstructionErrorMsgVer11;
    }