Extend openflow-protocol-impl serialization
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / serialization / factories / MultipartReplyMessageFactory.java
1 /*
2  * Copyright (c) 2015 NetIDE Consortium 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 package org.opendaylight.openflowjava.protocol.impl.serialization.factories;
9
10 import io.netty.buffer.ByteBuf;
11 import io.netty.buffer.UnpooledByteBufAllocator;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
16 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
17 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector;
18 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
19 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
20 import org.opendaylight.openflowjava.protocol.impl.util.ListSerializer;
21 import org.opendaylight.openflowjava.protocol.impl.util.TypeKeyMaker;
22 import org.opendaylight.openflowjava.protocol.impl.util.TypeKeyMakerFactory;
23 import org.opendaylight.openflowjava.util.ByteBufUtils;
24 import org.opendaylight.openflowjava.util.ExperimenterSerializerKeyFactory;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.ActionRelatedTableFeatureProperty;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.ExperimenterIdTableFeatureProperty;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.InstructionRelatedTableFeatureProperty;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.NextTableRelatedTableFeatureProperty;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.OxmRelatedTableFeatureProperty;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.table.features.properties.container.table.feature.properties.NextTableIds;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupCapabilities;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupTypes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterBandTypeBitmap;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterFlags;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortConfig;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortFeatures;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortState;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableConfig;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.Match;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterBandCommons;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsList;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.MeterBand;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandDropCase;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandDscpRemarkCase;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandExperimenterCase;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.meter.band.drop._case.MeterBandDrop;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.meter.band.dscp.remark._case.MeterBandDscpRemark;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.meter.band.experimenter._case.MeterBandExperimenter;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.MultipartReplyBody;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCase;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupCase;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupDescCase;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupFeaturesCase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterCase;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterConfigCase;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterFeaturesCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortDescCase;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableCase;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesCase;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.aggregate._case.MultipartReplyAggregate;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.experimenter._case.MultipartReplyExperimenter;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlow;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStats;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.MultipartReplyGroup;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.GroupStats;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group._case.multipart.reply.group.group.stats.BucketStats;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.MultipartReplyGroupDesc;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.desc._case.multipart.reply.group.desc.GroupDesc;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.group.features._case.MultipartReplyGroupFeatures;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.MultipartReplyMeter;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.multipart.reply.meter.MeterStats;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter._case.multipart.reply.meter.meter.stats.MeterBandStats;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.config._case.MultipartReplyMeterConfig;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.config._case.multipart.reply.meter.config.MeterConfig;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.config._case.multipart.reply.meter.config.meter.config.Bands;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.meter.features._case.MultipartReplyMeterFeatures;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.desc._case.MultipartReplyPortDesc;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.desc._case.multipart.reply.port.desc.Ports;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStats;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStats;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueue;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.MultipartReplyTable;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.multipart.reply.table.TableStats;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeatures;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.multipart.reply.table.features.TableFeatures;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.grouping.TableFeatureProperties;
100
101 /**
102  * @author giuseppex.petralia@intel.com
103  *
104  */
105 public class MultipartReplyMessageFactory implements OFSerializer<MultipartReplyMessage>, SerializerRegistryInjector {
106
107     private static final byte MESSAGE_TYPE = 19;
108     private SerializerRegistry registry;
109     private static final byte PADDING = 4;
110     private static final byte PORT_DESC_PADDING_1 = 4;
111     private static final byte PORT_DESC_PADDING_2 = 2;
112     private static final int FLOW_STATS_LENGTH_INDEX = 0;
113     private static final byte FLOW_STATS_PADDING_1 = 1;
114     private static final byte FLOW_STATS_PADDING_2 = 6;
115     private static final byte AGGREGATE_PADDING = 4;
116     private static final byte TABLE_PADDING = 3;
117     private static final byte PORT_STATS_PADDING = 4;
118     private static final byte GROUP_STATS_PADDING_1 = 2;
119     private static final byte GROUP_STATS_PADDING_2 = 4;
120     private static final int GROUP_STATS_LENGTH_INDEX = 0;
121     private static final int GROUP_DESC_LENGTH_INDEX = 0;
122     private static final int BUCKET_LENGTH_INDEX = 0;
123     private static final byte GROUP_DESC_PADDING = 1;
124     private static final byte BUCKET_PADDING = 4;
125     private static final int METER_LENGTH_INDEX = 4;
126     private static final byte METER_PADDING = 6;
127     private static final int METER_CONFIG_LENGTH_INDEX = 0;
128     private static final short LENGTH_OF_METER_BANDS = 16;
129     private static final byte METER_FEATURES_PADDING = 2;
130     private static final int TABLE_FEATURES_LENGTH_INDEX = 0;
131     private static final byte TABLE_FEATURES_PADDING = 5;
132     private static final byte INSTRUCTIONS_CODE = 0;
133     private static final byte INSTRUCTIONS_MISS_CODE = 1;
134     private static final byte NEXT_TABLE_CODE = 2;
135     private static final byte NEXT_TABLE_MISS_CODE = 3;
136     private static final byte WRITE_ACTIONS_CODE = 4;
137     private static final byte WRITE_ACTIONS_MISS_CODE = 5;
138     private static final byte APPLY_ACTIONS_CODE = 6;
139     private static final byte APPLY_ACTIONS_MISS_CODE = 7;
140     private static final byte MATCH_CODE = 8;
141     private static final byte WILDCARDS_CODE = 10;
142     private static final byte WRITE_SETFIELD_CODE = 12;
143     private static final byte WRITE_SETFIELD_MISS_CODE = 13;
144     private static final byte APPLY_SETFIELD_CODE = 14;
145     private static final byte APPLY_SETFIELD_MISS_CODE = 15;
146
147     @Override
148     public void injectSerializerRegistry(SerializerRegistry serializerRegistry) {
149         this.registry = serializerRegistry;
150     }
151
152     @Override
153     public void serialize(MultipartReplyMessage message, ByteBuf outBuffer) {
154         ByteBufUtils.writeOFHeader(MESSAGE_TYPE, message, outBuffer, EncodeConstants.EMPTY_LENGTH);
155         outBuffer.writeShort(message.getType().getIntValue());
156         writeFlags(message.getFlags(), outBuffer);
157         outBuffer.writeZero(PADDING);
158         switch (message.getType()) {
159         case OFPMPDESC:
160             serializeDescBody(message.getMultipartReplyBody(), outBuffer);
161             break;
162         case OFPMPFLOW:
163             serializeFlowBody(message.getMultipartReplyBody(), outBuffer, message);
164             break;
165         case OFPMPAGGREGATE:
166             serializeAggregateBody(message.getMultipartReplyBody(), outBuffer);
167             break;
168         case OFPMPTABLE:
169             serializeTableBody(message.getMultipartReplyBody(), outBuffer);
170             break;
171         case OFPMPPORTSTATS:
172             serializePortStatsBody(message.getMultipartReplyBody(), outBuffer);
173             break;
174         case OFPMPQUEUE:
175             serializeQueueBody(message.getMultipartReplyBody(), outBuffer);
176             break;
177         case OFPMPGROUP:
178             serializeGroupBody(message.getMultipartReplyBody(), outBuffer);
179             break;
180         case OFPMPGROUPDESC:
181             serializeGroupDescBody(message.getMultipartReplyBody(), outBuffer, message);
182             break;
183         case OFPMPGROUPFEATURES:
184             serializeGroupFeaturesBody(message.getMultipartReplyBody(), outBuffer);
185             break;
186         case OFPMPMETER:
187             serializeMeterBody(message.getMultipartReplyBody(), outBuffer);
188             break;
189         case OFPMPMETERCONFIG:
190             serializeMeterConfigBody(message.getMultipartReplyBody(), outBuffer);
191             break;
192         case OFPMPMETERFEATURES:
193             serializeMeterFeaturesBody(message.getMultipartReplyBody(), outBuffer);
194             break;
195         case OFPMPTABLEFEATURES:
196             serializeTableFeaturesBody(message.getMultipartReplyBody(), outBuffer);
197             break;
198         case OFPMPPORTDESC:
199             serializePortDescBody(message.getMultipartReplyBody(), outBuffer);
200             break;
201         case OFPMPEXPERIMENTER:
202             serializeExperimenterBody(message.getMultipartReplyBody(), outBuffer);
203             break;
204         }
205         ByteBufUtils.updateOFHeaderLength(outBuffer);
206     }
207
208     private void serializeExperimenterBody(MultipartReplyBody body, ByteBuf outBuffer) {
209         MultipartReplyExperimenterCase experimenterCase = (MultipartReplyExperimenterCase) body;
210         MultipartReplyExperimenter experimenterBody = experimenterCase.getMultipartReplyExperimenter();
211         // TODO: experimenterBody does not have get methods
212     }
213
214     private void writeFlags(MultipartRequestFlags flags, ByteBuf outBuffer) {
215         Map<Integer, Boolean> map = new HashMap<>();
216         map.put(0, flags.isOFPMPFREQMORE());
217         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
218         outBuffer.writeShort(bitmap);
219     }
220
221     private void serializeTableFeaturesBody(MultipartReplyBody body, ByteBuf outBuffer) {
222         MultipartReplyTableFeaturesCase tableFeaturesCase = (MultipartReplyTableFeaturesCase) body;
223         MultipartReplyTableFeatures tableFeatures = tableFeaturesCase.getMultipartReplyTableFeatures();
224         for (TableFeatures tableFeature : tableFeatures.getTableFeatures()) {
225             ByteBuf tableFeatureBuff = UnpooledByteBufAllocator.DEFAULT.buffer();
226             tableFeatureBuff.writeShort(EncodeConstants.EMPTY_LENGTH);
227             tableFeatureBuff.writeByte(tableFeature.getTableId());
228             tableFeatureBuff.writeZero(TABLE_FEATURES_PADDING);
229             write32String(tableFeature.getName(), tableFeatureBuff);
230             tableFeatureBuff.writeBytes(tableFeature.getMetadataMatch());
231             tableFeatureBuff.writeZero(64 - tableFeature.getMetadataMatch().length);
232             tableFeatureBuff.writeBytes(tableFeature.getMetadataWrite());
233             tableFeatureBuff.writeZero(64 - tableFeature.getMetadataWrite().length);
234             writeTableConfig(tableFeature.getConfig(), tableFeatureBuff);
235             tableFeatureBuff.writeInt(tableFeature.getMaxEntries().intValue());
236             for (TableFeatureProperties tableFeatureProp : tableFeature.getTableFeatureProperties()) {
237                 switch (tableFeatureProp.getType()) {
238                 case OFPTFPTINSTRUCTIONS:
239                     writeInstructionRelatedTableProperty(tableFeatureBuff, tableFeatureProp, INSTRUCTIONS_CODE);
240                     break;
241                 case OFPTFPTINSTRUCTIONSMISS:
242                     writeInstructionRelatedTableProperty(tableFeatureBuff, tableFeatureProp, INSTRUCTIONS_MISS_CODE);
243                     break;
244                 case OFPTFPTNEXTTABLES:
245                     writeNextTableRelatedTableProperty(tableFeatureBuff, tableFeatureProp, NEXT_TABLE_CODE);
246                     break;
247                 case OFPTFPTNEXTTABLESMISS:
248                     writeNextTableRelatedTableProperty(tableFeatureBuff, tableFeatureProp, NEXT_TABLE_MISS_CODE);
249                     break;
250                 case OFPTFPTWRITEACTIONS:
251                     writeActionsRelatedTableProperty(tableFeatureBuff, tableFeatureProp, WRITE_ACTIONS_CODE);
252                     break;
253                 case OFPTFPTWRITEACTIONSMISS:
254                     writeActionsRelatedTableProperty(tableFeatureBuff, tableFeatureProp, WRITE_ACTIONS_MISS_CODE);
255                     break;
256                 case OFPTFPTAPPLYACTIONS:
257                     writeActionsRelatedTableProperty(tableFeatureBuff, tableFeatureProp, APPLY_ACTIONS_CODE);
258                     break;
259                 case OFPTFPTAPPLYACTIONSMISS:
260                     writeActionsRelatedTableProperty(tableFeatureBuff, tableFeatureProp, APPLY_ACTIONS_MISS_CODE);
261                     break;
262                 case OFPTFPTMATCH:
263                     writeOxmRelatedTableProperty(tableFeatureBuff, tableFeatureProp, MATCH_CODE);
264                     break;
265                 case OFPTFPTWILDCARDS:
266                     writeOxmRelatedTableProperty(tableFeatureBuff, tableFeatureProp, WILDCARDS_CODE);
267                     break;
268                 case OFPTFPTWRITESETFIELD:
269                     writeOxmRelatedTableProperty(tableFeatureBuff, tableFeatureProp, WRITE_SETFIELD_CODE);
270                     break;
271                 case OFPTFPTWRITESETFIELDMISS:
272                     writeOxmRelatedTableProperty(tableFeatureBuff, tableFeatureProp, WRITE_SETFIELD_MISS_CODE);
273                     break;
274                 case OFPTFPTAPPLYSETFIELD:
275                     writeOxmRelatedTableProperty(tableFeatureBuff, tableFeatureProp, APPLY_SETFIELD_CODE);
276                     break;
277                 case OFPTFPTAPPLYSETFIELDMISS:
278                     writeOxmRelatedTableProperty(tableFeatureBuff, tableFeatureProp, APPLY_SETFIELD_MISS_CODE);
279                     break;
280                 case OFPTFPTEXPERIMENTER:
281                     writeExperimenterRelatedTableProperty(tableFeatureBuff, tableFeatureProp);
282                     break;
283                 case OFPTFPTEXPERIMENTERMISS:
284                     writeExperimenterRelatedTableProperty(tableFeatureBuff, tableFeatureProp);
285                     break;
286                 }
287             }
288             tableFeatureBuff.setShort(TABLE_FEATURES_LENGTH_INDEX, tableFeatureBuff.readableBytes());
289             outBuffer.writeBytes(tableFeatureBuff);
290         }
291     }
292
293     private void writeExperimenterRelatedTableProperty(final ByteBuf output, final TableFeatureProperties property) {
294         long expId = property.getAugmentation(ExperimenterIdTableFeatureProperty.class).getExperimenter().getValue();
295         OFSerializer<TableFeatureProperties> serializer = registry.getSerializer(ExperimenterSerializerKeyFactory
296                 .createMultipartRequestTFSerializerKey(EncodeConstants.OF13_VERSION_ID, expId));
297         serializer.serialize(property, output);
298     }
299
300     private void writeOxmRelatedTableProperty(final ByteBuf output, final TableFeatureProperties property,
301             final byte code) {
302         int startIndex = output.writerIndex();
303         output.writeShort(code);
304         int lengthIndex = output.writerIndex();
305         output.writeShort(EncodeConstants.EMPTY_LENGTH);
306         List<MatchEntry> entries = property.getAugmentation(OxmRelatedTableFeatureProperty.class).getMatchEntry();
307         if (entries != null) {
308             TypeKeyMaker<MatchEntry> keyMaker = TypeKeyMakerFactory
309                     .createMatchEntriesKeyMaker(EncodeConstants.OF13_VERSION_ID);
310             ListSerializer.serializeHeaderList(entries, keyMaker, registry, output);
311         }
312         int length = output.writerIndex() - startIndex;
313         output.setShort(lengthIndex, length);
314         output.writeZero(paddingNeeded(length));
315     }
316
317     private void writeActionsRelatedTableProperty(final ByteBuf output, final TableFeatureProperties property,
318             final byte code) {
319         int startIndex = output.writerIndex();
320         output.writeShort(code);
321         int lengthIndex = output.writerIndex();
322         output.writeShort(EncodeConstants.EMPTY_LENGTH);
323         List<Action> actions = property.getAugmentation(ActionRelatedTableFeatureProperty.class).getAction();
324         if (actions != null) {
325             TypeKeyMaker<Action> keyMaker = TypeKeyMakerFactory.createActionKeyMaker(EncodeConstants.OF13_VERSION_ID);
326             ListSerializer.serializeHeaderList(actions, keyMaker, registry, output);
327         }
328         int length = output.writerIndex() - startIndex;
329         output.setShort(lengthIndex, length);
330         output.writeZero(paddingNeeded(length));
331     }
332
333     private static void writeNextTableRelatedTableProperty(final ByteBuf output, final TableFeatureProperties property,
334             final byte code) {
335         int startIndex = output.writerIndex();
336         output.writeShort(code);
337         int lengthIndex = output.writerIndex();
338         output.writeShort(EncodeConstants.EMPTY_LENGTH);
339         List<NextTableIds> nextTableIds = property.getAugmentation(NextTableRelatedTableFeatureProperty.class)
340                 .getNextTableIds();
341         if (nextTableIds != null) {
342             for (NextTableIds next : nextTableIds) {
343                 output.writeByte(next.getTableId());
344             }
345         }
346         int length = output.writerIndex() - startIndex;
347         output.setShort(lengthIndex, length);
348         output.writeZero(paddingNeeded(length));
349     }
350
351     private void writeInstructionRelatedTableProperty(final ByteBuf output, final TableFeatureProperties property,
352             final byte code) {
353         int startIndex = output.writerIndex();
354         output.writeShort(code);
355         int lengthIndex = output.writerIndex();
356         output.writeShort(EncodeConstants.EMPTY_LENGTH);
357         List<Instruction> instructions = property.getAugmentation(InstructionRelatedTableFeatureProperty.class)
358                 .getInstruction();
359         if (instructions != null) {
360             TypeKeyMaker<Instruction> keyMaker = TypeKeyMakerFactory
361                     .createInstructionKeyMaker(EncodeConstants.OF13_VERSION_ID);
362             ListSerializer.serializeHeaderList(instructions, keyMaker, registry, output);
363         }
364         int length = output.writerIndex() - startIndex;
365         output.setShort(lengthIndex, length);
366         output.writeZero(paddingNeeded(length));
367     }
368
369     private static int paddingNeeded(final int length) {
370         int paddingRemainder = length % EncodeConstants.PADDING;
371         int result = 0;
372         if (paddingRemainder != 0) {
373             result = EncodeConstants.PADDING - paddingRemainder;
374         }
375         return result;
376     }
377
378     private void writeTableConfig(TableConfig tableConfig, ByteBuf outBuffer) {
379         Map<Integer, Boolean> map = new HashMap<>();
380         map.put(0, tableConfig.isOFPTCDEPRECATEDMASK());
381         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
382         outBuffer.writeInt(bitmap);
383     }
384
385     private void serializeMeterFeaturesBody(MultipartReplyBody body, ByteBuf outBuffer) {
386         MultipartReplyMeterFeaturesCase meterFeaturesCase = (MultipartReplyMeterFeaturesCase) body;
387         MultipartReplyMeterFeatures meterFeatures = meterFeaturesCase.getMultipartReplyMeterFeatures();
388         outBuffer.writeInt(meterFeatures.getMaxMeter().intValue());
389         writeBandTypes(meterFeatures.getBandTypes(), outBuffer);
390         writeMeterFlags(meterFeatures.getCapabilities(), outBuffer);
391         outBuffer.writeByte(meterFeatures.getMaxBands());
392         outBuffer.writeByte(meterFeatures.getMaxColor());
393         outBuffer.writeZero(METER_FEATURES_PADDING);
394     }
395
396     private void writeBandTypes(MeterBandTypeBitmap bandTypes, ByteBuf outBuffer) {
397         Map<Integer, Boolean> map = new HashMap<>();
398         map.put(0, bandTypes.isOFPMBTDROP());
399         map.put(1, bandTypes.isOFPMBTDSCPREMARK());
400         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
401         outBuffer.writeInt(bitmap);
402     }
403
404     private void serializeMeterConfigBody(MultipartReplyBody body, ByteBuf outBuffer) {
405         MultipartReplyMeterConfigCase meterConfigCase = (MultipartReplyMeterConfigCase) body;
406         MultipartReplyMeterConfig meter = meterConfigCase.getMultipartReplyMeterConfig();
407         for (MeterConfig meterConfig : meter.getMeterConfig()) {
408             ByteBuf meterConfigBuff = UnpooledByteBufAllocator.DEFAULT.buffer();
409             meterConfigBuff.writeShort(EncodeConstants.EMPTY_LENGTH);
410             writeMeterFlags(meterConfig.getFlags(), meterConfigBuff);
411             meterConfigBuff.writeInt(meterConfig.getMeterId().getValue().intValue());
412             for (Bands currentBand : meterConfig.getBands()) {
413                 MeterBand meterBand = currentBand.getMeterBand();
414                 if (meterBand instanceof MeterBandDropCase) {
415                     MeterBandDropCase dropBandCase = (MeterBandDropCase) meterBand;
416                     MeterBandDrop dropBand = dropBandCase.getMeterBandDrop();
417                     writeBandCommonFields(dropBand, meterConfigBuff);
418                 } else if (meterBand instanceof MeterBandDscpRemarkCase) {
419                     MeterBandDscpRemarkCase dscpRemarkBandCase = (MeterBandDscpRemarkCase) meterBand;
420                     MeterBandDscpRemark dscpRemarkBand = dscpRemarkBandCase.getMeterBandDscpRemark();
421                     writeBandCommonFields(dscpRemarkBand, meterConfigBuff);
422                 } else if (meterBand instanceof MeterBandExperimenterCase) {
423                     MeterBandExperimenterCase experimenterBandCase = (MeterBandExperimenterCase) meterBand;
424                     MeterBandExperimenter experimenterBand = experimenterBandCase.getMeterBandExperimenter();
425                     writeBandCommonFields(experimenterBand, meterConfigBuff);
426                 }
427             }
428             meterConfigBuff.setShort(METER_CONFIG_LENGTH_INDEX, meterConfigBuff.readableBytes());
429             outBuffer.writeBytes(meterConfigBuff);
430         }
431     }
432
433     private static void writeBandCommonFields(final MeterBandCommons meterBand, final ByteBuf outBuffer) {
434         outBuffer.writeShort(meterBand.getType().getIntValue());
435         outBuffer.writeShort(LENGTH_OF_METER_BANDS);
436         outBuffer.writeInt(meterBand.getRate().intValue());
437         outBuffer.writeInt(meterBand.getBurstSize().intValue());
438     }
439
440     private void writeMeterFlags(MeterFlags flags, ByteBuf outBuffer) {
441         Map<Integer, Boolean> map = new HashMap<>();
442         map.put(0, flags.isOFPMFKBPS());
443         map.put(1, flags.isOFPMFPKTPS());
444         map.put(2, flags.isOFPMFBURST());
445         map.put(3, flags.isOFPMFSTATS());
446         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
447         outBuffer.writeShort(bitmap);
448     }
449
450     private void serializeMeterBody(MultipartReplyBody body, ByteBuf outBuffer) {
451         MultipartReplyMeterCase meterCase = (MultipartReplyMeterCase) body;
452         MultipartReplyMeter meter = meterCase.getMultipartReplyMeter();
453         for (MeterStats meterStats : meter.getMeterStats()) {
454             ByteBuf meterStatsBuff = UnpooledByteBufAllocator.DEFAULT.buffer();
455             meterStatsBuff.writeInt(meterStats.getMeterId().getValue().intValue());
456             meterStatsBuff.writeInt(EncodeConstants.EMPTY_LENGTH);
457             meterStatsBuff.writeZero(METER_PADDING);
458             meterStatsBuff.writeInt(meterStats.getFlowCount().intValue());
459             meterStatsBuff.writeLong(meterStats.getPacketInCount().longValue());
460             meterStatsBuff.writeLong(meterStats.getByteInCount().longValue());
461             meterStatsBuff.writeInt(meterStats.getDurationSec().intValue());
462             meterStatsBuff.writeInt(meterStats.getDurationNsec().intValue());
463             for (MeterBandStats meterBandStats : meterStats.getMeterBandStats()) {
464                 meterStatsBuff.writeLong(meterBandStats.getPacketBandCount().longValue());
465                 meterStatsBuff.writeLong(meterBandStats.getByteBandCount().longValue());
466             }
467             meterStatsBuff.setInt(METER_LENGTH_INDEX, meterStatsBuff.readableBytes());
468             outBuffer.writeBytes(meterStatsBuff);
469         }
470     }
471
472     private void serializeGroupFeaturesBody(MultipartReplyBody body, ByteBuf outBuffer) {
473         MultipartReplyGroupFeaturesCase groupFeaturesCase = (MultipartReplyGroupFeaturesCase) body;
474         MultipartReplyGroupFeatures groupFeatures = groupFeaturesCase.getMultipartReplyGroupFeatures();
475         writeGroupTypes(groupFeatures.getTypes(), outBuffer);
476         writeGroupCapabilities(groupFeatures.getCapabilities(), outBuffer);
477         for (Long maxGroups : groupFeatures.getMaxGroups()) {
478             outBuffer.writeInt(maxGroups.intValue());
479         }
480         for (ActionType action : groupFeatures.getActionsBitmap()) {
481             writeActionType(action, outBuffer);
482         }
483     }
484
485     private void writeActionType(ActionType action, ByteBuf outBuffer) {
486         Map<Integer, Boolean> map = new HashMap<>();
487         map.put(0, action.isOFPATOUTPUT());
488         map.put(1, action.isOFPATCOPYTTLOUT());
489         map.put(2, action.isOFPATCOPYTTLIN());
490         map.put(3, action.isOFPATSETMPLSTTL());
491         map.put(4, action.isOFPATDECMPLSTTL());
492         map.put(5, action.isOFPATPUSHVLAN());
493         map.put(6, action.isOFPATPOPVLAN());
494         map.put(7, action.isOFPATPUSHMPLS());
495         map.put(8, action.isOFPATPOPMPLS());
496         map.put(9, action.isOFPATSETQUEUE());
497         map.put(10, action.isOFPATGROUP());
498         map.put(11, action.isOFPATSETNWTTL());
499         map.put(12, action.isOFPATDECNWTTL());
500         map.put(13, action.isOFPATSETFIELD());
501         map.put(14, action.isOFPATPUSHPBB());
502         map.put(15, action.isOFPATPOPPBB());
503         map.put(16, action.isOFPATEXPERIMENTER());
504         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
505         outBuffer.writeInt(bitmap);
506     }
507
508     private void writeGroupCapabilities(GroupCapabilities capabilities, ByteBuf outBuffer) {
509         Map<Integer, Boolean> map = new HashMap<>();
510         map.put(0, capabilities.isOFPGFCSELECTWEIGHT());
511         map.put(1, capabilities.isOFPGFCSELECTLIVENESS());
512         map.put(2, capabilities.isOFPGFCCHAINING());
513         map.put(3, capabilities.isOFPGFCCHAININGCHECKS());
514         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
515         outBuffer.writeInt(bitmap);
516     }
517
518     private void writeGroupTypes(GroupTypes types, ByteBuf outBuffer) {
519         Map<Integer, Boolean> map = new HashMap<>();
520         map.put(0, types.isOFPGTALL());
521         map.put(1, types.isOFPGTSELECT());
522         map.put(2, types.isOFPGTINDIRECT());
523         map.put(3, types.isOFPGTFF());
524         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
525         outBuffer.writeInt(bitmap);
526     }
527
528     private void serializeGroupDescBody(MultipartReplyBody body, ByteBuf outBuffer, MultipartReplyMessage message) {
529         MultipartReplyGroupDescCase groupDescCase = (MultipartReplyGroupDescCase) body;
530         MultipartReplyGroupDesc group = groupDescCase.getMultipartReplyGroupDesc();
531         for (GroupDesc groupDesc : group.getGroupDesc()) {
532             ByteBuf groupDescBuff = UnpooledByteBufAllocator.DEFAULT.buffer();
533             groupDescBuff.writeShort(EncodeConstants.EMPTY_LENGTH);
534             groupDescBuff.writeByte(groupDesc.getType().getIntValue());
535             groupDescBuff.writeZero(GROUP_DESC_PADDING);
536             groupDescBuff.writeInt(groupDesc.getGroupId().getValue().intValue());
537             for (BucketsList bucket : groupDesc.getBucketsList()) {
538                 ByteBuf bucketBuff = UnpooledByteBufAllocator.DEFAULT.buffer();
539                 bucketBuff.writeShort(EncodeConstants.EMPTY_LENGTH);
540                 bucketBuff.writeShort(bucket.getWeight());
541                 bucketBuff.writeInt(bucket.getWatchPort().getValue().intValue());
542                 bucketBuff.writeInt(bucket.getWatchGroup().intValue());
543                 bucketBuff.writeZero(BUCKET_PADDING);
544                 ListSerializer.serializeList(bucket.getAction(),
545                         TypeKeyMakerFactory.createActionKeyMaker(message.getVersion()), registry, bucketBuff);
546                 bucketBuff.setShort(BUCKET_LENGTH_INDEX, bucketBuff.readableBytes());
547                 groupDescBuff.writeBytes(bucketBuff);
548             }
549             groupDescBuff.setShort(GROUP_DESC_LENGTH_INDEX, groupDescBuff.readableBytes());
550             outBuffer.writeBytes(groupDescBuff);
551         }
552     }
553
554     private void serializeGroupBody(MultipartReplyBody body, ByteBuf outBuffer) {
555         MultipartReplyGroupCase groupCase = (MultipartReplyGroupCase) body;
556         MultipartReplyGroup group = groupCase.getMultipartReplyGroup();
557         for (GroupStats groupStats : group.getGroupStats()) {
558             ByteBuf groupStatsBuff = UnpooledByteBufAllocator.DEFAULT.buffer();
559             groupStatsBuff.writeShort(EncodeConstants.EMPTY_LENGTH);
560             groupStatsBuff.writeZero(GROUP_STATS_PADDING_1);
561             groupStatsBuff.writeInt(groupStats.getGroupId().getValue().intValue());
562             groupStatsBuff.writeInt(groupStats.getRefCount().intValue());
563             groupStatsBuff.writeZero(GROUP_STATS_PADDING_2);
564             groupStatsBuff.writeLong(groupStats.getPacketCount().longValue());
565             groupStatsBuff.writeLong(groupStats.getByteCount().longValue());
566             groupStatsBuff.writeInt(groupStats.getDurationSec().intValue());
567             groupStatsBuff.writeInt(groupStats.getDurationNsec().intValue());
568             for (BucketStats bucketStats : groupStats.getBucketStats()) {
569                 groupStatsBuff.writeLong(bucketStats.getPacketCount().longValue());
570                 groupStatsBuff.writeLong(bucketStats.getByteCount().longValue());
571             }
572             groupStatsBuff.setShort(GROUP_STATS_LENGTH_INDEX, groupStatsBuff.readableBytes());
573             outBuffer.writeBytes(groupStatsBuff);
574         }
575     }
576
577     private void serializeQueueBody(MultipartReplyBody body, ByteBuf outBuffer) {
578         MultipartReplyQueueCase queueCase = (MultipartReplyQueueCase) body;
579         MultipartReplyQueue queue = queueCase.getMultipartReplyQueue();
580         for (QueueStats queueStats : queue.getQueueStats()) {
581             outBuffer.writeInt(queueStats.getPortNo().intValue());
582             outBuffer.writeInt(queueStats.getQueueId().intValue());
583             outBuffer.writeLong(queueStats.getTxBytes().longValue());
584             outBuffer.writeLong(queueStats.getTxPackets().longValue());
585             outBuffer.writeLong(queueStats.getTxErrors().longValue());
586             outBuffer.writeInt(queueStats.getDurationSec().intValue());
587             outBuffer.writeInt(queueStats.getDurationNsec().intValue());
588         }
589     }
590
591     private void serializePortStatsBody(MultipartReplyBody body, ByteBuf outBuffer) {
592         MultipartReplyPortStatsCase portStatsCase = (MultipartReplyPortStatsCase) body;
593         MultipartReplyPortStats portStats = portStatsCase.getMultipartReplyPortStats();
594         for (PortStats portStat : portStats.getPortStats()) {
595             outBuffer.writeInt(portStat.getPortNo().intValue());
596             outBuffer.writeZero(PORT_STATS_PADDING);
597             outBuffer.writeLong(portStat.getRxPackets().longValue());
598             outBuffer.writeLong(portStat.getTxPackets().longValue());
599             outBuffer.writeLong(portStat.getRxBytes().longValue());
600             outBuffer.writeLong(portStat.getTxBytes().longValue());
601             outBuffer.writeLong(portStat.getRxDropped().longValue());
602             outBuffer.writeLong(portStat.getTxDropped().longValue());
603             outBuffer.writeLong(portStat.getRxErrors().longValue());
604             outBuffer.writeLong(portStat.getTxErrors().longValue());
605             outBuffer.writeLong(portStat.getRxFrameErr().longValue());
606             outBuffer.writeLong(portStat.getRxOverErr().longValue());
607             outBuffer.writeLong(portStat.getRxCrcErr().longValue());
608             outBuffer.writeLong(portStat.getCollisions().longValue());
609             outBuffer.writeInt(portStat.getDurationSec().intValue());
610             outBuffer.writeInt(portStat.getDurationNsec().intValue());
611         }
612     }
613
614     private void serializeTableBody(MultipartReplyBody body, ByteBuf outBuffer) {
615         MultipartReplyTableCase tableCase = (MultipartReplyTableCase) body;
616         MultipartReplyTable table = tableCase.getMultipartReplyTable();
617         for (TableStats tableStats : table.getTableStats()) {
618             outBuffer.writeByte(tableStats.getTableId());
619             outBuffer.writeZero(TABLE_PADDING);
620             outBuffer.writeInt(tableStats.getActiveCount().intValue());
621             outBuffer.writeLong(tableStats.getLookupCount().longValue());
622             outBuffer.writeLong(tableStats.getMatchedCount().longValue());
623         }
624     }
625
626     private void serializeAggregateBody(MultipartReplyBody body, ByteBuf outBuffer) {
627         MultipartReplyAggregateCase aggregateCase = (MultipartReplyAggregateCase) body;
628         MultipartReplyAggregate aggregate = aggregateCase.getMultipartReplyAggregate();
629         outBuffer.writeLong(aggregate.getPacketCount().longValue());
630         outBuffer.writeLong(aggregate.getByteCount().longValue());
631         outBuffer.writeInt(aggregate.getFlowCount().intValue());
632         outBuffer.writeZero(AGGREGATE_PADDING);
633     }
634
635     private void serializeFlowBody(MultipartReplyBody body, ByteBuf outBuffer, MultipartReplyMessage message) {
636         MultipartReplyFlowCase flowCase = (MultipartReplyFlowCase) body;
637         MultipartReplyFlow flow = flowCase.getMultipartReplyFlow();
638         for (FlowStats flowStats : flow.getFlowStats()) {
639             ByteBuf flowStatsBuff = UnpooledByteBufAllocator.DEFAULT.buffer();
640             flowStatsBuff.writeShort(EncodeConstants.EMPTY_LENGTH);
641             flowStatsBuff.writeByte(new Long(flowStats.getTableId()).byteValue());
642             flowStatsBuff.writeZero(FLOW_STATS_PADDING_1);
643             flowStatsBuff.writeInt(flowStats.getDurationSec().intValue());
644             flowStatsBuff.writeInt(flowStats.getDurationNsec().intValue());
645             flowStatsBuff.writeShort(flowStats.getPriority());
646             flowStatsBuff.writeShort(flowStats.getIdleTimeout());
647             flowStatsBuff.writeShort(flowStats.getHardTimeout());
648             flowStatsBuff.writeZero(FLOW_STATS_PADDING_2);
649             flowStatsBuff.writeLong(flowStats.getCookie().longValue());
650             flowStatsBuff.writeLong(flowStats.getPacketCount().longValue());
651             flowStatsBuff.writeLong(flowStats.getByteCount().longValue());
652             OFSerializer<Match> matchSerializer = registry.<Match, OFSerializer<Match>> getSerializer(
653                     new MessageTypeKey<>(message.getVersion(), Match.class));
654             matchSerializer.serialize(flowStats.getMatch(), flowStatsBuff);
655             ListSerializer.serializeList(flowStats.getInstruction(),
656                     TypeKeyMakerFactory.createInstructionKeyMaker(message.getVersion()), registry, flowStatsBuff);
657
658             flowStatsBuff.setShort(FLOW_STATS_LENGTH_INDEX, flowStatsBuff.readableBytes());
659             outBuffer.writeBytes(flowStatsBuff);
660         }
661     }
662
663     private void serializeDescBody(MultipartReplyBody body, ByteBuf outBuffer) {
664         MultipartReplyDescCase descCase = (MultipartReplyDescCase) body;
665         MultipartReplyDesc desc = descCase.getMultipartReplyDesc();
666         write256String(desc.getMfrDesc(), outBuffer);
667         write256String(desc.getHwDesc(), outBuffer);
668         write256String(desc.getSwDesc(), outBuffer);
669         write32String(desc.getSerialNum(), outBuffer);
670         write256String(desc.getDpDesc(), outBuffer);
671     }
672
673     private void write256String(String toWrite, ByteBuf outBuffer) {
674         byte[] nameBytes = toWrite.getBytes();
675         if (nameBytes.length < 256) {
676             byte[] nameBytesPadding = new byte[256];
677             int i = 0;
678             for (byte b : nameBytes) {
679                 nameBytesPadding[i] = b;
680                 i++;
681             }
682             for (; i < 256; i++) {
683                 nameBytesPadding[i] = 0x0;
684             }
685             outBuffer.writeBytes(nameBytesPadding);
686         } else {
687             outBuffer.writeBytes(nameBytes);
688         }
689     }
690
691     private void write32String(String toWrite, ByteBuf outBuffer) {
692         byte[] nameBytes = toWrite.getBytes();
693         if (nameBytes.length < 32) {
694             byte[] nameBytesPadding = new byte[32];
695             int i = 0;
696             for (byte b : nameBytes) {
697                 nameBytesPadding[i] = b;
698                 i++;
699             }
700             for (; i < 32; i++) {
701                 nameBytesPadding[i] = 0x0;
702             }
703             outBuffer.writeBytes(nameBytesPadding);
704         } else {
705             outBuffer.writeBytes(nameBytes);
706         }
707     }
708
709     private void serializePortDescBody(MultipartReplyBody body, ByteBuf outBuffer) {
710         MultipartReplyPortDescCase portCase = (MultipartReplyPortDescCase) body;
711         MultipartReplyPortDesc portDesc = portCase.getMultipartReplyPortDesc();
712         for (Ports port : portDesc.getPorts()) {
713             outBuffer.writeInt(port.getPortNo().intValue()); // Assuming PortNo
714                                                              // = PortId
715             outBuffer.writeZero(PORT_DESC_PADDING_1);
716             writeMacAddress(port.getHwAddr().getValue(), outBuffer);
717             outBuffer.writeZero(PORT_DESC_PADDING_2);
718             writeName(port.getName(), outBuffer);
719             writePortConfig(port.getConfig(), outBuffer);
720             writePortState(port.getState(), outBuffer);
721             writePortFeatures(port.getCurrentFeatures(), outBuffer);
722             writePortFeatures(port.getAdvertisedFeatures(), outBuffer);
723             writePortFeatures(port.getSupportedFeatures(), outBuffer);
724             writePortFeatures(port.getPeerFeatures(), outBuffer);
725             outBuffer.writeInt(port.getCurrSpeed().intValue());
726             outBuffer.writeInt(port.getMaxSpeed().intValue());
727         }
728     }
729
730     private void writeName(String name, ByteBuf outBuffer) {
731         byte[] nameBytes = name.getBytes();
732         if (nameBytes.length < 16) {
733             byte[] nameBytesPadding = new byte[16];
734             int i = 0;
735             for (byte b : nameBytes) {
736                 nameBytesPadding[i] = b;
737                 i++;
738             }
739             for (; i < 16; i++) {
740                 nameBytesPadding[i] = 0x0;
741             }
742             outBuffer.writeBytes(nameBytesPadding);
743         } else {
744             outBuffer.writeBytes(nameBytes);
745         }
746
747     }
748
749     private void writeMacAddress(String macAddress, ByteBuf outBuffer) {
750         String[] macAddressParts = macAddress.split(":");
751         byte[] macAddressBytes = new byte[6];
752         for (int i = 0; i < 6; i++) {
753             Integer hex = Integer.parseInt(macAddressParts[i], 16);
754             macAddressBytes[i] = hex.byteValue();
755         }
756         outBuffer.writeBytes(macAddressBytes);
757     }
758
759     private void writePortConfig(PortConfig config, ByteBuf outBuffer) {
760         Map<Integer, Boolean> map = new HashMap<>();
761         map.put(0, config.isPortDown());
762         map.put(2, config.isNoRecv());
763         map.put(5, config.isNoFwd());
764         map.put(6, config.isNoPacketIn());
765         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
766         outBuffer.writeInt(bitmap);
767     }
768
769     private void writePortState(PortState state, ByteBuf outBuffer) {
770         Map<Integer, Boolean> map = new HashMap<>();
771         map.put(0, state.isLinkDown());
772         map.put(1, state.isBlocked());
773         map.put(2, state.isLive());
774         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
775         outBuffer.writeInt(bitmap);
776     }
777
778     private void writePortFeatures(PortFeatures features, ByteBuf outBuffer) {
779         Map<Integer, Boolean> map = new HashMap<>();
780         map.put(0, features.is_10mbHd());
781         map.put(1, features.is_10mbFd());
782         map.put(2, features.is_100mbHd());
783         map.put(3, features.is_100mbFd());
784         map.put(4, features.is_1gbHd());
785         map.put(5, features.is_1gbFd());
786         map.put(6, features.is_10gbFd());
787         map.put(7, features.is_40gbFd());
788         map.put(8, features.is_100gbFd());
789         map.put(9, features.is_1tbFd());
790         map.put(10, features.isOther());
791         map.put(11, features.isCopper());
792         map.put(12, features.isFiber());
793         map.put(13, features.isAutoneg());
794         map.put(14, features.isPause());
795         map.put(15, features.isPauseAsym());
796         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
797         outBuffer.writeInt(bitmap);
798     }
799 }