Merge "Adding support for the git-review command line tool"
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / util / ActionsSerializer.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.List;
14
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthertypeAction;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterAction;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.GroupIdAction;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaxLengthAction;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsTtlAction;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NwTtlAction;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmFieldsAction;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortAction;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.QueueIdAction;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.CopyTtlIn;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.CopyTtlOut;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.DecMplsTtl;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.DecNwTtl;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Experimenter;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Group;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.Output;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopMpls;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopPbb;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PopVlan;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushMpls;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushPbb;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.PushVlan;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetField;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetMplsTtl;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetNwTtl;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.SetQueue;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.actions.list.Action;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;
44
45 /**
46  * Serializes ofp_actions (OpenFlow v1.3)
47  * @author michal.polkorab
48  * @author timotej.kubas
49  */
50 public abstract class ActionsSerializer {
51
52     private static final byte OUTPUT_CODE = 0;
53     private static final byte COPY_TTL_OUT_CODE = 11;
54     private static final byte COPY_TTL_IN_CODE = 12;
55     private static final byte SET_MPLS_TTL_CODE = 15;
56     private static final byte DEC_MPLS_TTL_CODE = 16;
57     private static final byte PUSH_VLAN_CODE = 17;
58     private static final byte POP_VLAN_CODE = 18;
59     private static final byte PUSH_MPLS_CODE = 19;
60     private static final byte POP_MPLS_CODE = 20;
61     private static final byte SET_QUEUE_CODE = 21;
62     private static final byte GROUP_CODE = 22;
63     private static final byte SET_NW_TTL_CODE = 23;
64     private static final byte DEC_NW_TTL_CODE = 24;
65     private static final int SET_FIELD_CODE = 25;
66     private static final byte PUSH_PBB_CODE = 26;
67     private static final byte POP_PBB_CODE = 27;
68     private static final int EXPERIMENTER_CODE = 65535; // 0xFFFF
69     private static final byte OUTPUT_LENGTH = 16;
70     private static final byte SET_MPLS_TTL_LENGTH = 8;
71     private static final byte SET_QUEUE_LENGTH = 8;
72     private static final byte GROUP_LENGTH = 8;
73     private static final byte SET_NW_TTL_LENGTH = 8;
74     private static final byte EXPERIMENTER_LENGTH = 8;
75     private static final byte ACTION_HEADER_LENGTH = 8;
76     private static final byte LENGTH_OF_ETHERTYPE_ACTION = 8;
77     private static final byte LENGTH_OF_OTHER_ACTIONS = 8;
78     private static final byte SET_FIELD_HEADER_LENGTH = 4; // only type and length
79     private static final byte OUTPUT_PADDING = 6;
80     private static final byte SET_MPLS_TTL_PADDING = 3;
81     private static final byte SET_NW_TTL_PADDING = 3;
82     private static final byte PADDING_IN_ACTION_HEADER = 4;
83     private static final byte ETHERTYPE_ACTION_PADDING = 2;
84
85
86     /**
87      * Encodes actions to ByteBuf
88      * @param actionsList list of actions to be encoded
89      * @param outBuffer output ByteBuf
90      */
91     public static void encodeActions(List<ActionsList> actionsList, ByteBuf outBuffer) {
92         if (actionsList == null) {
93             return;
94         }
95         for (ActionsList list : actionsList) {
96             Action action = list.getAction();
97             if (action.getType().isAssignableFrom(Output.class)) {
98                 encodeOutputAction(action, outBuffer);
99             } else if (action.getType().isAssignableFrom(CopyTtlOut.class)) {
100                 encodeCopyTtlOutAction(outBuffer);
101             } else if (action.getType().isAssignableFrom(CopyTtlIn.class)) {
102                 encodeCopyTtlInAction(outBuffer);
103             } else if (action.getType().isAssignableFrom(SetMplsTtl.class)) {
104                 encodeSetMplsTtltAction(action, outBuffer);
105             } else if (action.getType().isAssignableFrom(DecMplsTtl.class)) {
106                 encodeDecMplsTtlAction(outBuffer);
107             } else if (action.getType().isAssignableFrom(PushVlan.class)) {
108                 encodePushVlanAction(action, outBuffer);
109             } else if (action.getType().isAssignableFrom(PopVlan.class)) {
110                 encodePopVlanAction(outBuffer);
111             } else if (action.getType().isAssignableFrom(PushMpls.class)) {
112                 encodePushMplsAction(action, outBuffer);
113             } else if (action.getType().isAssignableFrom(PopMpls.class)) {
114                 encodePopMplsAction(action, outBuffer);
115             } else if (action.getType().isAssignableFrom(SetQueue.class)) {
116                 encodeSetQueueAction(action, outBuffer);
117             } else if (action.getType().isAssignableFrom(Group.class)) {
118                 encodeGroupAction(action, outBuffer);
119             } else if (action.getType().isAssignableFrom(SetNwTtl.class)) {
120                 encodeSetNwTtlAction(action, outBuffer);
121             } else if (action.getType().isAssignableFrom(DecNwTtl.class)) {
122                 encodeDecNwTtlAction(outBuffer);
123             } else if (action.getType().isAssignableFrom(SetField.class)) {
124                 encodeSetFieldAction(action, outBuffer);
125             } else if (action.getType().isAssignableFrom(PushPbb.class)) {
126                 encodePushPbbAction(action, outBuffer);
127             } else if (action.getType().isAssignableFrom(PopPbb.class)) {
128                 encodePopPbbAction(outBuffer);
129             } else if (action.getType().isAssignableFrom(Experimenter.class)) {
130                 encodeExperimenterAction(action, outBuffer);
131             } 
132         }
133     }
134
135     private static void encodeOutputAction(Action action, ByteBuf outBuffer) {
136         outBuffer.writeShort(OUTPUT_CODE);
137         outBuffer.writeShort(OUTPUT_LENGTH);
138         PortAction port = action.getAugmentation(PortAction.class);
139         outBuffer.writeInt(port.getPort().getValue().intValue());
140         MaxLengthAction maxlength = action.getAugmentation(MaxLengthAction.class);
141         outBuffer.writeShort(maxlength.getMaxLength());
142         ByteBufUtils.padBuffer(OUTPUT_PADDING, outBuffer);
143     }
144
145     private static void encodeCopyTtlOutAction(ByteBuf outBuffer) {
146         outBuffer.writeShort(COPY_TTL_OUT_CODE);
147         encodeRestOfActionHeader(outBuffer);
148     }
149     
150     private static void encodeCopyTtlInAction(ByteBuf outBuffer) {
151         outBuffer.writeShort(COPY_TTL_IN_CODE);
152         encodeRestOfActionHeader(outBuffer);
153     }
154     
155     private static void encodeSetMplsTtltAction(Action action, ByteBuf outBuffer) {
156         outBuffer.writeShort(SET_MPLS_TTL_CODE);
157         outBuffer.writeShort(SET_MPLS_TTL_LENGTH);
158         MplsTtlAction mplsTtl = action.getAugmentation(MplsTtlAction.class);
159         outBuffer.writeByte(mplsTtl.getMplsTtl());
160         ByteBufUtils.padBuffer(SET_MPLS_TTL_PADDING, outBuffer);
161     }
162     
163     private static void encodeDecMplsTtlAction(ByteBuf outBuffer) {
164         outBuffer.writeShort(DEC_MPLS_TTL_CODE);
165         encodeRestOfActionHeader(outBuffer);
166     }
167     
168     private static void encodePushVlanAction(Action action, ByteBuf outBuffer) {
169         outBuffer.writeShort(PUSH_VLAN_CODE);
170         encodeCommonEthertype(action, outBuffer);
171     }
172
173     private static void encodePopVlanAction(ByteBuf outBuffer) {
174         outBuffer.writeShort(POP_VLAN_CODE);
175         encodeRestOfActionHeader(outBuffer);
176     }
177     
178     private static void encodePushMplsAction(Action action, ByteBuf outBuffer) {
179         outBuffer.writeShort(PUSH_MPLS_CODE);
180         encodeCommonEthertype(action, outBuffer);
181     }
182     
183     private static void encodePopMplsAction(Action action, ByteBuf outBuffer) {
184         outBuffer.writeShort(POP_MPLS_CODE);
185         encodeCommonEthertype(action, outBuffer);
186     }
187     
188     private static void encodeSetQueueAction(Action action, ByteBuf outBuffer) {
189         outBuffer.writeShort(SET_QUEUE_CODE);
190         outBuffer.writeShort(SET_QUEUE_LENGTH);
191         QueueIdAction queueId = action.getAugmentation(QueueIdAction.class);
192         outBuffer.writeInt(queueId.getQueueId().intValue());
193     }
194
195     private static void encodeGroupAction(Action action, ByteBuf outBuffer) {
196         outBuffer.writeShort(GROUP_CODE);
197         outBuffer.writeShort(GROUP_LENGTH);
198         GroupIdAction groupId = action.getAugmentation(GroupIdAction.class);
199         outBuffer.writeInt(groupId.getGroupId().intValue());
200     }
201     
202     private static void encodeSetNwTtlAction(Action action, ByteBuf outBuffer) {
203         outBuffer.writeShort(SET_NW_TTL_CODE);
204         outBuffer.writeShort(SET_NW_TTL_LENGTH);
205         NwTtlAction nwTtl = action.getAugmentation(NwTtlAction.class);
206         outBuffer.writeByte(nwTtl.getNwTtl());
207         ByteBufUtils.padBuffer(SET_NW_TTL_PADDING, outBuffer);
208     }
209     
210     private static void encodeDecNwTtlAction(ByteBuf outBuffer) {
211         outBuffer.writeShort(DEC_NW_TTL_CODE);
212         encodeRestOfActionHeader(outBuffer);
213     }
214     
215     private static void encodeSetFieldAction(Action action, ByteBuf outBuffer) {
216         OxmFieldsAction oxmField = action.getAugmentation(OxmFieldsAction.class);
217         int length = MatchSerializer.computeMatchEntriesLength(oxmField.getMatchEntries()) + SET_FIELD_HEADER_LENGTH;
218         outBuffer.writeShort(SET_FIELD_CODE);
219         int paddingRemainder = length % EncodeConstants.PADDING;
220         if (paddingRemainder != 0) {
221             length += EncodeConstants.PADDING - paddingRemainder;
222         }
223         outBuffer.writeShort(length);
224         MatchSerializer.encodeMatchEntries(oxmField.getMatchEntries(), outBuffer);
225         if (paddingRemainder != 0) {
226             ByteBufUtils.padBuffer(EncodeConstants.PADDING - paddingRemainder, outBuffer);
227         }
228     }
229     
230     private static void encodePushPbbAction(Action action, ByteBuf outBuffer) {
231         outBuffer.writeShort(PUSH_PBB_CODE);
232         encodeCommonEthertype(action, outBuffer);
233     }
234     
235     private static void encodePopPbbAction(ByteBuf outBuffer) {
236         outBuffer.writeShort(POP_PBB_CODE);
237         encodeRestOfActionHeader(outBuffer);
238     }
239
240     private static void encodeExperimenterAction(Action action, ByteBuf outBuffer) {
241         outBuffer.writeShort(EXPERIMENTER_CODE);
242         outBuffer.writeShort(EXPERIMENTER_LENGTH);
243         ExperimenterAction experimenter = action.getAugmentation(ExperimenterAction.class);
244         outBuffer.writeInt(experimenter.getExperimenter().intValue());
245     }
246     
247     private static void encodeRestOfActionHeader(ByteBuf outBuffer) {
248         outBuffer.writeShort(ACTION_HEADER_LENGTH);
249         ByteBufUtils.padBuffer(PADDING_IN_ACTION_HEADER, outBuffer);
250     }
251     
252     private static void encodeCommonEthertype(Action action, ByteBuf outBuffer) {
253         EthertypeAction ethertype = action.getAugmentation(EthertypeAction.class);
254         outBuffer.writeShort(LENGTH_OF_ETHERTYPE_ACTION);
255         outBuffer.writeShort(ethertype.getEthertype().getValue());
256         ByteBufUtils.padBuffer(ETHERTYPE_ACTION_PADDING, outBuffer);
257     }
258     
259     /**
260      * Computes length of actions
261      * @param actionsList list of actions
262      * @return actions length
263      */
264     public static int computeLengthOfActions(List<ActionsList> actionsList) {
265         int lengthOfActions = 0;
266         if (actionsList != null) {
267             for (ActionsList list : actionsList) {
268                 Action action = list.getAction();
269                 if (action.getType().isAssignableFrom(Output.class)) {
270                     lengthOfActions += OUTPUT_LENGTH;
271                 } else if (action.getType().isAssignableFrom(SetField.class)){
272                     List<MatchEntries> entries = action.getAugmentation(OxmFieldsAction.class).getMatchEntries();
273                     int actionLength = (2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES) + MatchSerializer.computeMatchEntriesLength(entries);
274                     lengthOfActions += actionLength;
275                     int paddingRemainder = actionLength % EncodeConstants.PADDING;
276                     if ((paddingRemainder) != 0) {
277                         lengthOfActions += EncodeConstants.PADDING - paddingRemainder;
278                     }
279                 } else {
280                     lengthOfActions += LENGTH_OF_OTHER_ACTIONS;
281                 }
282             }
283         }
284         return lengthOfActions;
285     }
286 }