OpenFlow 1.0 support completed
[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             encodeQueueBody(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 encodeQueueBody(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         output.writeBytes(experimenter.getData());\r
181     }\r
182     \r
183     private static void encodeTableFeaturesBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
184         if (multipartRequestBody != null) {\r
185             MultipartRequestTableFeatures tableFeatures = (MultipartRequestTableFeatures) multipartRequestBody;\r
186             for (TableFeatures currTableFeature : tableFeatures.getTableFeatures()) {\r
187                 final byte PADDING_IN_MULTIPART_REQUEST_TABLE_FEATURES_BODY = 5;\r
188                 output.writeByte(currTableFeature.getTableId());\r
189                 ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_TABLE_FEATURES_BODY, output);\r
190                 output.writeBytes(currTableFeature.getName().getBytes());\r
191                 ByteBufUtils.padBuffer((32 - currTableFeature.getName().getBytes().length), output);\r
192                 output.writeLong(currTableFeature.getMetadataMatch().longValue());\r
193                 output.writeLong(currTableFeature.getMetadataWrite().longValue());\r
194                 output.writeInt(createTableConfigBitmask(currTableFeature.getConfig()));\r
195                 output.writeInt(currTableFeature.getMaxEntries().intValue());\r
196                 writeTableFeatureProperties(output, currTableFeature.getTableFeatureProperties());\r
197             }\r
198         }\r
199     }\r
200     \r
201     private static void writeTableFeatureProperties(ByteBuf output, List<TableFeatureProperties> props) {\r
202         if (props != null) {\r
203             for (TableFeatureProperties property : props) {\r
204                 TableFeaturesPropType type = property.getType();\r
205                 if (type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONS)) {\r
206                     final byte INSTRUCTIONS_CODE = 0;\r
207                     writeInstructionRelatedTableProperty(output, property, INSTRUCTIONS_CODE);\r
208                 } else if (type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONSMISS)) {\r
209                     final byte INSTRUCTIONS_MISS_CODE = 1;\r
210                     writeInstructionRelatedTableProperty(output, property, INSTRUCTIONS_MISS_CODE);\r
211                 } else if (type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLES)) {\r
212                     final byte NEXT_TABLE_CODE = 2;\r
213                     writeNextTableRelatedTableProperty(output, property, NEXT_TABLE_CODE);\r
214                 } else if (type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLESMISS)) {\r
215                     final byte NEXT_TABLE_MISS_CODE = 3;\r
216                     writeNextTableRelatedTableProperty(output, property, NEXT_TABLE_MISS_CODE);\r
217                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITEACTIONS)) {\r
218                     final byte WRITE_ACTIONS_CODE = 4;\r
219                     writeActionsRelatedTableProperty(output, property, WRITE_ACTIONS_CODE);\r
220                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITEACTIONSMISS)) {\r
221                     final byte WRITE_ACTIONS_MISS_CODE = 5;\r
222                     writeActionsRelatedTableProperty(output, property, WRITE_ACTIONS_MISS_CODE);\r
223                 } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONS)) {\r
224                     final byte APPLY_ACTIONS_CODE = 6;\r
225                     writeActionsRelatedTableProperty(output, property, APPLY_ACTIONS_CODE);\r
226                 } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONSMISS)) {\r
227                     final byte APPLY_ACTIONS_MISS_CODE = 7;\r
228                     writeActionsRelatedTableProperty(output, property, APPLY_ACTIONS_MISS_CODE);\r
229                 } else if (type.equals(TableFeaturesPropType.OFPTFPTMATCH)) {\r
230                     final byte MATCH_CODE = 8;\r
231                     writeOxmRelatedTableProperty(output, property, MATCH_CODE);\r
232                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWILDCARDS)) {\r
233                     final byte WILDCARDS_CODE = 10;\r
234                     writeOxmRelatedTableProperty(output, property, WILDCARDS_CODE);\r
235                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITESETFIELD)) {\r
236                     final byte WRITE_SETFIELD_CODE = 12;\r
237                     writeOxmRelatedTableProperty(output, property, WRITE_SETFIELD_CODE);\r
238                 } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITESETFIELDMISS)) {\r
239                     final byte WRITE_SETFIELD_MISS_CODE = 13;\r
240                     writeOxmRelatedTableProperty(output, property, WRITE_SETFIELD_MISS_CODE);\r
241                 } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELD)) {\r
242                     final byte APPLY_SETFIELD_CODE = 14;\r
243                     writeOxmRelatedTableProperty(output, property, APPLY_SETFIELD_CODE);\r
244                 } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELDMISS)) {\r
245                     final byte APPLY_SETFIELD_MISS_CODE = 15;\r
246                     writeOxmRelatedTableProperty(output, property, APPLY_SETFIELD_MISS_CODE);\r
247                 } else if (type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTER)) {\r
248                     final int EXPERIMENTER_CODE = 65534; // 0xFFFE\r
249                     writeExperimenterRelatedTableProperty(output, property, EXPERIMENTER_CODE);\r
250                 } else if (type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTERMISS)) {\r
251                     final int EXPERIMENTER_MISS_CODE = 65535; // 0xFFFF\r
252                     writeExperimenterRelatedTableProperty(output, property, EXPERIMENTER_MISS_CODE);\r
253                 } \r
254             }\r
255         }\r
256     }\r
257 \r
258     private static void writeInstructionRelatedTableProperty(ByteBuf output,\r
259             TableFeatureProperties property, byte code) {\r
260         output.writeShort(code);\r
261         List<Instructions> instructions = property.\r
262                 getAugmentation(InstructionRelatedTableFeatureProperty.class).getInstructions();\r
263         int length = TABLE_FEAT_HEADER_LENGTH;\r
264         if (instructions != null) {\r
265         output.writeShort(InstructionsSerializer.computeInstructionsLength(instructions)\r
266                 + TABLE_FEAT_HEADER_LENGTH);\r
267         InstructionsSerializer.encodeInstructions(instructions, output);\r
268         } else {\r
269             output.writeShort(length);\r
270         }\r
271     }\r
272     \r
273     private static void writeNextTableRelatedTableProperty(ByteBuf output,\r
274             TableFeatureProperties property, byte code) {\r
275         output.writeShort(code);\r
276         List<NextTableIds> nextTableIds = property.\r
277                 getAugmentation(NextTableRelatedTableFeatureProperty.class).getNextTableIds();\r
278         int length = TABLE_FEAT_HEADER_LENGTH;\r
279         if (nextTableIds != null) {\r
280             output.writeShort(length + nextTableIds.size());\r
281             for (NextTableIds next : nextTableIds) {\r
282                 output.writeByte(next.getTableId());\r
283             }\r
284         } else {\r
285             output.writeShort(length);\r
286         }\r
287     }\r
288     \r
289     private static void writeActionsRelatedTableProperty(ByteBuf output,\r
290             TableFeatureProperties property, byte code) {\r
291         output.writeShort(code);\r
292         List<ActionsList> actions = property.\r
293                 getAugmentation(ActionRelatedTableFeatureProperty.class).getActionsList();\r
294         int length = TABLE_FEAT_HEADER_LENGTH;\r
295         if (actions != null) {\r
296         output.writeShort(ActionsSerializer.computeLengthOfActions(actions)\r
297                 + TABLE_FEAT_HEADER_LENGTH);\r
298         ActionsSerializer.encodeActions(actions, output);\r
299         } else {\r
300             output.writeShort(length);\r
301         }\r
302     }\r
303     \r
304     private static void writeOxmRelatedTableProperty(ByteBuf output,\r
305             TableFeatureProperties property, byte code) {\r
306         output.writeShort(code);\r
307         List<MatchEntries> entries = property.\r
308                 getAugmentation(OxmRelatedTableFeatureProperty.class).getMatchEntries();\r
309         int length = TABLE_FEAT_HEADER_LENGTH;\r
310         if (entries != null) {\r
311         output.writeShort(MatchSerializer.computeMatchEntriesLength(entries)\r
312                 + TABLE_FEAT_HEADER_LENGTH);\r
313         MatchSerializer.encodeMatchEntries(entries, output);\r
314         } else {\r
315             output.writeShort(length);\r
316         }\r
317     }\r
318     \r
319     private static void writeExperimenterRelatedTableProperty(ByteBuf output,\r
320             TableFeatureProperties property, int code) {\r
321         output.writeShort(code);\r
322         ExperimenterRelatedTableFeatureProperty exp = property.\r
323                 getAugmentation(ExperimenterRelatedTableFeatureProperty.class);\r
324         byte[] data = exp.getData();\r
325         int length = TABLE_FEAT_HEADER_LENGTH + 2 * (Integer.SIZE / Byte.SIZE);\r
326         if (data != null) {\r
327             output.writeShort(length + data.length);\r
328             output.writeInt(exp.getExperimenter().intValue());\r
329             output.writeInt(exp.getExpType().intValue());\r
330             output.writeBytes(data);\r
331         } else {\r
332             output.writeShort(length);\r
333             output.writeInt(exp.getExperimenter().intValue());\r
334             output.writeInt(exp.getExpType().intValue());\r
335         }\r
336     }\r
337     \r
338     private static int createTableConfigBitmask(TableConfig tableConfig) {\r
339         int tableConfigBitmask = 0;\r
340         Map<Integer, Boolean> tableConfigMap = new HashMap<>();\r
341         tableConfigMap.put(3, tableConfig.isOFPTCDEPRECATEDMASK());\r
342         \r
343         tableConfigBitmask = ByteBufUtils.fillBitMaskFromMap(tableConfigMap);\r
344         return tableConfigBitmask;\r
345     }\r
346 }\r