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