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