2 * Copyright (c) 2013 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
9 package org.opendaylight.openflowjava.protocol.impl.util;
11 import io.netty.buffer.ByteBuf;
13 import java.util.ArrayList;
14 import java.util.List;
16 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
17 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
18 import org.opendaylight.openflowjava.protocol.api.extensibility.EnhancedMessageCodeKey;
19 import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderDeserializer;
20 import org.opendaylight.openflowjava.protocol.api.extensibility.MessageCodeKey;
21 import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthertypeAction;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthertypeActionBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterAction;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.GroupIdAction;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.GroupIdActionBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaxLengthAction;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaxLengthActionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsTtlAction;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsTtlActionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NwTtlAction;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NwTtlActionBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmFieldsAction;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmFieldsActionBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortAction;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortActionBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.QueueIdAction;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.QueueIdActionBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.CopyTtlIn;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.CopyTtlOut;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.DecMplsTtl;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.DecNwTtl;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Experimenter;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Group;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Output;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopMpls;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopPbb;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopVlan;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushMpls;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushPbb;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushVlan;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetField;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetMplsTtl;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetNwTtl;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetQueue;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.Action;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.ActionBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionBase;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.EtherType;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.grouping.MatchEntries;
64 * Deserializes ofp_actions (OpenFlow v1.3)
65 * @author timotej.kubas
66 * @author michal.polkorab
68 public class ActionsDeserializer implements OFDeserializer<Action>,
69 HeaderDeserializer<Action>, DeserializerRegistryInjector {
71 private static final byte PADDING_IN_ACTIONS_HEADER = 4;
72 private static final byte PADDING_IN_OUTPUT_ACTIONS_HEADER = 6;
73 private static final byte PADDING_IN_SET_MPLS_TTL_ACTIONS_HEADER = 3;
74 private static final byte PADDING_IN_PUSH_VLAN_ACTIONS_HEADER = 2;
75 private static final byte PADDING_IN_NW_TTL_ACTIONS_HEADER = 3;
76 private DeserializerRegistry registry;
79 public Action deserialize(ByteBuf input) {
81 ActionBuilder actionBuilder = new ActionBuilder();
82 int type = input.getUnsignedShort(input.readerIndex());
85 action = createOutputAction(input, actionBuilder);
88 action = createCopyTtlOutAction(input, actionBuilder);
91 action = createCopyTtlInAction(input, actionBuilder);
94 action = createSetMplsTtlAction(input, actionBuilder);
97 action = createDecMplsTtlOutAction(input, actionBuilder);
100 action = createPushVlanAction(input, actionBuilder);
103 action = createPopVlanAction(input, actionBuilder);
106 action = createPushMplsAction(input, actionBuilder);
109 action = createPopMplsAction(input, actionBuilder);
112 action = createSetQueueAction(input, actionBuilder);
115 action = createGroupAction(input, actionBuilder);
118 action = createSetNwTtlAction(input, actionBuilder);
121 action = createDecNwTtlAction(input, actionBuilder);
124 action = createSetFieldAction(input, actionBuilder);
127 action = createPushPbbAction(input, actionBuilder);
130 action = createPopPbbAction(input, actionBuilder);
133 OFDeserializer<ExperimenterAction> expDeserializer = registry.getDeserializer(
134 new MessageCodeKey(EncodeConstants.OF13_VERSION_ID, 0xFFFF, ExperimenterAction.class));
135 ExperimenterAction expAction = expDeserializer.deserialize(input);
136 actionBuilder.addAugmentation(ExperimenterAction.class, expAction);
145 public Action deserializeHeader(ByteBuf input) {
146 ActionBuilder builder;
147 builder = new ActionBuilder();
148 int type = input.readUnsignedShort();
149 input.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
152 builder.setType(Output.class);
155 builder.setType(CopyTtlOut.class);
158 builder.setType(CopyTtlIn.class);
161 builder.setType(SetMplsTtl.class);
164 builder.setType(DecMplsTtl.class);
167 builder.setType(PushVlan.class);
170 builder.setType(PopVlan.class);
173 builder.setType(PushMpls.class);
176 builder.setType(PopMpls.class);
179 builder.setType(SetQueue.class);
182 builder.setType(Group.class);
185 builder.setType(SetNwTtl.class);
188 builder.setType(DecNwTtl.class);
191 builder.setType(SetField.class);
194 builder.setType(PushPbb.class);
197 builder.setType(PopPbb.class);
200 HeaderDeserializer<ExperimenterAction> expDeserializer = registry.getDeserializer(
201 new MessageCodeKey(EncodeConstants.OF13_VERSION_ID, 0xFFFF, ExperimenterAction.class));
202 ExperimenterAction expAction = expDeserializer.deserializeHeader(input);
203 builder.setType(Experimenter.class);
204 builder.addAugmentation(ExperimenterAction.class, expAction);
209 return builder.build();
212 private static Action createEmptyHeader(Class<? extends ActionBase> action,
213 ByteBuf in, ActionBuilder actionBuilder) {
214 actionBuilder.setType(action);
215 in.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
216 in.skipBytes(PADDING_IN_ACTIONS_HEADER);
217 return actionBuilder.build();
220 private static Action createCopyTtlInAction(ByteBuf in, ActionBuilder actionBuilder) {
221 return createEmptyHeader(CopyTtlIn.class, in, actionBuilder);
224 private static Action createCopyTtlOutAction(ByteBuf in, ActionBuilder actionBuilder) {
225 return createEmptyHeader(CopyTtlOut.class, in, actionBuilder);
228 private static Action createDecMplsTtlOutAction(ByteBuf in, ActionBuilder actionBuilder) {
229 return createEmptyHeader(DecMplsTtl.class, in, actionBuilder);
232 private static Action createPopVlanAction(ByteBuf in, ActionBuilder actionBuilder) {
233 return createEmptyHeader(PopVlan.class, in, actionBuilder);
236 private static Action createDecNwTtlAction(ByteBuf in, ActionBuilder actionBuilder) {
237 return createEmptyHeader(DecNwTtl.class, in, actionBuilder);
240 private static Action createPopPbbAction(ByteBuf in, ActionBuilder actionBuilder) {
241 return createEmptyHeader(PopPbb.class, in, actionBuilder);
244 private static Action createOutputAction(ByteBuf in, ActionBuilder actionBuilder) {
245 actionBuilder.setType(Output.class);
246 in.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
247 PortActionBuilder port = new PortActionBuilder();
248 port.setPort(new PortNumber(in.readUnsignedInt()));
249 actionBuilder.addAugmentation(PortAction.class, port.build());
250 MaxLengthActionBuilder maxLen = new MaxLengthActionBuilder();
251 maxLen.setMaxLength(in.readUnsignedShort());
252 actionBuilder.addAugmentation(MaxLengthAction.class, maxLen.build());
253 in.skipBytes(PADDING_IN_OUTPUT_ACTIONS_HEADER);
254 return actionBuilder.build();
257 private static Action createSetMplsTtlAction(ByteBuf in, ActionBuilder actionBuilder) {
258 actionBuilder.setType(SetMplsTtl.class);
259 in.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
260 MplsTtlActionBuilder mplsTtl = new MplsTtlActionBuilder();
261 mplsTtl.setMplsTtl(in.readUnsignedByte());
262 actionBuilder.addAugmentation(MplsTtlAction.class, mplsTtl.build());
263 in.skipBytes(PADDING_IN_SET_MPLS_TTL_ACTIONS_HEADER);
264 return actionBuilder.build();
267 private static Action createPushAction(Class<? extends ActionBase> action,
268 ByteBuf in, ActionBuilder actionBuilder) {
269 actionBuilder.setType(action);
270 in.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
271 EthertypeActionBuilder etherType = new EthertypeActionBuilder();
272 etherType.setEthertype(new EtherType(in.readUnsignedShort()));
273 actionBuilder.addAugmentation(EthertypeAction.class, etherType.build());
274 in.skipBytes(PADDING_IN_PUSH_VLAN_ACTIONS_HEADER);
275 return actionBuilder.build();
278 private static Action createPushVlanAction(ByteBuf in, ActionBuilder actionBuilder) {
279 return createPushAction(PushVlan.class, in, actionBuilder);
282 private static Action createPushMplsAction(ByteBuf in, ActionBuilder actionBuilder) {
283 return createPushAction(PushMpls.class, in, actionBuilder);
286 private static Action createPopMplsAction(ByteBuf in, ActionBuilder actionBuilder) {
287 return createPushAction(PopMpls.class, in, actionBuilder);
290 private static Action createPushPbbAction(ByteBuf in, ActionBuilder actionBuilder) {
291 return createPushAction(PushPbb.class, in, actionBuilder);
294 private static Action createSetQueueAction(ByteBuf in, ActionBuilder actionBuilder) {
295 actionBuilder.setType(SetQueue.class);
296 in.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
297 QueueIdActionBuilder queueId = new QueueIdActionBuilder();
298 queueId.setQueueId(in.readUnsignedInt());
299 actionBuilder.addAugmentation(QueueIdAction.class, queueId.build());
300 return actionBuilder.build();
303 private static Action createGroupAction(ByteBuf in, ActionBuilder actionBuilder) {
304 actionBuilder.setType(Group.class);
305 in.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
306 GroupIdActionBuilder group = new GroupIdActionBuilder();
307 group.setGroupId(in.readUnsignedInt());
308 actionBuilder.addAugmentation(GroupIdAction.class, group.build());
309 return actionBuilder.build();
312 private static Action createSetNwTtlAction(ByteBuf in, ActionBuilder actionBuilder) {
313 actionBuilder.setType(SetNwTtl.class);
314 in.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
315 NwTtlActionBuilder nwTtl = new NwTtlActionBuilder();
316 nwTtl.setNwTtl(in.readUnsignedByte());
317 actionBuilder.addAugmentation(NwTtlAction.class, nwTtl.build());
318 in.skipBytes(PADDING_IN_NW_TTL_ACTIONS_HEADER);
319 return actionBuilder.build();
322 private Action createSetFieldAction(ByteBuf in, ActionBuilder actionBuilder) {
323 actionBuilder.setType(SetField.class);
324 int startIndex = in.readerIndex();
325 in.skipBytes(2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
326 OxmFieldsActionBuilder matchEntries = new OxmFieldsActionBuilder();
327 int oxmClass = in.getUnsignedShort(in.readerIndex());
328 // get oxm_field & hasMask byte and extract the field value
329 int oxmField = in.getUnsignedByte(in.readerIndex()
330 + EncodeConstants.SIZE_OF_SHORT_IN_BYTES) >>> 1;
331 OFDeserializer<MatchEntries> matchDeserializer = registry.getDeserializer(
332 new EnhancedMessageCodeKey(EncodeConstants.OF13_VERSION_ID, oxmClass,
333 oxmField, MatchEntries.class));
334 List<MatchEntries> entry = new ArrayList<>();
335 entry.add(matchDeserializer.deserialize(in));
336 matchEntries.setMatchEntries(entry);
337 actionBuilder.addAugmentation(OxmFieldsAction.class, matchEntries.build());
338 int paddingRemainder = (in.readerIndex() - startIndex) % EncodeConstants.PADDING;
339 if (paddingRemainder != 0) {
340 in.skipBytes(EncodeConstants.PADDING - paddingRemainder);
342 return actionBuilder.build();
346 public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
347 registry = deserializerRegistry;