Fixed the encoding of SendMultipartRequestMessageInput 04/2804/1
authorEd Warnicke <eaw@cisco.com>
Sun, 17 Nov 2013 21:33:55 +0000 (15:33 -0600)
committerEd Warnicke <eaw@cisco.com>
Sun, 17 Nov 2013 21:33:55 +0000 (15:33 -0600)
Change-Id: Iefc7cfdefae00bd244018714d420b4f4a7587373
Signed-off-by: Ed Warnicke <eaw@cisco.com>
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/EncoderTable.java
openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/SendMultipartRequestMessageInputFactory.java [new file with mode: 0644]

index b67238e03a56e4e173237d0a3e2f4ec11ccced05..0fd8205d60d54977fb929d9726a590ff56c62ec8 100644 (file)
@@ -34,6 +34,7 @@ import org.opendaylight.openflowjava.protocol.impl.serialization.factories.OF10V
 import org.opendaylight.openflowjava.protocol.impl.serialization.factories.PacketOutInputMessageFactory;\r
 import org.opendaylight.openflowjava.protocol.impl.serialization.factories.PortModInputMessageFactory;\r
 import org.opendaylight.openflowjava.protocol.impl.serialization.factories.RoleRequestInputMessageFactory;\r
+import org.opendaylight.openflowjava.protocol.impl.serialization.factories.SendMultipartRequestMessageInputFactory;\r
 import org.opendaylight.openflowjava.protocol.impl.serialization.factories.SetAsyncInputMessageFactory;\r
 import org.opendaylight.openflowjava.protocol.impl.serialization.factories.SetConfigMessageFactory;\r
 import org.opendaylight.openflowjava.protocol.impl.serialization.factories.TableModInputMessageFactory;\r
@@ -53,6 +54,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInput;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SendMultipartRequestMessageInput;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetAsyncInput;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetConfigInput;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;\r
@@ -64,17 +66,17 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
  * @author timotej.kubas\r
  */\r
 public class EncoderTable {\r
-    \r
+\r
     private static final short OF10 = OFVersionDetector.OF10_VERSION_ID;\r
     private static final short OF13 = OFVersionDetector.OF13_VERSION_ID;\r
     private static EncoderTable instance;\r
     private Map<MessageTypeKey<?>, OFSerializer<?>> table;\r
-    \r
+\r
 \r
     private EncoderTable() {\r
         // do nothing\r
     }\r
-    \r
+\r
     /**\r
      * @return singleton instance\r
      */\r
@@ -85,7 +87,7 @@ public class EncoderTable {
         }\r
         return instance;\r
     }\r
-    \r
+\r
     /**\r
      * Encoder table provisioning\r
      */\r
