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