1 /* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */
\r
2 package org.opendaylight.openflowjava.protocol.impl.util;
\r
4 import io.netty.buffer.ByteBuf;
\r
6 import java.util.List;
\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
39 * Serializes ofp_actions (OpenFlow v1.3)
\r
40 * @author michal.polkorab
\r
41 * @author timotej.kubas
\r
43 public abstract class ActionsSerializer {
\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
80 * Encodes actions to ByteBuf
\r
81 * @param actionsList list of actions to be encoded
\r
82 * @param outBuffer output ByteBuf
\r
84 public static void encodeActions(List<ActionsList> actionsList, ByteBuf outBuffer) {
\r
85 if (actionsList == null) {
\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
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
138 private static void encodeCopyTtlOutAction(ByteBuf outBuffer) {
\r
139 outBuffer.writeShort(COPY_TTL_OUT_CODE);
\r
140 encodeRestOfActionHeader(outBuffer);
\r
143 private static void encodeCopyTtlInAction(ByteBuf outBuffer) {
\r
144 outBuffer.writeShort(COPY_TTL_IN_CODE);
\r
145 encodeRestOfActionHeader(outBuffer);
\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
156 private static void encodeDecMplsTtlAction(ByteBuf outBuffer) {
\r
157 outBuffer.writeShort(DEC_MPLS_TTL_CODE);
\r
158 encodeRestOfActionHeader(outBuffer);
\r
161 private static void encodePushVlanAction(Action action, ByteBuf outBuffer) {
\r
162 outBuffer.writeShort(PUSH_VLAN_CODE);
\r
163 encodeCommonEthertype(action, outBuffer);
\r
166 private static void encodePopVlanAction(ByteBuf outBuffer) {
\r
167 outBuffer.writeShort(POP_VLAN_CODE);
\r
168 encodeRestOfActionHeader(outBuffer);
\r
171 private static void encodePushMplsAction(Action action, ByteBuf outBuffer) {
\r
172 outBuffer.writeShort(PUSH_MPLS_CODE);
\r
173 encodeCommonEthertype(action, outBuffer);
\r
176 private static void encodePopMplsAction(Action action, ByteBuf outBuffer) {
\r
177 outBuffer.writeShort(POP_MPLS_CODE);
\r
178 encodeCommonEthertype(action, outBuffer);
\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
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
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
203 private static void encodeDecNwTtlAction(ByteBuf outBuffer) {
\r
204 outBuffer.writeShort(DEC_NW_TTL_CODE);
\r
205 encodeRestOfActionHeader(outBuffer);
\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
216 outBuffer.writeShort(length);
\r
217 MatchSerializer.encodeMatchEntries(oxmField.getMatchEntries(), outBuffer);
\r
218 ByteBufUtils.padBuffer(EncodeConstants.PADDING - paddingRemainder, outBuffer);
\r
221 private static void encodePushPbbAction(Action action, ByteBuf outBuffer) {
\r
222 outBuffer.writeShort(PUSH_PBB_CODE);
\r
223 encodeCommonEthertype(action, outBuffer);
\r
226 private static void encodePopPbbAction(ByteBuf outBuffer) {
\r
227 outBuffer.writeShort(POP_PBB_CODE);
\r
228 encodeRestOfActionHeader(outBuffer);
\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
238 private static void encodeRestOfActionHeader(ByteBuf outBuffer) {
\r
239 outBuffer.writeShort(ACTION_HEADER_LENGTH);
\r
240 ByteBufUtils.padBuffer(PADDING_IN_ACTION_HEADER, outBuffer);
\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
251 * Computes length of actions
\r
252 * @param actionsList list of actions
\r
253 * @return actions length
\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
271 lengthOfActions += LENGTH_OF_OTHER_ACTIONS;
\r
275 return lengthOfActions;
\r