@@ -117,6 +119,7 @@ public class EncoderTable {
         table.put(new MessageTypeKey<>(OF13, HelloInput.class), HelloInputMessageFactory.getInstance());\r
         table.put(new MessageTypeKey<>(OF13, MeterModInput.class), MeterModInputMessageFactory.getInstance());\r
         table.put(new MessageTypeKey<>(OF13, MultipartRequestMessage.class), MultipartRequestMessageFactory.getInstance());\r
+        table.put(new MessageTypeKey<>(OF13, SendMultipartRequestMessageInput.class), SendMultipartRequestMessageInputFactory.getInstance());\r
         table.put(new MessageTypeKey<>(OF13, PacketOutInput.class), PacketOutInputMessageFactory.getInstance());\r
         table.put(new MessageTypeKey<>(OF13, PortModInput.class), PortModInputMessageFactory.getInstance());\r
         table.put(new MessageTypeKey<>(OF13, RoleRequestInput.class), RoleRequestInputMessageFactory.getInstance());\r
@@ -124,7 +127,7 @@ public class EncoderTable {
         table.put(new MessageTypeKey<>(OF13, SetConfigInput.class), SetConfigMessageFactory.getInstance());\r
         table.put(new MessageTypeKey<>(OF13, TableModInput.class), TableModInputMessageFactory.getInstance());\r
     }\r
-    \r
+\r
     /**\r
      * @param msgTypeKey\r
      * @return encoder for current type of message (msgTypeKey)\r
diff --git a/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/SendMultipartRequestMessageInputFactory.java b/openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization/factories/SendMultipartRequestMessageInputFactory.java
new file mode 100644 (file)
index 0000000..e1b4ae8
--- /dev/null
@@ -0,0 +1,447 @@
+/* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */\r
+package org.opendaylight.openflowjava.protocol.impl.serialization.factories;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.opendaylight.openflowjava.protocol.impl.serialization.OFSerializer;\r
+import org.opendaylight.openflowjava.protocol.impl.util.ActionsSerializer;\r
+import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils;\r
+import org.opendaylight.openflowjava.protocol.impl.util.InstructionsSerializer;\r
+import org.opendaylight.openflowjava.protocol.impl.util.MatchSerializer;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.InstructionRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NextTableRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.table.features.properties.container.table.feature.properties.NextTableIds;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.Instructions;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableConfig;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesPropType;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SendMultipartRequestMessageInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestAggregate;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestDesc;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenter;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestFlow;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroup;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeter;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterConfig;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortStats;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestQueue;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeatures;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features.TableFeatures;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.TableFeatureProperties;\r
+\r
+/**\r
+ * Translates MultipartRequest messages\r
+ * @author timotej.kubas\r
+ * @author michal.polkorab\r
+ */\r
+public class SendMultipartRequestMessageInputFactory implements OFSerializer<SendMultipartRequestMessageInput> {\r
+    private static final byte MESSAGE_TYPE = 18;\r
+    private static final int MESSAGE_LENGTH = 16;\r
+    private static final byte PADDING_IN_MULTIPART_REQUEST_MESSAGE = 4;\r
+    private static final byte TABLE_FEAT_HEADER_LENGTH = 4;\r
+    private static SendMultipartRequestMessageInputFactory instance;\r
+\r
+    private SendMultipartRequestMessageInputFactory() {\r
+        // singleton\r
+    }\r
+\r
+    /**\r
+     * @return singleton factory\r
+     */\r
+    public static synchronized SendMultipartRequestMessageInputFactory getInstance() {\r
+        if (instance == null) {\r
+            instance = new SendMultipartRequestMessageInputFactory();\r
+        }\r
+        return instance;\r
+    }\r
+\r
+    @Override\r
+    public void messageToBuffer(short version, ByteBuf out,\r
+            SendMultipartRequestMessageInput message) {\r
+        ByteBufUtils.writeOFHeader(instance, message, out);\r
+        out.writeShort(message.getType().getIntValue());\r
+        out.writeShort(createMultipartRequestFlagsBitmask(message.getFlags()));\r
+        ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_MESSAGE, out);\r
+\r
+        if (message.getMultipartRequestBody() instanceof MultipartRequestDesc ){\r
+            encodeDescBody(message.getMultipartRequestBody(), out);\r
+        } else if (message.getMultipartRequestBody() instanceof MultipartRequestFlow) {\r
+            encodeFlowBody(message.getMultipartRequestBody(), out);\r
+        } else if (message.getMultipartRequestBody() instanceof MultipartRequestAggregate) {\r
+            encodeAggregateBody(message.getMultipartRequestBody(), out);\r
+        } else if (message.getMultipartRequestBody() instanceof MultipartRequestPortStats) {\r
+            encodePortStatsBody(message.getMultipartRequestBody(), out);\r
+        } else if (message.getMultipartRequestBody() instanceof MultipartRequestQueue) {\r
+            encodeQueueBody(message.getMultipartRequestBody(), out);\r
+        } else if (message.getMultipartRequestBody() instanceof MultipartRequestGroup) {\r
+            encodeGroupStatsBody(message.getMultipartRequestBody(), out);\r
+        } else if (message.getMultipartRequestBody() instanceof MultipartRequestMeter) {\r
+            encodeMeterBody(message.getMultipartRequestBody(), out);\r
+        } else if (message.getMultipartRequestBody() instanceof MultipartRequestMeterConfig) {\r
+            encodeMeterConfigBody(message.getMultipartRequestBody(), out);\r
+        } else if (message.getMultipartRequestBody() instanceof MultipartRequestTableFeatures) {\r
+            encodeTableFeaturesBody(message.getMultipartRequestBody(), out);\r
+        } else if (message.getMultipartRequestBody() instanceof MultipartRequestExperimenter) {\r
+            encodeExperimenterBody(message.getMultipartRequestBody(), out);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public int computeLength(SendMultipartRequestMessageInput message) {\r
+        return MESSAGE_LENGTH + computeBodyLength(message);\r
+    }\r
+    @Override\r
+    public byte getMessageType() {\r
+        return MESSAGE_TYPE;\r
+    }\r
+\r
+    /**\r
+     *\r
+     * @param message\r
+     * @return length of SendMultipartRequestMessageInput\r
+     */\r
+    public int computeBodyLength(SendMultipartRequestMessageInput message) {\r
+        int length = 0;\r
+        MultipartType type = message.getType();\r
+        if (type.equals(MultipartType.OFPMPFLOW)) {\r
+            final byte FLOW_BODY_LENGTH = 32;\r
+            MultipartRequestFlow body = (MultipartRequestFlow) message.getMultipartRequestBody();\r
+            length += FLOW_BODY_LENGTH + MatchSerializer.computeMatchLength(body.getMatch());\r
+        } else if (type.equals(MultipartType.OFPMPAGGREGATE)) {\r
+            final byte AGGREGATE_BODY_LENGTH = 32;\r
+            MultipartRequestAggregate body = (MultipartRequestAggregate) message.getMultipartRequestBody();\r
+            length += AGGREGATE_BODY_LENGTH + MatchSerializer.computeMatchLength(body.getMatch());\r
+        } else if (type.equals(MultipartType.OFPMPPORTSTATS)) {\r
+            final byte PORT_STATS_BODY_LENGTH = 8;\r
+            length += PORT_STATS_BODY_LENGTH;\r
+        } else if (type.equals(MultipartType.OFPMPQUEUE)) {\r
+            final byte QUEUE_BODY_LENGTH = 8;\r
+            length += QUEUE_BODY_LENGTH;\r
+        } else if (type.equals(MultipartType.OFPMPGROUP)) {\r
+            final byte GROUP_BODY_LENGTH = 8;\r
+            length += GROUP_BODY_LENGTH;\r
+        } else if (type.equals(MultipartType.OFPMPMETER)) {\r
+            final byte METER_BODY_LENGTH = 8;\r
+            length += METER_BODY_LENGTH;\r
+        } else if (type.equals(MultipartType.OFPMPMETERCONFIG)) {\r
+            final byte METER_CONFIG_BODY_LENGTH = 8;\r
+            length += METER_CONFIG_BODY_LENGTH;\r
+        } else if (type.equals(MultipartType.OFPMPTABLEFEATURES)) {\r
+            MultipartRequestTableFeatures body = (MultipartRequestTableFeatures) message.getMultipartRequestBody();\r
+            length += computeTableFeaturesLength(body);\r
+        } else if (type.equals(MultipartType.OFPMPEXPERIMENTER)) {\r
+            final byte EXPERIMENTER_BODY_LENGTH = 8;\r
+            MultipartRequestExperimenter body = (MultipartRequestExperimenter) message.getMultipartRequestBody();\r
+            length += EXPERIMENTER_BODY_LENGTH;\r
+            if (body.getData() != null) {\r
+                length += body.getData().length;\r
+            }\r
+        }\r
+        return length;\r
+    }\r
+\r
+    private static int computeTableFeaturesLength(MultipartRequestTableFeatures body) {\r
+        final byte TABLE_FEATURES_LENGTH = 64;\r
+        final byte STRUCTURE_HEADER_LENGTH = 4;\r
+        int length = 0;\r
+        if (body != null) {\r
+            List<TableFeatures> tableFeatures = body.getTableFeatures();\r
+            for (TableFeatures feature : tableFeatures) {\r
+                length += TABLE_FEATURES_LENGTH;\r
+                List<TableFeatureProperties> featureProperties = feature.getTableFeatureProperties();\r
+                if (featureProperties != null) {\r
+                    for (TableFeatureProperties featProp : featureProperties) {\r
+                        length += TABLE_FEAT_HEADER_LENGTH;\r
+                        if (featProp.getAugmentation(InstructionRelatedTableFeatureProperty.class) != null) {\r
+                            InstructionRelatedTableFeatureProperty property =\r
+                                    featProp.getAugmentation(InstructionRelatedTableFeatureProperty.class);\r
+                            length += property.getInstructions().size() * STRUCTURE_HEADER_LENGTH;\r
+                        } else if (featProp.getAugmentation(NextTableRelatedTableFeatureProperty.class) != null) {\r
+                            NextTableRelatedTableFeatureProperty property =\r
+                                    featProp.getAugmentation(NextTableRelatedTableFeatureProperty.class);\r
+                            length += property.getNextTableIds().size();\r
+                        } else if (featProp.getAugmentation(ActionRelatedTableFeatureProperty.class) != null) {\r
+                            ActionRelatedTableFeatureProperty property =\r
+                                    featProp.getAugmentation(ActionRelatedTableFeatureProperty.class);\r
+                            length += property.getActionsList().size() * STRUCTURE_HEADER_LENGTH;\r
+                        } else if (featProp.getAugmentation(OxmRelatedTableFeatureProperty.class) != null) {\r
+                            OxmRelatedTableFeatureProperty property =\r
+                                    featProp.getAugmentation(OxmRelatedTableFeatureProperty.class);\r
+                            length += property.getMatchEntries().size() * STRUCTURE_HEADER_LENGTH;\r
+                        } else if (featProp.getAugmentation(ExperimenterRelatedTableFeatureProperty.class) != null) {\r
+                            ExperimenterRelatedTableFeatureProperty property =\r
+                                    featProp.getAugmentation(ExperimenterRelatedTableFeatureProperty.class);\r
+                            length += 2 * (Integer.SIZE / Byte.SIZE);\r
+                            if (property.getData() != null) {\r
+                                length += property.getData().length;\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        return length;\r
+    }\r
+\r
+    private static int createMultipartRequestFlagsBitmask(MultipartRequestFlags flags) {\r
+        int multipartRequestFlagsBitmask = 0;\r
+        Map<Integer, Boolean> multipartRequestFlagsMap = new HashMap<>();\r
+        multipartRequestFlagsMap.put(0, flags.isOFPMPFREQMORE());\r
+\r
+        multipartRequestFlagsBitmask = ByteBufUtils.fillBitMaskFromMap(multipartRequestFlagsMap);\r
+        return multipartRequestFlagsBitmask;\r
+    }\r
+\r
+    private void encodeDescBody(MultipartRequestBody multipartRequestBody,\r
+            ByteBuf output) {\r
+        // The body of MultiPartRequestDesc is empty\r
+\r
+    }\r
+\r
+    private static void encodeFlowBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+        final byte PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_01 = 3;\r
+        final byte PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_02 = 4;\r
+        MultipartRequestFlow flow = (MultipartRequestFlow) multipartRequestBody;\r
+        output.writeByte(flow.getTableId().byteValue());\r
+        ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_01, output);\r
+        output.writeInt(flow.getOutPort().intValue());\r
+        output.writeInt(flow.getOutGroup().intValue());\r
+        ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_02, output);\r
+        output.writeLong(flow.getCookie().longValue());\r
+        output.writeLong(flow.getCookieMask().longValue());\r
+        MatchSerializer.encodeMatch(flow.getMatch(), output);\r
+    }\r
+\r
+    private static void encodeAggregateBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+        final byte PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_01 = 3;\r
+        final byte PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_02 = 4;\r
+        MultipartRequestAggregate aggregate = (MultipartRequestAggregate) multipartRequestBody;\r
+        output.writeByte(aggregate.getTableId().byteValue());\r
+        ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_01, output);\r
+        output.writeInt(aggregate.getOutPort().intValue());\r
+        output.writeInt(aggregate.getOutGroup().intValue());\r
+        ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_02, output);\r
+        output.writeLong(aggregate.getCookie().longValue());\r
+        output.writeLong(aggregate.getCookieMask().longValue());\r
+        MatchSerializer.encodeMatch(aggregate.getMatch(), output);\r
+    }\r
+\r
+    private static void encodePortStatsBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+        final byte PADDING_IN_MULTIPART_REQUEST_PORTSTATS_BODY = 4;\r
+        MultipartRequestPortStats portstats = (MultipartRequestPortStats) multipartRequestBody;\r
+        output.writeInt(portstats.getPortNo().intValue());\r
+        ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_PORTSTATS_BODY, output);\r
+    }\r
+\r
+    private static void encodeQueueBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+        MultipartRequestQueue queue = (MultipartRequestQueue) multipartRequestBody;\r
+        output.writeInt(queue.getPortNo().intValue());\r
+        output.writeInt(queue.getQueueId().intValue());\r
+    }\r
+\r
+    private static void encodeGroupStatsBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+        final byte PADDING_IN_MULTIPART_REQUEST_GROUP_BODY = 4;\r
+        MultipartRequestGroup groupStats = (MultipartRequestGroup) multipartRequestBody;\r
+        output.writeInt(groupStats.getGroupId().intValue());\r
+        ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_GROUP_BODY, output);\r
+    }\r
+\r
+    private static void encodeMeterBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+        final byte PADDING_IN_MULTIPART_REQUEST_METER_BODY = 4;\r
+        MultipartRequestMeter meter = (MultipartRequestMeter) multipartRequestBody;\r
+        output.writeInt(meter.getMeterId().intValue());\r
+        ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_METER_BODY, output);\r
+    }\r
+\r
+    private static void encodeMeterConfigBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+        final byte PADDING_IN_MULTIPART_REQUEST_METER_CONFIG_BODY = 4;\r
+        MultipartRequestMeterConfig meterConfig = (MultipartRequestMeterConfig) multipartRequestBody;\r
+        output.writeInt(meterConfig.getMeterId().intValue());\r
+        ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_METER_CONFIG_BODY, output);\r
+    }\r
+\r
+    private static void encodeExperimenterBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+        MultipartRequestExperimenter experimenter = (MultipartRequestExperimenter) multipartRequestBody;\r
+        output.writeInt(experimenter.getExperimenter().intValue());\r
+        output.writeInt(experimenter.getExpType().intValue());\r
+        byte[] data = experimenter.getData();\r
+        if (data != null) {\r
+            output.writeBytes(data);\r
+        }\r
+    }\r
+\r
+    private static void encodeTableFeaturesBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+        if (multipartRequestBody != null) {\r
+            MultipartRequestTableFeatures tableFeatures = (MultipartRequestTableFeatures) multipartRequestBody;\r
+            for (TableFeatures currTableFeature : tableFeatures.getTableFeatures()) {\r
+                final byte PADDING_IN_MULTIPART_REQUEST_TABLE_FEATURES_BODY = 5;\r
+                output.writeByte(currTableFeature.getTableId());\r
+                ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_TABLE_FEATURES_BODY, output);\r
+                output.writeBytes(currTableFeature.getName().getBytes());\r
+                ByteBufUtils.padBuffer((32 - currTableFeature.getName().getBytes().length), output);\r
+                output.writeLong(currTableFeature.getMetadataMatch().longValue());\r
+                output.writeLong(currTableFeature.getMetadataWrite().longValue());\r
+                output.writeInt(createTableConfigBitmask(currTableFeature.getConfig()));\r
+                output.writeInt(currTableFeature.getMaxEntries().intValue());\r
+                writeTableFeatureProperties(output, currTableFeature.getTableFeatureProperties());\r
+            }\r
+        }\r
+    }\r
+\r
+    private static void writeTableFeatureProperties(ByteBuf output, List<TableFeatureProperties> props) {\r
+        if (props != null) {\r
+            for (TableFeatureProperties property : props) {\r
+                TableFeaturesPropType type = property.getType();\r
+                if (type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONS)) {\r
+                    final byte INSTRUCTIONS_CODE = 0;\r
+                    writeInstructionRelatedTableProperty(output, property, INSTRUCTIONS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONSMISS)) {\r
+                    final byte INSTRUCTIONS_MISS_CODE = 1;\r
+                    writeInstructionRelatedTableProperty(output, property, INSTRUCTIONS_MISS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLES)) {\r
+                    final byte NEXT_TABLE_CODE = 2;\r
+                    writeNextTableRelatedTableProperty(output, property, NEXT_TABLE_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLESMISS)) {\r
+                    final byte NEXT_TABLE_MISS_CODE = 3;\r
+                    writeNextTableRelatedTableProperty(output, property, NEXT_TABLE_MISS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITEACTIONS)) {\r
+                    final byte WRITE_ACTIONS_CODE = 4;\r
+                    writeActionsRelatedTableProperty(output, property, WRITE_ACTIONS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITEACTIONSMISS)) {\r
+                    final byte WRITE_ACTIONS_MISS_CODE = 5;\r
+                    writeActionsRelatedTableProperty(output, property, WRITE_ACTIONS_MISS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONS)) {\r
+                    final byte APPLY_ACTIONS_CODE = 6;\r
+                    writeActionsRelatedTableProperty(output, property, APPLY_ACTIONS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONSMISS)) {\r
+                    final byte APPLY_ACTIONS_MISS_CODE = 7;\r
+                    writeActionsRelatedTableProperty(output, property, APPLY_ACTIONS_MISS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTMATCH)) {\r
+                    final byte MATCH_CODE = 8;\r
+                    writeOxmRelatedTableProperty(output, property, MATCH_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTWILDCARDS)) {\r
+                    final byte WILDCARDS_CODE = 10;\r
+                    writeOxmRelatedTableProperty(output, property, WILDCARDS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITESETFIELD)) {\r
+                    final byte WRITE_SETFIELD_CODE = 12;\r
+                    writeOxmRelatedTableProperty(output, property, WRITE_SETFIELD_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITESETFIELDMISS)) {\r
+                    final byte WRITE_SETFIELD_MISS_CODE = 13;\r
+                    writeOxmRelatedTableProperty(output, property, WRITE_SETFIELD_MISS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELD)) {\r
+                    final byte APPLY_SETFIELD_CODE = 14;\r
+                    writeOxmRelatedTableProperty(output, property, APPLY_SETFIELD_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELDMISS)) {\r
+                    final byte APPLY_SETFIELD_MISS_CODE = 15;\r
+                    writeOxmRelatedTableProperty(output, property, APPLY_SETFIELD_MISS_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTER)) {\r
+                    final int EXPERIMENTER_CODE = 65534; // 0xFFFE\r
+                    writeExperimenterRelatedTableProperty(output, property, EXPERIMENTER_CODE);\r
+                } else if (type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTERMISS)) {\r
+                    final int EXPERIMENTER_MISS_CODE = 65535; // 0xFFFF\r
+                    writeExperimenterRelatedTableProperty(output, property, EXPERIMENTER_MISS_CODE);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    private static void writeInstructionRelatedTableProperty(ByteBuf output,\r
+            TableFeatureProperties property, byte code) {\r
+        output.writeShort(code);\r
+        List<Instructions> instructions = property.\r
+                getAugmentation(InstructionRelatedTableFeatureProperty.class).getInstructions();\r
+        int length = TABLE_FEAT_HEADER_LENGTH;\r
+        if (instructions != null) {\r
+        output.writeShort(InstructionsSerializer.computeInstructionsLength(instructions)\r
+                + TABLE_FEAT_HEADER_LENGTH);\r
+        InstructionsSerializer.encodeInstructions(instructions, output);\r
+        } else {\r
+            output.writeShort(length);\r
+        }\r
+    }\r
+\r
+    private static void writeNextTableRelatedTableProperty(ByteBuf output,\r
+            TableFeatureProperties property, byte code) {\r
+        output.writeShort(code);\r
+        List<NextTableIds> nextTableIds = property.\r
+                getAugmentation(NextTableRelatedTableFeatureProperty.class).getNextTableIds();\r
+        int length = TABLE_FEAT_HEADER_LENGTH;\r
+        if (nextTableIds != null) {\r
+            output.writeShort(length + nextTableIds.size());\r
+            for (NextTableIds next : nextTableIds) {\r
+                output.writeByte(next.getTableId());\r
+            }\r
+        } else {\r
+            output.writeShort(length);\r
+        }\r
+    }\r
+\r
+    private static void writeActionsRelatedTableProperty(ByteBuf output,\r
+            TableFeatureProperties property, byte code) {\r
+        output.writeShort(code);\r
+        List<ActionsList> actions = property.\r
+                getAugmentation(ActionRelatedTableFeatureProperty.class).getActionsList();\r
+        int length = TABLE_FEAT_HEADER_LENGTH;\r
+        if (actions != null) {\r
+        output.writeShort(ActionsSerializer.computeLengthOfActions(actions)\r
+                + TABLE_FEAT_HEADER_LENGTH);\r
+        ActionsSerializer.encodeActions(actions, output);\r
+        } else {\r
+            output.writeShort(length);\r
+        }\r
+    }\r
+\r
+    private static void writeOxmRelatedTableProperty(ByteBuf output,\r
+            TableFeatureProperties property, byte code) {\r
+        output.writeShort(code);\r
+        List<MatchEntries> entries = property.\r
+                getAugmentation(OxmRelatedTableFeatureProperty.class).getMatchEntries();\r
+        int length = TABLE_FEAT_HEADER_LENGTH;\r
+        if (entries != null) {\r
+        output.writeShort(MatchSerializer.computeMatchEntriesLength(entries)\r
+                + TABLE_FEAT_HEADER_LENGTH);\r
+        MatchSerializer.encodeMatchEntries(entries, output);\r
+        } else {\r
+            output.writeShort(length);\r
+        }\r
+    }\r
+\r
+    private static void writeExperimenterRelatedTableProperty(ByteBuf output,\r
+            TableFeatureProperties property, int code) {\r
+        output.writeShort(code);\r
+        ExperimenterRelatedTableFeatureProperty exp = property.\r
+                getAugmentation(ExperimenterRelatedTableFeatureProperty.class);\r
+        byte[] data = exp.getData();\r
+        int length = TABLE_FEAT_HEADER_LENGTH + 2 * (Integer.SIZE / Byte.SIZE);\r
+        if (data != null) {\r
+            output.writeShort(length + data.length);\r
+            output.writeInt(exp.getExperimenter().intValue());\r
+            output.writeInt(exp.getExpType().intValue());\r
+            output.writeBytes(data);\r
+        } else {\r
+            output.writeShort(length);\r
+            output.writeInt(exp.getExperimenter().intValue());\r
+            output.writeInt(exp.getExpType().intValue());\r
+        }\r
+    }\r
+\r
+    private static int createTableConfigBitmask(TableConfig tableConfig) {\r
+        int tableConfigBitmask = 0;\r
+        Map<Integer, Boolean> tableConfigMap = new HashMap<>();\r
+        tableConfigMap.put(3, tableConfig.isOFPTCDEPRECATEDMASK());\r
+\r
+        tableConfigBitmask = ByteBufUtils.fillBitMaskFromMap(tableConfigMap);\r
+        return tableConfigBitmask;\r
+    }\r
+}\r