2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart;
10 import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint32;
11 import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint64;
12 import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint8;
14 import io.netty.buffer.ByteBuf;
15 import java.util.ArrayList;
16 import java.util.List;
17 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
18 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
19 import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
20 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
21 import org.opendaylight.openflowjava.util.ByteBufUtils;
22 import org.opendaylight.openflowjava.util.ExperimenterDeserializerKeyFactory;
23 import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
24 import org.opendaylight.openflowplugin.impl.protocol.deserialization.util.ActionUtil;
25 import org.opendaylight.openflowplugin.impl.protocol.deserialization.util.InstructionUtil;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesPropType;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableConfig;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.set.field.match.SetFieldMatch;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplyActionsBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplyActionsMissBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplySetfieldBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.ApplySetfieldMissBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.InstructionsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.InstructionsMissBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.MatchBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.NextTableBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.NextTableMissBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WildcardsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteActionsBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteActionsMissBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteSetfieldBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.WriteSetfieldMissBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.match.MatchSetfieldBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.next.table.TablesBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.next.table.miss.TablesMissBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature.prop.type.wildcards.WildcardSetfieldBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.TableProperties;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.TablePropertiesBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.table.properties.TableFeatureProperties;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.table.properties.TableFeaturePropertiesBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.table.features.table.properties.TableFeaturePropertiesKey;
62 import org.opendaylight.yangtools.yang.common.Uint8;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
66 public class MultipartReplyTableFeaturesDeserializer implements OFDeserializer<MultipartReplyBody>,
67 DeserializerRegistryInjector {
68 private static final Logger LOG = LoggerFactory.getLogger(MultipartReplyTableFeaturesDeserializer.class);
69 private static final byte PADDING_IN_MULTIPART_REPLY_TABLE_FEATURES = 5;
70 private static final byte MAX_TABLE_NAME_LENGTH = 32;
71 private static final byte MULTIPART_REPLY_TABLE_FEATURES_STRUCTURE_LENGTH = 64;
72 private static final byte COMMON_PROPERTY_LENGTH = 4;
73 private static final TableFeaturesMatchFieldDeserializer MATCH_FIELD_DESERIALIZER =
74 new TableFeaturesMatchFieldDeserializer();
76 private DeserializerRegistry registry;
79 public MultipartReplyBody deserialize(final ByteBuf message) {
80 final MultipartReplyTableFeaturesBuilder builder = new MultipartReplyTableFeaturesBuilder();
81 final List<TableFeatures> items = new ArrayList<>();
83 while (message.readableBytes() > 0) {
84 final int itemLength = message.readUnsignedShort();
85 final TableFeaturesBuilder itemBuilder = new TableFeaturesBuilder()
86 .setTableId(readUint8(message));
88 message.skipBytes(PADDING_IN_MULTIPART_REPLY_TABLE_FEATURES);
91 .withKey(new TableFeaturesKey(itemBuilder.getTableId()))
92 .setName(ByteBufUtils.decodeNullTerminatedString(message, MAX_TABLE_NAME_LENGTH))
93 .setMetadataMatch(readUint64(message))
94 .setMetadataWrite(readUint64(message))
95 .setConfig(readTableConfig(message))
96 .setMaxEntries(readUint32(message))
97 .setTableProperties(readTableProperties(message,
98 itemLength - MULTIPART_REPLY_TABLE_FEATURES_STRUCTURE_LENGTH))
103 .setTableFeatures(items)
107 private static TableConfig readTableConfig(final ByteBuf message) {
108 final long input = message.readUnsignedInt();
109 final boolean deprecated = (input & 3) != 0;
111 return new TableConfig(deprecated);
114 private TableProperties readTableProperties(final ByteBuf message, final int length) {
115 final List<TableFeatureProperties> items = new ArrayList<>();
116 int tableFeaturesLength = length;
118 while (tableFeaturesLength > 0) {
119 final int propStartIndex = message.readerIndex();
120 final TableFeaturesPropType propType = TableFeaturesPropType.forValue(message.readUnsignedShort());
121 int propertyLength = message.readUnsignedShort();
122 final int paddingRemainder = propertyLength % EncodeConstants.PADDING;
123 tableFeaturesLength -= propertyLength;
124 final int commonPropertyLength = propertyLength - COMMON_PROPERTY_LENGTH;
125 final TableFeaturePropertiesBuilder propBuilder = new TableFeaturePropertiesBuilder()
127 .withKey(new TableFeaturePropertiesKey(order));
130 case OFPTFPTINSTRUCTIONS:
131 propBuilder.setTableFeaturePropType(new InstructionsBuilder()
132 .setInstructions(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
133 .rev131026.table.feature.prop.type.table.feature.prop.type.instructions
134 .InstructionsBuilder()
135 .setInstruction(readInstructions(message, commonPropertyLength))
139 case OFPTFPTINSTRUCTIONSMISS:
140 propBuilder.setTableFeaturePropType(new InstructionsMissBuilder()
141 .setInstructionsMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
142 .rev131026.table.feature.prop.type.table.feature.prop.type.instructions.miss
143 .InstructionsMissBuilder()
144 .setInstruction(readInstructions(message, commonPropertyLength))
148 case OFPTFPTNEXTTABLES:
149 propBuilder.setTableFeaturePropType(new NextTableBuilder()
150 .setTables(new TablesBuilder()
151 .setTableIds(readNextTableIds(message, commonPropertyLength))
155 case OFPTFPTNEXTTABLESMISS:
156 propBuilder.setTableFeaturePropType(new NextTableMissBuilder()
157 .setTablesMiss(new TablesMissBuilder()
158 .setTableIds(readNextTableIds(message, commonPropertyLength))
162 case OFPTFPTWRITEACTIONS:
163 propBuilder.setTableFeaturePropType(new WriteActionsBuilder()
164 .setWriteActions(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026
165 .table.feature.prop.type.table.feature.prop.type.write.actions.WriteActionsBuilder()
166 .setAction(readActions(message, commonPropertyLength))
170 case OFPTFPTWRITEACTIONSMISS:
171 propBuilder.setTableFeaturePropType(new WriteActionsMissBuilder()
172 .setWriteActionsMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
173 .rev131026.table.feature.prop.type.table.feature.prop.type.write.actions.miss
174 .WriteActionsMissBuilder()
175 .setAction(readActions(message, commonPropertyLength))
179 case OFPTFPTAPPLYACTIONS:
180 propBuilder.setTableFeaturePropType(new ApplyActionsBuilder()
181 .setApplyActions(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026
182 .table.feature.prop.type.table.feature.prop.type.apply.actions.ApplyActionsBuilder()
183 .setAction(readActions(message, commonPropertyLength))
187 case OFPTFPTAPPLYACTIONSMISS:
188 propBuilder.setTableFeaturePropType(new ApplyActionsMissBuilder()
189 .setApplyActionsMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
190 .rev131026.table.feature.prop.type.table.feature.prop.type.apply.actions.miss
191 .ApplyActionsMissBuilder()
192 .setAction(readActions(message, commonPropertyLength))
197 propBuilder.setTableFeaturePropType(new MatchBuilder()
198 .setMatchSetfield(new MatchSetfieldBuilder()
199 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
203 case OFPTFPTWILDCARDS:
204 propBuilder.setTableFeaturePropType(new WildcardsBuilder()
205 .setWildcardSetfield(new WildcardSetfieldBuilder()
206 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
210 case OFPTFPTWRITESETFIELD:
211 propBuilder.setTableFeaturePropType(new WriteSetfieldBuilder()
212 .setWriteSetfield(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026
213 .table.feature.prop.type.table.feature.prop.type.write.setfield.WriteSetfieldBuilder()
214 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
218 case OFPTFPTWRITESETFIELDMISS:
219 propBuilder.setTableFeaturePropType(new WriteSetfieldMissBuilder()
220 .setWriteSetfieldMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
221 .rev131026.table.feature.prop.type.table.feature.prop.type.write.setfield.miss
222 .WriteSetfieldMissBuilder()
223 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
227 case OFPTFPTAPPLYSETFIELD:
228 propBuilder.setTableFeaturePropType(new ApplySetfieldBuilder()
229 .setApplySetfield(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026
230 .table.feature.prop.type.table.feature.prop.type.apply.setfield.ApplySetfieldBuilder()
231 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
235 case OFPTFPTAPPLYSETFIELDMISS:
236 propBuilder.setTableFeaturePropType(new ApplySetfieldMissBuilder()
237 .setApplySetfieldMiss(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types
238 .rev131026.table.feature.prop.type.table.feature.prop.type.apply.setfield.miss
239 .ApplySetfieldMissBuilder()
240 .setSetFieldMatch(readMatchFields(message, commonPropertyLength))
244 case OFPTFPTEXPERIMENTER:
245 case OFPTFPTEXPERIMENTERMISS:
246 final long expId = message.readUnsignedInt();
247 message.readerIndex(propStartIndex);
249 final OFDeserializer<TableFeatureProperties> propDeserializer = registry
250 .getDeserializer(ExperimenterDeserializerKeyFactory
251 .createMultipartReplyTFDeserializerKey(EncodeConstants.OF13_VERSION_ID, expId));
253 // TODO: Finish experimenter table features (currently using OFJava deserialization only to skip
255 propDeserializer.deserialize(message);
256 LOG.debug("Table feature property type {} is not handled yet.", propType);
263 if (paddingRemainder != 0) {
264 message.skipBytes(EncodeConstants.PADDING - paddingRemainder);
265 tableFeaturesLength -= EncodeConstants.PADDING - paddingRemainder;
268 items.add(propBuilder.build());
273 return new TablePropertiesBuilder()
274 .setTableFeatureProperties(items)
278 private static List<SetFieldMatch> readMatchFields(final ByteBuf message, final int length) {
279 final List<SetFieldMatch> matchFields = new ArrayList<>();
281 final int startIndex = message.readerIndex();
283 while (message.readerIndex() - startIndex < length) {
284 MATCH_FIELD_DESERIALIZER
285 .deserialize(message)
286 .map(matchFields::add)
288 message.skipBytes(2 * Short.BYTES);
289 return Boolean.FALSE;
296 private static List<Uint8> readNextTableIds(final ByteBuf message, final int length) {
297 final List<Uint8> tableIds = new ArrayList<>();
298 int nextTableLength = length;
300 while (nextTableLength > 0) {
301 tableIds.add(Uint8.valueOf(message.readUnsignedByte()));
302 nextTableLength -= 1;
308 private List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list
309 .Instruction> readInstructions(final ByteBuf message, final int length) {
311 final List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list
312 .Instruction> instructions = new ArrayList<>();
313 final int startIndex = message.readerIndex();
316 while (message.readerIndex() - startIndex < length) {
318 instructions.add(new InstructionBuilder()
319 .withKey(new InstructionKey(offset))
321 .setInstruction(InstructionUtil
322 .readInstructionHeader(EncodeConstants.OF13_VERSION_ID, message, registry))
326 } catch (ClassCastException | IllegalStateException e) {
327 message.skipBytes(2 * Short.BYTES);
334 @SuppressWarnings("checkstyle:LineLength")
335 private List<Action> readActions(final ByteBuf message, final int length) {
336 final List<Action> actions = new ArrayList<>();
337 final int startIndex = message.readerIndex();
340 while (message.readerIndex() - startIndex < length) {
342 actions.add(new ActionBuilder()
343 .withKey(new ActionKey(offset))
345 .setAction(ActionUtil.readActionHeader(EncodeConstants.OF13_VERSION_ID, message, registry,
346 ActionPath.FLOWS_STATISTICS_UPDATE_APPLY_ACTIONS))
350 } catch (ClassCastException | IllegalStateException e) {
351 message.skipBytes(2 * Short.BYTES);
359 public void injectDeserializerRegistry(final DeserializerRegistry deserializerRegistry) {
360 registry = deserializerRegistry;