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