Merge "Add INFO.yaml for openflowplugin"
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / protocol / deserialization / multipart / MultipartReplyTableFeaturesDeserializer.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart;
9
10 import io.netty.buffer.ByteBuf;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.List;
14 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
15 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
16 import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
17 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
18 import org.opendaylight.openflowjava.util.ByteBufUtils;
19 import org.opendaylight.openflowjava.util.ExperimenterDeserializerKeyFactory;
20 import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
21 import org.opendaylight.openflowplugin.impl.protocol.deserialization.util.ActionUtil;
22 import org.opendaylight.openflowplugin.impl.protocol.deserialization.util.InstructionUtil;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesPropType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableConfig;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.set.field.match.SetFieldMatch;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplyActionsBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplyActionsMissBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplySetfieldBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplySetfieldMissBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.InstructionsBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.InstructionsMissBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.MatchBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.NextTableBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.NextTableMissBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WildcardsBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteActionsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteActionsMissBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteSetfieldBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteSetfieldMissBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.match.MatchSetfieldBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.next.table.TablesBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.next.table.miss.TablesMissBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.wildcards.WildcardSetfieldBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.TableProperties;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.TablePropertiesBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.table.properties.TableFeatureProperties;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.table.properties.TableFeaturePropertiesBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.table.properties.TableFeaturePropertiesKey;
59 import org.opendaylight.yangtools.yang.common.Uint8;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 public class MultipartReplyTableFeaturesDeserializer implements OFDeserializer<MultipartReplyBody>,
64         DeserializerRegistryInjector {
65     private static final Logger LOG = LoggerFactory.getLogger(MultipartReplyTableFeaturesDeserializer.class);
66     private static final byte PADDING_IN_MULTIPART_REPLY_TABLE_FEATURES = 5;
67     private static final byte MAX_TABLE_NAME_LENGTH = 32;
68     private static final byte MULTIPART_REPLY_TABLE_FEATURES_STRUCTURE_LENGTH = 64;
69     private static final byte COMMON_PROPERTY_LENGTH = 4;
70     private static final TableFeaturesMatchFieldDeserializer MATCH_FIELD_DESERIALIZER =
71             new TableFeaturesMatchFieldDeserializer();
72
73     private DeserializerRegistry registry;
74
75     @Override
76     public MultipartReplyBody deserialize(final ByteBuf message) {
77         final MultipartReplyTableFeaturesBuilder builder = new MultipartReplyTableFeaturesBuilder();
78         final List<TableFeatures> items = new ArrayList<>();
79
80         while (message.readableBytes() > 0) {
81             final int itemLength = message.readUnsignedShort();
82             final TableFeaturesBuilder itemBuilder = new TableFeaturesBuilder()
83                     .setTableId(message.readUnsignedByte());
84
85             message.skipBytes(PADDING_IN_MULTIPART_REPLY_TABLE_FEATURES);
86
87             final String name = ByteBufUtils.decodeNullTerminatedString(message, MAX_TABLE_NAME_LENGTH);
88             final byte[] match = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
89             message.readBytes(match);
90             final byte[] write = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
91             message.readBytes(write);
92
93             items.add(itemBuilder
94                     .withKey(new TableFeaturesKey(itemBuilder.getTableId()))
95                     .setName(name)
96                     .setMetadataMatch(new BigInteger(1, match))
97                     .setMetadataWrite(new BigInteger(1, write))
98                     .setConfig(readTableConfig(message))
99                     .setMaxEntries(message.readUnsignedInt())
100                     .setTableProperties(readTableProperties(message,
101                             itemLength - MULTIPART_REPLY_TABLE_FEATURES_STRUCTURE_LENGTH))
102                     .build());
103         }
104
105         return builder
106                 .setTableFeatures(items)
107                 .build();
108     }
109
110     private static TableConfig readTableConfig(final ByteBuf message) {
111         final long input = message.readUnsignedInt();
112         final boolean deprecated = (input & 3) != 0;
113
114         return new TableConfig(deprecated);
115     }
116
117     private TableProperties readTableProperties(final ByteBuf message, final int length) {
118         final List<TableFeatureProperties> items = new ArrayList<>();
119         int tableFeaturesLength = length;
120         int order = 0;
121         while (tableFeaturesLength > 0) {
122             final int propStartIndex = message.readerIndex();
123             final TableFeaturesPropType propType = TableFeaturesPropType.forValue(message.readUnsignedShort());
124             int propertyLength = message.readUnsignedShort();
125             final int paddingRemainder = propertyLength % EncodeConstants.PADDING;
126             tableFeaturesLength -= propertyLength;
127             final int commonPropertyLength = propertyLength - COMMON_PROPERTY_LENGTH;
128             final TableFeaturePropertiesBuilder propBuilder = new TableFeaturePropertiesBuilder()
129                 .setOrder(order)
130                 .withKey(new TableFeaturePropertiesKey(order));
131
132             switch (propType) {
133                 case OFPTFPTINSTRUCTIONS:
134                     propBuilder.setTableFeaturePropType(new InstructionsBuilder()
135                             .setInstructions(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
136                                 .rev131026.table.feature.prop.type.table.feature.prop.type.instructions
137                                 .InstructionsBuilder()
138                                 .setInstruction(readInstructions(message, commonPropertyLength))
139                                 .build())
140                             .build());
141                     break;
142                 case OFPTFPTINSTRUCTIONSMISS:
143                     propBuilder.setTableFeaturePropType(new InstructionsMissBuilder()
144                             .setInstructionsMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
145                                 .rev131026.table.feature.prop.type.table.feature.prop.type.instructions.miss
146                                 .InstructionsMissBuilder()
147                                 .setInstruction(readInstructions(message, commonPropertyLength))
148                                 .build())
149                             .build());
150                     break;
151                 case OFPTFPTNEXTTABLES:
152                     propBuilder.setTableFeaturePropType(new NextTableBuilder()
153                             .setTables(new TablesBuilder()
154                                 .setTableIds(readNextTableIds(message, commonPropertyLength))
155                                 .build())
156                             .build());
157                     break;
158                 case OFPTFPTNEXTTABLESMISS:
159                     propBuilder.setTableFeaturePropType(new NextTableMissBuilder()
160                             .setTablesMiss(new TablesMissBuilder()
161                                 .setTableIds(readNextTableIds(message, commonPropertyLength))
162                                 .build())
163                             .build());
164                     break;
165                 case OFPTFPTWRITEACTIONS:
166                     propBuilder.setTableFeaturePropType(new WriteActionsBuilder()
167                             .setWriteActions(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026
168                                 .table.feature.prop.type.table.feature.prop.type.write.actions.WriteActionsBuilder()
169                                 .setAction(readActions(message, commonPropertyLength))
170                                 .build())
171                             .build());
172                     break;
173                 case OFPTFPTWRITEACTIONSMISS:
174                     propBuilder.setTableFeaturePropType(new WriteActionsMissBuilder()
175                             .setWriteActionsMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
176                                 .rev131026.table.feature.prop.type.table.feature.prop.type.write.actions.miss
177                                 .WriteActionsMissBuilder()
178                                 .setAction(readActions(message, commonPropertyLength))
179                                 .build())
180                             .build());
181                     break;
182                 case OFPTFPTAPPLYACTIONS:
183                     propBuilder.setTableFeaturePropType(new ApplyActionsBuilder()
184                             .setApplyActions(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026
185                                 .table.feature.prop.type.table.feature.prop.type.apply.actions.ApplyActionsBuilder()
186                                 .setAction(readActions(message, commonPropertyLength))
187                                 .build())
188                             .build());
189                     break;
190                 case OFPTFPTAPPLYACTIONSMISS:
191                     propBuilder.setTableFeaturePropType(new ApplyActionsMissBuilder()
192                             .setApplyActionsMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
193                                 .rev131026.table.feature.prop.type.table.feature.prop.type.apply.actions.miss
194                                 .ApplyActionsMissBuilder()
195                                 .setAction(readActions(message, commonPropertyLength))
196                                 .build())
197                             .build());
198                     break;
199                 case OFPTFPTMATCH:
200                     propBuilder.setTableFeaturePropType(new MatchBuilder()
201                             .setMatchSetfield(new MatchSetfieldBuilder()
202                                 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
203                                 .build())
204                             .build());
205                     break;
206                 case OFPTFPTWILDCARDS:
207                     propBuilder.setTableFeaturePropType(new WildcardsBuilder()
208                             .setWildcardSetfield(new WildcardSetfieldBuilder()
209                                 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
210                                 .build())
211                             .build());
212                     break;
213                 case OFPTFPTWRITESETFIELD:
214                     propBuilder.setTableFeaturePropType(new WriteSetfieldBuilder()
215                             .setWriteSetfield(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026
216                                 .table.feature.prop.type.table.feature.prop.type.write.setfield.WriteSetfieldBuilder()
217                                 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
218                                 .build())
219                             .build());
220                     break;
221                 case OFPTFPTWRITESETFIELDMISS:
222                     propBuilder.setTableFeaturePropType(new WriteSetfieldMissBuilder()
223                             .setWriteSetfieldMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
224                                 .rev131026.table.feature.prop.type.table.feature.prop.type.write.setfield.miss
225                                 .WriteSetfieldMissBuilder()
226                                 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
227                                 .build())
228                             .build());
229                     break;
230                 case OFPTFPTAPPLYSETFIELD:
231                     propBuilder.setTableFeaturePropType(new ApplySetfieldBuilder()
232                             .setApplySetfield(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026
233                                 .table.feature.prop.type.table.feature.prop.type.apply.setfield.ApplySetfieldBuilder()
234                                 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
235                                 .build())
236                             .build());
237                     break;
238                 case OFPTFPTAPPLYSETFIELDMISS:
239                     propBuilder.setTableFeaturePropType(new ApplySetfieldMissBuilder()
240                             .setApplySetfieldMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
241                                 .rev131026.table.feature.prop.type.table.feature.prop.type.apply.setfield.miss
242                                 .ApplySetfieldMissBuilder()
243                                 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
244                                 .build())
245                             .build());
246                     break;
247                 case OFPTFPTEXPERIMENTER:
248                 case OFPTFPTEXPERIMENTERMISS:
249                     final long expId = message.readUnsignedInt();
250                     message.readerIndex(propStartIndex);
251
252                     final OFDeserializer<TableFeatureProperties> propDeserializer = registry
253                         .getDeserializer(ExperimenterDeserializerKeyFactory
254                                 .createMultipartReplyTFDeserializerKey(EncodeConstants.OF13_VERSION_ID, expId));
255
256                     // TODO: Finish experimenter table features (currently using OFJava deserialization only to skip
257                     // bytes)
258                     propDeserializer.deserialize(message);
259                     LOG.debug("Table feature property type {} is not handled yet.", propType);
260                     break;
261                 default:
262                     // no operation
263             }
264
265
266             if (paddingRemainder != 0) {
267                 message.skipBytes(EncodeConstants.PADDING - paddingRemainder);
268                 tableFeaturesLength -= EncodeConstants.PADDING - paddingRemainder;
269             }
270
271             items.add(propBuilder.build());
272             order++;
273         }
274
275
276         return new TablePropertiesBuilder()
277             .setTableFeatureProperties(items)
278             .build();
279     }
280
281     private static List<SetFieldMatch> readMatchFields(final ByteBuf message, final int length) {
282         final List<SetFieldMatch> matchFields = new ArrayList<>();
283
284         final int startIndex = message.readerIndex();
285
286         while (message.readerIndex() - startIndex < length) {
287             MATCH_FIELD_DESERIALIZER
288                     .deserialize(message)
289                     .map(matchFields::add)
290                     .orElseGet(() -> {
291                         message.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
292                         return Boolean.FALSE;
293                     });
294         }
295
296         return matchFields;
297     }
298
299     private static List<Uint8> readNextTableIds(final ByteBuf message, final int length) {
300         final List<Uint8> tableIds = new ArrayList<>();
301         int nextTableLength = length;
302
303         while (nextTableLength > 0) {
304             tableIds.add(Uint8.valueOf(message.readUnsignedByte()));
305             nextTableLength -= 1;
306         }
307
308         return tableIds;
309     }
310
311     private List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list
312             .Instruction> readInstructions(final ByteBuf message, final int length) {
313
314         final List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list
315                 .Instruction> instructions = new ArrayList<>();
316         final int startIndex = message.readerIndex();
317         int offset = 0;
318
319         while (message.readerIndex() - startIndex < length) {
320             try {
321                 instructions.add(new InstructionBuilder()
322                         .withKey(new InstructionKey(offset))
323                         .setOrder(offset)
324                         .setInstruction(InstructionUtil
325                                 .readInstructionHeader(EncodeConstants.OF13_VERSION_ID, message, registry))
326                         .build());
327
328                 offset++;
329             } catch (ClassCastException | IllegalStateException e) {
330                 message.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
331             }
332         }
333
334         return instructions;
335     }
336
337     @SuppressWarnings("checkstyle:LineLength")
338     private List<Action> readActions(final ByteBuf message, final int length) {
339         final List<Action> actions = new ArrayList<>();
340         final int startIndex = message.readerIndex();
341         int offset = 0;
342
343         while (message.readerIndex() - startIndex < length) {
344             try {
345                 actions.add(new ActionBuilder()
346                         .withKey(new ActionKey(offset))
347                         .setOrder(offset)
348                         .setAction(ActionUtil.readActionHeader(EncodeConstants.OF13_VERSION_ID, message, registry,
349                                 ActionPath.FLOWS_STATISTICS_UPDATE_APPLY_ACTIONS))
350                         .build());
351
352                 offset++;
353             } catch (ClassCastException | IllegalStateException e) {
354                 message.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
355             }
356         }
357
358         return actions;
359     }
360
361     @Override
362     public void injectDeserializerRegistry(final DeserializerRegistry deserializerRegistry) {
363         registry = deserializerRegistry;
364     }
365
366 }