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