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