Extensibility support (serialization 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.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthertypeAction;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthertypeActionBuilder;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterAction;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterActionBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.GroupIdAction;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.GroupIdActionBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaxLengthAction;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaxLengthActionBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsTtlAction;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsTtlActionBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NwTtlAction;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NwTtlActionBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmFieldsAction;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmFieldsActionBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortAction;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortActionBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.QueueIdAction;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.QueueIdActionBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.CopyTtlIn;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.CopyTtlOut;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.DecMplsTtl;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.DecNwTtl;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Experimenter;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Group;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Output;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopMpls;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopPbb;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopVlan;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushMpls;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushPbb;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushVlan;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetField;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetMplsTtl;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetNwTtl;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetQueue;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.Action;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.ActionBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionBase;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.EtherType;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
56
57 /**
58  * Deserializes ofp_actions (OpenFlow v1.3)
59  * @author timotej.kubas
60  * @author michal.polkorab
61  */
62 public class ActionsDeserializer {
63     
64     private static final byte ACTION_HEADER_LENGTH = 4;
65     private static final byte PADDING_IN_ACTIONS_HEADER = 4;
66     private static final byte PADDING_IN_OUTPUT_ACTIONS_HEADER = 6;
67     private static final byte PADDING_IN_SET_MPLS_TTL_ACTIONS_HEADER = 3;
68     private static final byte PADDING_IN_PUSH_VLAN_ACTIONS_HEADER = 2;
69     private static final byte PADDING_IN_NW_TTL_ACTIONS_HEADER = 3;
70     private static final byte EXPERIMENTER_ACTION_HEADER_LENGTH = 8;
71     
72     /**
73      * Creates list of actions (OpenFlow v1.3)
74      * @param input input ByteBuf
75      * @param actionsLength length of buckets
76      * @return ActionsList
77      */
78     public static List<Action> createActions(ByteBuf input, int actionsLength) {
79         List<Action> actions = new ArrayList<>();
80         int length = 0;
81         while (length < actionsLength) {
82             int type = input.readUnsignedShort();
83             int currentActionLength = input.readUnsignedShort();
84             ActionBuilder actionBuilder = new ActionBuilder();
85             switch(type) {
86             case 0:
87                 actions.add(createOutputAction(input, actionBuilder));
88                 break;
89             case 11:
90                 actions.add(createCopyTtlOutAction(input, actionBuilder));
91                 break;
92             case 12:
93                 actions.add(createCopyTtlInAction(input, actionBuilder));
94                 break;
95             case 15:
96                 actions.add(createSetMplsTtlAction(input, actionBuilder));
97                 break;
98             case 16:
99                 actions.add(createDecMplsTtlOutAction(input, actionBuilder));
100                 break;
101             case 17:
102                 actions.add(createPushVlanAction(input, actionBuilder));
103                 break;
104             case 18:
105                 actions.add(createPopVlanAction(input, actionBuilder));
106                 break;
107             case 19:
108                 actions.add(createPushMplsAction(input, actionBuilder));
109                 break;
110             case 20:
111                 actions.add(createPopMplsAction(input, actionBuilder));
112                 break;
113             case 21:
114                 actions.add(createSetQueueAction(input, actionBuilder));
115                 break;
116             case 22:
117                 actions.add(createGroupAction(input, actionBuilder));
118                 break;
119             case 23:
120                 actions.add(createSetNwTtlAction(input, actionBuilder));
121                 break;
122             case 24:
123                 actions.add(createDecNwTtlAction(input, actionBuilder));
124                 break;
125             case 25:
126                 actions.add(createSetFieldAction(input, actionBuilder, currentActionLength));
127                 break;
128             case 26:
129                 actions.add(createPushPbbAction(input, actionBuilder));
130                 break;
131             case 27:
132                 actions.add(createPopPbbAction(input, actionBuilder));
133                 break;
134             case 0xFFFF:
135                 actions.add(createExperimenterAction(input, actionBuilder, currentActionLength));
136                 break;
137             default:
138                 break;
139             }
140             length += currentActionLength;
141         } 
142         return actions;
143     }
144
145     /**
146      * Creates action ids - actions without values (OpenFlow v1.3)
147      * @param input input ByteBuf
148      * @param actionsLength length of actions
149      * @return ActionsList
150      */
151     public static List<Action> createActionIds(ByteBuf input, int actionsLength) {
152         List<Action> actionsList = new ArrayList<>();
153         int length = 0;
154         ActionBuilder builder;
155         while (length < actionsLength) {
156             builder = new ActionBuilder();
157             int type = input.readUnsignedShort();
158             int currentActionLength = input.readUnsignedShort();
159             switch(type) {
160             case 0:
161                 builder.setType(Output.class);
162                 break;
163             case 11:
164                 builder.setType(CopyTtlOut.class);
165                 break;
166             case 12:
167                 builder.setType(CopyTtlIn.class);
168                 break;
169             case 15:
170                 builder.setType(SetMplsTtl.class);
171                 break;
172             case 16:
173                 builder.setType(DecMplsTtl.class);
174                 break;
175             case 17:
176                 builder.setType(PushVlan.class);
177                 break;
178             case 18:
179                 builder.setType(PopVlan.class);
180                 break;
181             case 19:
182                 builder.setType(PushMpls.class);
183                 break;
184             case 20:
185                 builder.setType(PopMpls.class);
186                 break;
187             case 21:
188                 builder.setType(SetQueue.class);
189                 break;
190             case 22:
191                 builder.setType(Group.class);
192                 break;
193             case 23:
194                 builder.setType(SetNwTtl.class);
195                 break;
196             case 24:
197                 builder.setType(DecNwTtl.class);
198                 break;
199             case 25:
200                 builder.setType(SetField.class);
201                 break; 
202             case 26:
203                 builder.setType(PushPbb.class);
204                 break;
205             case 27:
206                 builder.setType(PopPbb.class);
207                 break;
208             case 0xFFFF:
209                 builder.setType(Experimenter.class);
210                 ExperimenterActionBuilder experimenter = new ExperimenterActionBuilder();
211                 experimenter.setExperimenter(input.readUnsignedInt());
212                 builder.addAugmentation(ExperimenterAction.class, experimenter.build());
213                 break;
214             default: 
215                 break;
216             }
217             actionsList.add(builder.build());
218             length += currentActionLength;
219         } 
220         return actionsList;
221     }
222
223     private static Action createEmptyHeader(Class<? extends ActionBase> action,
224             ByteBuf in, ActionBuilder actionBuilder) {
225         actionBuilder.setType(action);
226         in.skipBytes(PADDING_IN_ACTIONS_HEADER);
227         return actionBuilder.build();
228     }
229     
230     private static Action createCopyTtlInAction(ByteBuf in, ActionBuilder actionBuilder) {
231         return createEmptyHeader(CopyTtlIn.class, in, actionBuilder);
232     }
233
234     private static Action createCopyTtlOutAction(ByteBuf in, ActionBuilder actionBuilder) {
235         return createEmptyHeader(CopyTtlOut.class, in, actionBuilder);
236     }
237     
238     private static Action createDecMplsTtlOutAction(ByteBuf in, ActionBuilder actionBuilder) {
239         return createEmptyHeader(DecMplsTtl.class, in, actionBuilder);
240     }
241     
242     private static Action createPopVlanAction(ByteBuf in, ActionBuilder actionBuilder) {
243         return createEmptyHeader(PopVlan.class, in, actionBuilder);
244     }
245     
246     private static Action createDecNwTtlAction(ByteBuf in, ActionBuilder actionBuilder) {
247         return createEmptyHeader(DecNwTtl.class, in, actionBuilder);
248     }
249     
250     private static Action createPopPbbAction(ByteBuf in, ActionBuilder actionBuilder) {
251         return createEmptyHeader(PopPbb.class, in, actionBuilder);
252     }
253     
254     private static Action createOutputAction(ByteBuf in, ActionBuilder actionBuilder) {
255         actionBuilder.setType(Output.class);
256         PortActionBuilder port = new PortActionBuilder();
257         port.setPort(new PortNumber(in.readUnsignedInt()));
258         actionBuilder.addAugmentation(PortAction.class, port.build());
259         MaxLengthActionBuilder maxLen = new MaxLengthActionBuilder();
260         maxLen.setMaxLength(in.readUnsignedShort());
261         actionBuilder.addAugmentation(MaxLengthAction.class, maxLen.build());
262         in.skipBytes(PADDING_IN_OUTPUT_ACTIONS_HEADER);
263         return actionBuilder.build();
264     }
265     
266     private static Action createSetMplsTtlAction(ByteBuf in, ActionBuilder actionBuilder) {
267         actionBuilder.setType(SetMplsTtl.class);
268         MplsTtlActionBuilder mplsTtl = new MplsTtlActionBuilder();
269         mplsTtl.setMplsTtl(in.readUnsignedByte());
270         actionBuilder.addAugmentation(MplsTtlAction.class, mplsTtl.build());
271         in.skipBytes(PADDING_IN_SET_MPLS_TTL_ACTIONS_HEADER);
272         return actionBuilder.build();
273     }
274     
275     private static Action createPushAction(Class<? extends ActionBase> action,
276             ByteBuf in, ActionBuilder actionBuilder) {
277         actionBuilder.setType(action);
278         EthertypeActionBuilder etherType = new EthertypeActionBuilder();
279         etherType.setEthertype(new EtherType(in.readUnsignedShort()));
280         actionBuilder.addAugmentation(EthertypeAction.class, etherType.build());
281         in.skipBytes(PADDING_IN_PUSH_VLAN_ACTIONS_HEADER);
282         return actionBuilder.build();
283     }
284     
285     private static Action createPushVlanAction(ByteBuf in, ActionBuilder actionBuilder) {
286         return createPushAction(PushVlan.class, in, actionBuilder);
287     }
288     
289     private static Action createPushMplsAction(ByteBuf in, ActionBuilder actionBuilder) {
290         return createPushAction(PushMpls.class, in, actionBuilder);
291     }
292     
293     private static Action createPopMplsAction(ByteBuf in, ActionBuilder actionBuilder) {
294         return createPushAction(PopMpls.class, in, actionBuilder);
295     }
296     
297     private static Action createPushPbbAction(ByteBuf in, ActionBuilder actionBuilder) {
298         return createPushAction(PushPbb.class, in, actionBuilder);
299     }
300     
301     private static Action createSetQueueAction(ByteBuf in, ActionBuilder actionBuilder) {
302         actionBuilder.setType(SetQueue.class);
303         QueueIdActionBuilder queueId = new QueueIdActionBuilder();
304         queueId.setQueueId(in.readUnsignedInt());
305         actionBuilder.addAugmentation(QueueIdAction.class, queueId.build());
306         return actionBuilder.build();
307     }
308     
309     private static Action createGroupAction(ByteBuf in, ActionBuilder actionBuilder) {
310         actionBuilder.setType(Group.class);
311         GroupIdActionBuilder group = new GroupIdActionBuilder();
312         group.setGroupId(in.readUnsignedInt());
313         actionBuilder.addAugmentation(GroupIdAction.class, group.build());
314         return actionBuilder.build();
315     }
316     
317     private static Action createExperimenterAction(ByteBuf in, ActionBuilder actionBuilder, int actionLength) {
318         actionBuilder.setType(Experimenter.class);
319         ExperimenterActionBuilder experimenter = new ExperimenterActionBuilder();
320         experimenter.setExperimenter(in.readUnsignedInt());
321         int dataLength = actionLength - EXPERIMENTER_ACTION_HEADER_LENGTH;
322         if (dataLength > 0) {
323             byte[] data = new byte[dataLength];
324             in.readBytes(data);
325             experimenter.setData(data);
326         }
327         actionBuilder.addAugmentation(ExperimenterAction.class, experimenter.build());
328         return actionBuilder.build();
329     }
330     
331     private static Action createSetNwTtlAction(ByteBuf in, ActionBuilder actionBuilder) {
332         actionBuilder.setType(SetNwTtl.class);
333         NwTtlActionBuilder nwTtl = new NwTtlActionBuilder();
334         nwTtl.setNwTtl(in.readUnsignedByte());
335         actionBuilder.addAugmentation(NwTtlAction.class, nwTtl.build());
336         in.skipBytes(PADDING_IN_NW_TTL_ACTIONS_HEADER);
337         return actionBuilder.build();
338     }
339     
340     private static Action createSetFieldAction(ByteBuf in, ActionBuilder actionBuilder, int actionLength) {
341         actionBuilder.setType(SetField.class);
342         OxmFieldsActionBuilder matchEntries = new OxmFieldsActionBuilder();
343         matchEntries.setMatchEntries(MatchDeserializer.createMatchEntry(in, actionLength  - ACTION_HEADER_LENGTH));
344         actionBuilder.addAugmentation(OxmFieldsAction.class, matchEntries.build());
345         return actionBuilder.build();
346     }
347 }