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