Extensibility support (deserialization part)
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / util / ActionsDeserializer.java
1 /*
2  * Copyright (c) 2013 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
9 package org.opendaylight.openflowjava.protocol.impl.util;
10
11 import io.netty.buffer.ByteBuf;
12
13 import java.util.ArrayList;
14 import java.util.List;
15
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;
62
63 /**
64  * Deserializes ofp_actions (OpenFlow v1.3)
65  * @author timotej.kubas
66  * @author michal.polkorab
67  */
68 public class ActionsDeserializer implements OFDeserializer<Action>,
69         HeaderDeserializer<Action>, DeserializerRegistryInjector {
70     
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;
77
78     @Override
79     public Action deserialize(ByteBuf input) {
80         Action action = null;
81         ActionBuilder actionBuilder = new ActionBuilder();
82         int type = input.getUnsignedShort(input.readerIndex());
83         switch(type) {
84         case 0:
85             action = createOutputAction(input, actionBuilder);
86             break;
87         case 11:
88             action = createCopyTtlOutAction(input, actionBuilder);
89             break;
90         case 12:
91             action = createCopyTtlInAction(input, actionBuilder);
92             break;
93         case 15:
94             action = createSetMplsTtlAction(input, actionBuilder);
95             break;
96         case 16:
97             action = createDecMplsTtlOutAction(input, actionBuilder);
98             break;
99         case 17:
100             action = createPushVlanAction(input, actionBuilder);
101             break;
102         case 18:
103             action = createPopVlanAction(input, actionBuilder);
104             break;
105         case 19:
106             action = createPushMplsAction(input, actionBuilder);
107             break;
108         case 20:
109             action = createPopMplsAction(input, actionBuilder);
110             break;
111         case 21:
112             action = createSetQueueAction(input, actionBuilder);
113             break;
114         case 22:
115             action = createGroupAction(input, actionBuilder);
116             break;
117         case 23:
118             action = createSetNwTtlAction(input, actionBuilder);
119             break;
120         case 24:
121             action = createDecNwTtlAction(input, actionBuilder);
122             break;
123         case 25:
124             action = createSetFieldAction(input, actionBuilder);
125             break;
126         case 26:
127             action = createPushPbbAction(input, actionBuilder);
128             break;
129         case 27:
130             action = createPopPbbAction(input, actionBuilder);
131             break;
132         case 0xFFFF:
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);
137             break;
138         default:
139             break;
140         }
141         return action;
142     }
143
144     @Override
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);
150         switch(type) {
151         case 0:
152             builder.setType(Output.class);
153             break;
154         case 11:
155             builder.setType(CopyTtlOut.class);
156             break;
157         case 12:
158             builder.setType(CopyTtlIn.class);
159             break;
160         case 15:
161             builder.setType(SetMplsTtl.class);
162             break;
163         case 16:
164             builder.setType(DecMplsTtl.class);
165             break;
166         case 17:
167             builder.setType(PushVlan.class);
168             break;
169         case 18:
170             builder.setType(PopVlan.class);
171             break;
172         case 19:
173             builder.setType(PushMpls.class);
174             break;
175         case 20:
176             builder.setType(PopMpls.class);
177             break;
178         case 21:
179             builder.setType(SetQueue.class);
180             break;
181         case 22:
182             builder.setType(Group.class);
183             break;
184         case 23:
185             builder.setType(SetNwTtl.class);
186             break;
187         case 24:
188             builder.setType(DecNwTtl.class);
189             break;
190         case 25:
191             builder.setType(SetField.class);
192             break; 
193         case 26:
194             builder.setType(PushPbb.class);
195             break;
196         case 27:
197             builder.setType(PopPbb.class);
198             break;
199         case 0xFFFF:
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);
205             break;
206         default: 
207             break;
208         }
209         return builder.build();
210     }
211
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();
218     }
219     
220     private static Action createCopyTtlInAction(ByteBuf in, ActionBuilder actionBuilder) {
221         return createEmptyHeader(CopyTtlIn.class, in, actionBuilder);
222     }
223
224     private static Action createCopyTtlOutAction(ByteBuf in, ActionBuilder actionBuilder) {
225         return createEmptyHeader(CopyTtlOut.class, in, actionBuilder);
226     }
227     
228     private static Action createDecMplsTtlOutAction(ByteBuf in, ActionBuilder actionBuilder) {
229         return createEmptyHeader(DecMplsTtl.class, in, actionBuilder);
230     }
231     
232     private static Action createPopVlanAction(ByteBuf in, ActionBuilder actionBuilder) {
233         return createEmptyHeader(PopVlan.class, in, actionBuilder);
234     }
235     
236     private static Action createDecNwTtlAction(ByteBuf in, ActionBuilder actionBuilder) {
237         return createEmptyHeader(DecNwTtl.class, in, actionBuilder);
238     }
239     
240     private static Action createPopPbbAction(ByteBuf in, ActionBuilder actionBuilder) {
241         return createEmptyHeader(PopPbb.class, in, actionBuilder);
242     }
243     
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();
255     }
256     
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();
265     }
266     
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();
276     }
277     
278     private static Action createPushVlanAction(ByteBuf in, ActionBuilder actionBuilder) {
279         return createPushAction(PushVlan.class, in, actionBuilder);
280     }
281     
282     private static Action createPushMplsAction(ByteBuf in, ActionBuilder actionBuilder) {
283         return createPushAction(PushMpls.class, in, actionBuilder);
284     }
285     
286     private static Action createPopMplsAction(ByteBuf in, ActionBuilder actionBuilder) {
287         return createPushAction(PopMpls.class, in, actionBuilder);
288     }
289     
290     private static Action createPushPbbAction(ByteBuf in, ActionBuilder actionBuilder) {
291         return createPushAction(PushPbb.class, in, actionBuilder);
292     }
293     
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();
301     }
302     
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();
310     }
311
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();
320     }
321     
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);
341         }
342         return actionBuilder.build();
343     }
344
345     @Override
346     public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
347         registry = deserializerRegistry;
348     }
349 }