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