Constants introduced
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / serialization / factories / MultipartRequestInputFactory.java
1 /* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */\r
2 package org.opendaylight.openflowjava.protocol.impl.serialization.factories;\r
3 \r
4 import io.netty.buffer.ByteBuf;\r
5 \r
6 import java.util.HashMap;\r
7 import java.util.List;\r
8 import java.util.Map;\r
9 \r
10 import org.opendaylight.openflowjava.protocol.impl.serialization.OFSerializer;\r
11 import org.opendaylight.openflowjava.protocol.impl.util.ActionsSerializer;\r
12 import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils;\r
13 import org.opendaylight.openflowjava.protocol.impl.util.EncodeConstants;\r
14 import org.opendaylight.openflowjava.protocol.impl.util.InstructionsSerializer;\r
15 import org.opendaylight.openflowjava.protocol.impl.util.MatchSerializer;\r
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionRelatedTableFeatureProperty;\r
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterRelatedTableFeatureProperty;\r
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.InstructionRelatedTableFeatureProperty;\r
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NextTableRelatedTableFeatureProperty;\r
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmRelatedTableFeatureProperty;\r
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.table.features.properties.container.table.feature.properties.NextTableIds;\r
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList;\r
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.Instructions;\r
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;\r
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;\r
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableConfig;\r
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesPropType;\r
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestAggregate;\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestDesc;\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenter;\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestFlow;\r
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroup;\r
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupDesc;\r
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupFeatures;\r
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeter;\r
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterConfig;\r
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterFeatures;\r
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortDesc;\r
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortStats;\r
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestQueue;\r
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTable;\r
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeatures;\r
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features.TableFeatures;\r
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.TableFeatureProperties;\r
48 \r
49 /**\r
50  * Translates MultipartRequest messages\r
51  * @author timotej.kubas\r
52  * @author michal.polkorab\r
53  */\r
54 public class MultipartRequestInputFactory implements OFSerializer<MultipartRequestInput> {\r
55     private static final byte MESSAGE_TYPE = 18;\r
56     private static final int MESSAGE_LENGTH = 16;\r
57     private static final byte PADDING_IN_MULTIPART_REQUEST_MESSAGE = 4;\r
58     private static final byte TABLE_FEAT_HEADER_LENGTH = 4;\r
59     private static MultipartRequestInputFactory instance;\r
60     private static final byte INSTRUCTIONS_CODE = 0;\r
61     private static final byte INSTRUCTIONS_MISS_CODE = 1;\r
62     private static final byte NEXT_TABLE_CODE = 2;\r
63     private static final byte NEXT_TABLE_MISS_CODE = 3;\r
64     private static final byte WRITE_ACTIONS_CODE = 4;\r
65     private static final byte WRITE_ACTIONS_MISS_CODE = 5;\r
66     private static final byte APPLY_ACTIONS_CODE = 6;\r
67     private static final byte APPLY_ACTIONS_MISS_CODE = 7;\r
68     private static final byte MATCH_CODE = 8;\r
69     private static final byte WILDCARDS_CODE = 10;\r
70     private static final byte WRITE_SETFIELD_CODE = 12;\r
71     private static final byte WRITE_SETFIELD_MISS_CODE = 13;\r
72     private static final byte APPLY_SETFIELD_CODE = 14;\r
73     private static final byte APPLY_SETFIELD_MISS_CODE = 15;\r
74     private static final int EXPERIMENTER_CODE = 65534; // 0xFFFE\r
75     private static final int EXPERIMENTER_MISS_CODE = 65535; // 0xFFFF\r
76     private static final byte FLOW_BODY_LENGTH = 32;\r
77     private static final byte AGGREGATE_BODY_LENGTH = 32;\r
78     private static final byte PORT_STATS_BODY_LENGTH = 8;\r
79     private static final byte QUEUE_BODY_LENGTH = 8;\r
80     private static final byte GROUP_BODY_LENGTH = 8;\r
81     private static final byte METER_BODY_LENGTH = 8;\r
82     private static final byte METER_CONFIG_BODY_LENGTH = 8;\r
83     private static final byte EXPERIMENTER_BODY_LENGTH = 8;\r
84     private static final byte TABLE_FEATURES_LENGTH = 64;\r
85     private static final byte STRUCTURE_HEADER_LENGTH = 4;\r
86     private static final byte PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_01 = 3;\r
87     private static final byte PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_02 = 4;\r
88     private static final byte PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_01 = 3;\r
89     private static final byte PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_02 = 4;\r
90     private static final byte PADDING_IN_MULTIPART_REQUEST_PORTSTATS_BODY = 4;\r
91     private static final byte PADDING_IN_MULTIPART_REQUEST_GROUP_BODY = 4;\r
92     private static final byte PADDING_IN_MULTIPART_REQUEST_METER_BODY = 4;\r
93     private static final byte PADDING_IN_MULTIPART_REQUEST_METER_CONFIG_BODY = 4;\r
94     private static final byte PADDING_IN_MULTIPART_REQUEST_TABLE_FEATURES_BODY = 5;\r
95     \r
96 \r
97 \r
98     private MultipartRequestInputFactory() {\r
99         // singleton\r
100     }\r
101 \r
102     /**\r
103      * @return singleton factory\r
104      */\r
105     public static synchronized MultipartRequestInputFactory getInstance() {\r
106         if (instance == null) {\r
107             instance = new MultipartRequestInputFactory();\r
108         }\r
109         return instance;\r
110     }\r
111 \r
112     @Override\r
113     public void messageToBuffer(short version, ByteBuf out,\r
114             MultipartRequestInput message) {\r
115         ByteBufUtils.writeOFHeader(instance, message, out);\r
116         out.writeShort(message.getType().getIntValue());\r
117         out.writeShort(createMultipartRequestFlagsBitmask(message.getFlags()));\r
118         ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_MESSAGE, out);\r
119 \r
120         if (message.getMultipartRequestBody() instanceof MultipartRequestDesc ){\r
121             encodeDescBody(message.getMultipartRequestBody(), out);\r
122         } else if (message.getMultipartRequestBody() instanceof MultipartRequestFlow) {\r
123             encodeFlowBody(message.getMultipartRequestBody(), out);\r
124         } else if (message.getMultipartRequestBody() instanceof MultipartRequestAggregate) {\r
125             encodeAggregateBody(message.getMultipartRequestBody(), out);\r
126         } else if (message.getMultipartRequestBody() instanceof MultipartRequestTable) {\r
127             encodeTableBody(message.getMultipartRequestBody(), out);\r
128         } else if (message.getMultipartRequestBody() instanceof MultipartRequestPortStats) {\r
129             encodePortStatsBody(message.getMultipartRequestBody(), out);\r
130         } else if (message.getMultipartRequestBody() instanceof MultipartRequestQueue) {\r
131             encodeQueueBody(message.getMultipartRequestBody(), out);\r
132         } else if (message.getMultipartRequestBody() instanceof MultipartRequestGroup) {\r
133             encodeGroupStatsBody(message.getMultipartRequestBody(), out);\r
134         } else if (message.getMultipartRequestBody() instanceof MultipartRequestGroupDesc) {\r
135             encodeGroupDescBody(message.getMultipartRequestBody(), out);\r
136         } else if (message.getMultipartRequestBody() instanceof MultipartRequestGroupFeatures) {\r
137             encodeGroupFeaturesBody(message.getMultipartRequestBody(), out);\r
138         } else if (message.getMultipartRequestBody() instanceof MultipartRequestMeter) {\r
139             encodeMeterBody(message.getMultipartRequestBody(), out);\r
140         } else if (message.getMultipartRequestBody() instanceof MultipartRequestMeterConfig) {\r
141             encodeMeterConfigBody(message.getMultipartRequestBody(), out);\r
142         } else if (message.getMultipartRequestBody() instanceof MultipartRequestMeterFeatures) {\r
143             encodeMeterFeaturesBody(message.getMultipartRequestBody(), out);\r
144         } else if (message.getMultipartRequestBody() instanceof MultipartRequestTableFeatures) {\r
145             encodeTableFeaturesBody(message.getMultipartRequestBody(), out);\r
146         } else if (message.getMultipartRequestBody() instanceof MultipartRequestPortDesc) {\r
147             encodePortDescBody(message.getMultipartRequestBody(), out);\r
148         } else if (message.getMultipartRequestBody() instanceof MultipartRequestExperimenter) {\r
149             encodeExperimenterBody(message.getMultipartRequestBody(), out);\r
150         }\r
151     }\r
152 \r
153     @Override\r
154     public int computeLength(MultipartRequestInput message) {\r
155         return MESSAGE_LENGTH + computeBodyLength(message);\r
156     }\r
157     @Override\r
158     public byte getMessageType() {\r
159         return MESSAGE_TYPE;\r
160     }\r
161 \r
162     /**\r
163      *\r
164      * @param message\r
165      * @return length of MultipartRequestMessage\r
166      */\r
167     public int computeBodyLength(MultipartRequestInput message) {\r
168         int length = 0;\r
169         MultipartType type = message.getType();\r
170         if (type.equals(MultipartType.OFPMPFLOW)) {\r
171             MultipartRequestFlow body = (MultipartRequestFlow) message.getMultipartRequestBody();\r
172             length += FLOW_BODY_LENGTH + MatchSerializer.computeMatchLength(body.getMatch());\r
173         } else if (type.equals(MultipartType.OFPMPAGGREGATE)) {\r
174             MultipartRequestAggregate body = (MultipartRequestAggregate) message.getMultipartRequestBody();\r
175             length += AGGREGATE_BODY_LENGTH + MatchSerializer.computeMatchLength(body.getMatch());\r
176         } else if (type.equals(MultipartType.OFPMPPORTSTATS)) {\r
177             length += PORT_STATS_BODY_LENGTH;\r
178         } else if (type.equals(MultipartType.OFPMPQUEUE)) {\r
179             length += QUEUE_BODY_LENGTH;\r
180         } else if (type.equals(MultipartType.OFPMPGROUP)) {\r
181             length += GROUP_BODY_LENGTH;\r
182         } else if (type.equals(MultipartType.OFPMPMETER)) {\r
183             length += METER_BODY_LENGTH;\r
184         } else if (type.equals(MultipartType.OFPMPMETERCONFIG)) {\r
185             length += METER_CONFIG_BODY_LENGTH;\r
186         } else if (type.equals(MultipartType.OFPMPTABLEFEATURES)) {\r
187             MultipartRequestTableFeatures body = (MultipartRequestTableFeatures) message.getMultipartRequestBody();\r
188             length += computeTableFeaturesLength(body);\r
189         } else if (type.equals(MultipartType.OFPMPEXPERIMENTER)) {\r
190             MultipartRequestExperimenter body = (MultipartRequestExperimenter) message.getMultipartRequestBody();\r
191             length += EXPERIMENTER_BODY_LENGTH;\r
192             if (body.getData() != null) {\r
193                 length += body.getData().length;\r
194             }\r
195         }\r
196         return length;\r
197     }\r
198 \r
199     private static int computeTableFeaturesLength(MultipartRequestTableFeatures body) {\r
200         int length = 0;\r
201         if (body != null && body.getTableFeatures() != null) {\r
202             List<TableFeatures> tableFeatures = body.getTableFeatures();\r
203             for (TableFeatures feature : tableFeatures) {\r
204                 length += TABLE_FEATURES_LENGTH;\r
205                 List<TableFeatureProperties> featureProperties = feature.getTableFeatureProperties();\r
206                 if (featureProperties != null) {\r
207                     for (TableFeatureProperties featProp : featureProperties) {\r
208                         length += TABLE_FEAT_HEADER_LENGTH;\r
209                         if (featProp.getAugmentation(InstructionRelatedTableFeatureProperty.class) != null) {\r
210                             InstructionRelatedTableFeatureProperty property =\r
211                                     featProp.getAugmentation(InstructionRelatedTableFeatureProperty.class);\r
212                             length += property.getInstructions().size() * STRUCTURE_HEADER_LENGTH;\r
213                         } else if (featProp.getAugmentation(NextTableRelatedTableFeatureProperty.class) != null) {\r
214                             NextTableRelatedTableFeatureProperty property =\r
215                                     featProp.getAugmentation(NextTableRelatedTableFeatureProperty.class);\r
216                             length += property.getNextTableIds().size();\r
217                         } else if (featProp.getAugmentation(ActionRelatedTableFeatureProperty.class) != null) {\r
218                             ActionRelatedTableFeatureProperty property =\r
219                                     featProp.getAugmentation(ActionRelatedTableFeatureProperty.class);\r
220                             length += property.getActionsList().size() * STRUCTURE_HEADER_LENGTH;\r
221                         } else if (featProp.getAugmentation(OxmRelatedTableFeatureProperty.class) != null) {\r
222                             OxmRelatedTableFeatureProperty property =\r
223                                     featProp.getAugmentation(OxmRelatedTableFeatureProperty.class);\r
224                             length += property.getMatchEntries().size() * STRUCTURE_HEADER_LENGTH;\r
225                         } else if (featProp.getAugmentation(ExperimenterRelatedTableFeatureProperty.class) != null) {\r
226                             ExperimenterRelatedTableFeatureProperty property =\r
227                                     featProp.getAugmentation(ExperimenterRelatedTableFeatureProperty.class);\r
228                             length += 2 * (EncodeConstants.SIZE_OF_INT_IN_BYTES);\r
229                             if (property.getData() != null) {\r
230                                 length += property.getData().length;\r
231                             }\r
232                         }\r
233                     }\r
234                 }\r
235             }\r
236         }\r
237         return length;\r
238     }\r
239 \r
240     private static int createMultipartRequestFlagsBitmask(MultipartRequestFlags flags) {\r
241         int multipartRequestFlagsBitmask = 0;\r
242         Map<Integer, Boolean> multipartRequestFlagsMap = new HashMap<>();\r
243         multipartRequestFlagsMap.put(0, flags.isOFPMPFREQMORE());\r
244 \r
245         multipartRequestFlagsBitmask = ByteBufUtils.fillBitMaskFromMap(multipartRequestFlagsMap);\r
246         return multipartRequestFlagsBitmask;\r
247     }\r
248 \r
249     /**\r
250      * @param multipartRequestBody\r
251      * @param output\r
252      */\r
253     private void encodeDescBody(MultipartRequestBody multipartRequestBody,\r
254             ByteBuf output) {\r
255         // The body of MultiPartRequestDesc is empty\r
256     }\r
257 \r
258     /**\r
259      * @param multipartRequestBody\r
260      * @param out\r
261      */\r
262     private void encodeTableBody(MultipartRequestBody multipartRequestBody,\r
263             ByteBuf out) {\r
264      // The body of MultiPartTable is empty\r
265     }\r
266 \r
267     /**\r
268      * @param multipartRequestBody\r
269      * @param out\r
270      */\r
271     private void encodeGroupDescBody(MultipartRequestBody multipartRequestBody,\r
272             ByteBuf out) {\r
273      // The body of MultiPartRequestGroupDesc is empty\r
274     }\r
275 \r
276     /**\r
277      * @param multipartRequestBody\r
278      * @param out\r
279      */\r
280     private void encodeGroupFeaturesBody(\r
281             MultipartRequestBody multipartRequestBody, ByteBuf out) {\r
282      // The body of MultiPartRequestGroupFeatures is empty\r
283     }\r
284 \r
285     /**\r
286      * @param multipartRequestBody\r
287      * @param out\r
288      */\r
289     private void encodeMeterFeaturesBody(\r
290             MultipartRequestBody multipartRequestBody, ByteBuf out) {\r
291      // The body of MultiPartMeterFeatures is empty\r
292     }\r
293 \r
294     /**\r
295      * @param multipartRequestBody\r
296      * @param out\r
297      */\r
298     private void encodePortDescBody(MultipartRequestBody multipartRequestBody,\r
299             ByteBuf out) {\r
300      // The body of MultiPartPortDesc is empty\r
301     }\r
302 \r
303     private static void encodeFlowBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
304         MultipartRequestFlow flow = (MultipartRequestFlow) multipartRequestBody;\r
305         output.writeByte(flow.getTableId().byteValue());\r
306         ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_01, output);\r
307         output.writeInt(flow.getOutPort().intValue());\r
308         output.writeInt(flow.getOutGroup().intValue());\r
309         ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_02, output);\r
310         output.writeLong(flow.getCookie().longValue());\r
311         output.writeLong(flow.getCookieMask().longValue());\r
312         MatchSerializer.encodeMatch(flow.getMatch(), output);\r
313     }\r
314 \r
315     private static void encodeAggregateBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
316         MultipartRequestAggregate aggregate = (MultipartRequestAggregate) multipartRequestBody;\r
317         output.writeByte(aggregate.getTableId().byteValue());\r
318         ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_01, output);\r
319         output.writeInt(aggregate.getOutPort().intValue());\r
320         output.writeInt(aggregate.getOutGroup().intValue());\r
321         ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_02, output);\r
322         output.writeLong(aggregate.getCookie().longValue());\r
323         output.writeLong(aggregate.getCookieMask().longValue());\r
324         MatchSerializer.encodeMatch(aggregate.getMatch(), output);\r
325     }\r
326 \r
327     private static void encodePortStatsBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
328         MultipartRequestPortStats portstats = (MultipartRequestPortStats) multipartRequestBody;\r
329         output.writeInt(portstats.getPortNo().intValue());\r
330         ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_PORTSTATS_BODY, output);\r
331     }\r
332 \r
333     private static void encodeQueueBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
334         MultipartRequestQueue queue = (MultipartRequestQueue) multipartRequestBody;\r
335         output.writeInt(queue.getPortNo().intValue());\r
336         output.writeInt(queue.getQueueId().intValue());\r
337     }\r
338 \r
339     private static void encodeGroupStatsBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
340         MultipartRequestGroup groupStats = (MultipartRequestGroup) multipartRequestBody;\r
341         output.writeInt(groupStats.getGroupId().intValue());\r
342         ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_GROUP_BODY, output);\r
343     }\r
344 \r
345     private static void encodeMeterBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
346         MultipartRequestMeter meter = (MultipartRequestMeter) multipartRequestBody;\r
347         output.writeInt(meter.getMeterId().intValue());\r
348         ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_METER_BODY, output);\r
349     }\r
350 \r
351     private static void encodeMeterConfigBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
352         MultipartRequestMeterConfig meterConfig = (MultipartRequestMeterConfig) multipartRequestBody;\r
353         output.writeInt(meterConfig.getMeterId().intValue());\r
354         ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_METER_CONFIG_BODY, output);\r
355     }\r
356 \r
357     private static void encodeExperimenterBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
358         MultipartRequestExperimenter experimenter = (MultipartRequestExperimenter) multipartRequestBody;\r
359         output.writeInt(experimenter.getExperimenter().intValue());\r
360         output.writeInt(experimenter.getExpType().intValue());\r
361         byte[] data = experimenter.getData();\r
362         if (data != null) {\r
363             output.writeBytes(data);\r
364         }\r
365     }\r
366 \r
367     private static void encodeTableFeaturesBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
368         if (multipartRequestBody != null) {\r
369             MultipartRequestTableFeatures tableFeatures = (MultipartRequestTableFeatures) multipartRequestBody;\r
370             if(tableFeatures.getTableFeatures() != null) {\r
371                 for (TableFeatures currTableFeature : tableFeatures.getTableFeatures()) {\r
372                     output.writeByte(currTableFeature.getTableId());\r
373                     ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_TABLE_FEATURES_BODY, output);\r
374                     output.writeBytes(currTableFeature.getName().getBytes());\r
375                     ByteBufUtils.padBuffer((32 - currTableFeature.getName().getBytes().length), output);\r
376                     output.writeLong(currTableFeature.getMetadataMatch().longValue());\r
377                     output.writeLong(currTableFeature.getMetadataWrite().longValue());\r
378                     output.writeInt(createTableConfigBitmask(currTableFeature.getConfig()));\r
379                     output.writeInt(currTableFeature.getMaxEntries().intValue());\r
380                     writeTableFeatureProperties(output, currTableFeature.getTableFeatureProperties());\r
381                 }\r
382             }\r
383         }\r
384     }\r
385 \r
386     private static void writeTableFeatureProperties(ByteBuf output, List<TableFeatureProperties> props) {\r
387         if (props != null) {\r
388             for (TableFeatureProperties property : props) {\r
389                 TableFeaturesPropType type = property.getType();\r
390                 if (type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONS)) {\r
391                     writeInstructionRelatedTableProperty(output, property, INSTRUCTIONS_CODE);\r
392                 } else if (type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONSMISS)) {\r
393                     writeInstructionRelatedTableProperty(output, property, INSTRUCTIONS_MISS_CODE);\r
394                 } else if (type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLES)) {\r
395                     writeNextTableRelatedTableProperty(output, property, NEXT_TABLE_CODE);\r
396                 } else if (type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLESMISS)) {\r
397                     writeNextTableRelatedTableProperty(output, property, NEXT_TABLE_MISS_CODE);\r
398                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITEACTIONS)) {\r
399                     writeActionsRelatedTableProperty(output, property, WRITE_ACTIONS_CODE);\r
400                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITEACTIONSMISS)) {\r
401                     writeActionsRelatedTableProperty(output, property, WRITE_ACTIONS_MISS_CODE);\r
402                 } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONS)) {\r
403                     writeActionsRelatedTableProperty(output, property, APPLY_ACTIONS_CODE);\r
404                 } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONSMISS)) {\r
405                     writeActionsRelatedTableProperty(output, property, APPLY_ACTIONS_MISS_CODE);\r
406                 } else if (type.equals(TableFeaturesPropType.OFPTFPTMATCH)) {\r
407                     writeOxmRelatedTableProperty(output, property, MATCH_CODE);\r
408                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWILDCARDS)) {\r
409                     writeOxmRelatedTableProperty(output, property, WILDCARDS_CODE);\r
410                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITESETFIELD)) {\r
411                     writeOxmRelatedTableProperty(output, property, WRITE_SETFIELD_CODE);\r
412                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITESETFIELDMISS)) {\r
413                     writeOxmRelatedTableProperty(output, property, WRITE_SETFIELD_MISS_CODE);\r
414                 } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELD)) {\r
415                     writeOxmRelatedTableProperty(output, property, APPLY_SETFIELD_CODE);\r
416                 } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELDMISS)) {\r
417                     writeOxmRelatedTableProperty(output, property, APPLY_SETFIELD_MISS_CODE);\r
418                 } else if (type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTER)) {\r
419                     writeExperimenterRelatedTableProperty(output, property, EXPERIMENTER_CODE);\r
420                 } else if (type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTERMISS)) {\r
421                     writeExperimenterRelatedTableProperty(output, property, EXPERIMENTER_MISS_CODE);\r
422                 }\r
423             }\r
424         }\r
425     }\r
426 \r
427     private static void writeInstructionRelatedTableProperty(ByteBuf output,\r
428             TableFeatureProperties property, byte code) {\r
429         output.writeShort(code);\r
430         List<Instructions> instructions = property.\r
431                 getAugmentation(InstructionRelatedTableFeatureProperty.class).getInstructions();\r
432         int length = TABLE_FEAT_HEADER_LENGTH;\r
433         if (instructions != null) {\r
434         output.writeShort(InstructionsSerializer.computeInstructionsLength(instructions)\r
435                 + TABLE_FEAT_HEADER_LENGTH);\r
436         InstructionsSerializer.encodeInstructions(instructions, output);\r
437         } else {\r
438             output.writeShort(length);\r
439         }\r
440     }\r
441 \r
442     private static void writeNextTableRelatedTableProperty(ByteBuf output,\r
443             TableFeatureProperties property, byte code) {\r
444         output.writeShort(code);\r
445         List<NextTableIds> nextTableIds = property.\r
446                 getAugmentation(NextTableRelatedTableFeatureProperty.class).getNextTableIds();\r
447         int length = TABLE_FEAT_HEADER_LENGTH;\r
448         if (nextTableIds != null) {\r
449             output.writeShort(length + nextTableIds.size());\r
450             for (NextTableIds next : nextTableIds) {\r
451                 output.writeByte(next.getTableId());\r
452             }\r
453         } else {\r
454             output.writeShort(length);\r
455         }\r
456     }\r
457 \r
458     private static void writeActionsRelatedTableProperty(ByteBuf output,\r
459             TableFeatureProperties property, byte code) {\r
460         output.writeShort(code);\r
461         List<ActionsList> actions = property.\r
462                 getAugmentation(ActionRelatedTableFeatureProperty.class).getActionsList();\r
463         int length = TABLE_FEAT_HEADER_LENGTH;\r
464         if (actions != null) {\r
465         output.writeShort(ActionsSerializer.computeLengthOfActions(actions)\r
466                 + TABLE_FEAT_HEADER_LENGTH);\r
467         ActionsSerializer.encodeActions(actions, output);\r
468         } else {\r
469             output.writeShort(length);\r
470         }\r
471     }\r
472 \r
473     private static void writeOxmRelatedTableProperty(ByteBuf output,\r
474             TableFeatureProperties property, byte code) {\r
475         output.writeShort(code);\r
476         List<MatchEntries> entries = property.\r
477                 getAugmentation(OxmRelatedTableFeatureProperty.class).getMatchEntries();\r
478         int length = TABLE_FEAT_HEADER_LENGTH;\r
479         if (entries != null) {\r
480         output.writeShort(MatchSerializer.computeMatchEntriesLength(entries)\r
481                 + TABLE_FEAT_HEADER_LENGTH);\r
482         MatchSerializer.encodeMatchEntries(entries, output);\r
483         } else {\r
484             output.writeShort(length);\r
485         }\r
486     }\r
487 \r
488     private static void writeExperimenterRelatedTableProperty(ByteBuf output,\r
489             TableFeatureProperties property, int code) {\r
490         output.writeShort(code);\r
491         ExperimenterRelatedTableFeatureProperty exp = property.\r
492                 getAugmentation(ExperimenterRelatedTableFeatureProperty.class);\r
493         byte[] data = exp.getData();\r
494         int length = TABLE_FEAT_HEADER_LENGTH + 2 * (EncodeConstants.SIZE_OF_INT_IN_BYTES);\r
495         if (data != null) {\r
496             output.writeShort(length + data.length);\r
497             output.writeInt(exp.getExperimenter().intValue());\r
498             output.writeInt(exp.getExpType().intValue());\r
499             output.writeBytes(data);\r
500         } else {\r
501             output.writeShort(length);\r
502             output.writeInt(exp.getExperimenter().intValue());\r
503             output.writeInt(exp.getExpType().intValue());\r
504         }\r
505     }\r
506 \r
507     private static int createTableConfigBitmask(TableConfig tableConfig) {\r
508         int tableConfigBitmask = 0;\r
509         Map<Integer, Boolean> tableConfigMap = new HashMap<>();\r
510         tableConfigMap.put(3, tableConfig.isOFPTCDEPRECATEDMASK());\r
511 \r
512         tableConfigBitmask = ByteBufUtils.fillBitMaskFromMap(tableConfigMap);\r
513         return tableConfigBitmask;\r
514     }\r
515 }\r