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