2 * Copyright (c) 2016 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.impl.protocol.serialization.messages;
11 import static org.junit.Assert.assertArrayEquals;
12 import static org.junit.Assert.assertEquals;
14 import io.netty.buffer.ByteBuf;
15 import io.netty.buffer.UnpooledByteBufAllocator;
16 import java.math.BigInteger;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import org.junit.Test;
20 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
21 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
22 import org.opendaylight.openflowjava.protocol.api.util.OxmMatchConstants;
23 import org.opendaylight.openflowjava.protocol.impl.util.ActionConstants;
24 import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants;
25 import org.opendaylight.openflowjava.util.ByteBufUtils;
26 import org.opendaylight.openflowplugin.impl.protocol.serialization.AbstractSerializerTest;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCaseBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCaseBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.dst.action._case.SetTpDstActionBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.tp.src.action._case.SetTpSrcActionBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.vlan.id.action._case.SetVlanIdActionBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowMessage;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowMessageBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
52 public class FlowMessageSerializerTest extends AbstractSerializerTest {
53 private static final byte PADDING_IN_FLOW_MOD_MESSAGE = 2;
55 private static final Long XID = 42L;
56 private static final Short VERSION = EncodeConstants.OF13_VERSION_ID;
57 private static final Short TABLE_ID = 2;
58 private static final Boolean STRICT = true;
59 private static final Integer PRIORITY = 10;
60 private static final FlowModCommand COMMAND = FlowModCommand.OFPFCADD;
61 private static final Boolean BARRIER = false;
62 private static final Long BUFFER_ID = 12L;
63 private static final String CONTAINER_NAME = "openflow:1";
64 private static final FlowCookie COOKIE = new FlowCookie(BigInteger.ONE);
65 private static final FlowCookie COOKIE_MASK = new FlowCookie(BigInteger.ZERO);
66 private static final String FLOW_NAME = "flowflow";
67 private static final Integer HARD_TIMEOUT = 10;
68 private static final Integer IDLE_TIMEOUT = 5;
69 private static final Boolean INSTALL_HW = true;
70 private static final Long OUT_GROUP = 1L;
71 private static final BigInteger OUT_PORT = BigInteger.TEN;
74 private static final Boolean IS_CHECKOVERLAP = true;
75 private static final Boolean IS_NOBYTCOUNTS = false;
76 private static final Boolean IS_NOPKTCOUNTS = false;
77 private static final Boolean IS_RESETCOUNTS = true;
78 private static final Boolean IS_SENDFLOWREM = false;
79 private static final FlowModFlags FLAGS = new FlowModFlags(
86 private static final Integer VLAN_ID = 1;
87 private static final Short IP_PROTOCOL = (short) 6; // TCP
89 private static final Integer TP_SRC_PORT = 22;
90 private static final Integer TP_DST_PORT = 23;
91 private static final Instructions INSTRUCTIONS = new InstructionsBuilder()
92 .setInstruction(Arrays.asList(
93 new InstructionBuilder()
95 .withKey(new InstructionKey(0))
96 .setInstruction(new ApplyActionsCaseBuilder()
97 .setApplyActions(new ApplyActionsBuilder()
98 .setAction(Collections.singletonList(new ActionBuilder()
100 .withKey(new ActionKey(0))
101 .setAction(new SetVlanIdActionCaseBuilder()
102 .setSetVlanIdAction(new SetVlanIdActionBuilder()
103 .setVlanId(new VlanId(VLAN_ID))
110 new InstructionBuilder()
112 .withKey(new InstructionKey(2))
113 .setInstruction(new ApplyActionsCaseBuilder()
114 .setApplyActions(new ApplyActionsBuilder()
115 .setAction(Collections.singletonList(new ActionBuilder()
117 .withKey(new ActionKey(0))
118 .setAction(new SetTpDstActionCaseBuilder()
119 .setSetTpDstAction(new SetTpDstActionBuilder()
120 .setIpProtocol(IP_PROTOCOL)
121 .setPort(new PortNumber(TP_DST_PORT))
128 new InstructionBuilder()
130 .withKey(new InstructionKey(1))
131 .setInstruction(new ApplyActionsCaseBuilder()
132 .setApplyActions(new ApplyActionsBuilder()
133 .setAction(Collections.singletonList(new ActionBuilder()
135 .withKey(new ActionKey(0))
136 .setAction(new SetTpSrcActionCaseBuilder()
137 .setSetTpSrcAction(new SetTpSrcActionBuilder()
138 .setIpProtocol(IP_PROTOCOL)
139 .setPort(new PortNumber(TP_SRC_PORT))
148 private static final Short IP_PROTOCOL_MATCH = (short) 17;
149 private static final Match MATCH = new MatchBuilder()
150 .setIpMatch(new IpMatchBuilder()
151 .setIpProtocol(IP_PROTOCOL_MATCH)
155 private static final FlowMessage MESSAGE = new FlowMessageBuilder()
158 .setTableId(TABLE_ID)
160 .setPriority(PRIORITY)
163 .setBufferId(BUFFER_ID)
164 .setContainerName(CONTAINER_NAME)
166 .setCookieMask(COOKIE_MASK)
168 .setFlowName(FLOW_NAME)
169 .setHardTimeout(HARD_TIMEOUT)
170 .setIdleTimeout(IDLE_TIMEOUT)
171 .setInstallHw(INSTALL_HW)
172 .setOutGroup(OUT_GROUP)
173 .setOutPort(OUT_PORT)
174 .setInstructions(INSTRUCTIONS)
178 private FlowMessageSerializer serializer;
181 protected void init() {
182 serializer = getRegistry()
183 .getSerializer(new MessageTypeKey<>(EncodeConstants.OF13_VERSION_ID, FlowMessage.class));
187 public void testSerialize() {
188 final ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer();
189 serializer.serialize(MESSAGE, out);
191 // Our message was split to 2 flows because it contained set_vlan_id action
194 assertEquals(out.readableBytes(), 0);
197 private void testVlanFalse(final ByteBuf out) {
199 assertEquals(out.readByte(), VERSION.shortValue());
200 assertEquals(out.readByte(), serializer.getMessageType());
201 assertEquals(out.readUnsignedShort(), 144);
202 assertEquals(out.readInt(), XID.intValue());
205 assertEquals(out.readLong(), COOKIE.getValue().longValue());
206 assertEquals(out.readLong(), COOKIE_MASK.getValue().longValue());
207 assertEquals(out.readUnsignedByte(), TABLE_ID.shortValue());
208 assertEquals(out.readUnsignedByte(), COMMAND.getIntValue());
209 assertEquals(out.readUnsignedShort(), IDLE_TIMEOUT.intValue());
210 assertEquals(out.readUnsignedShort(), HARD_TIMEOUT.intValue());
211 assertEquals(out.readUnsignedShort(), PRIORITY.intValue());
212 assertEquals(out.readUnsignedInt(), BUFFER_ID.longValue());
213 assertEquals(out.readUnsignedInt(), OUT_PORT.longValue());
214 assertEquals(out.readUnsignedInt(), OUT_GROUP.longValue());
215 assertEquals(out.readUnsignedShort(), ByteBufUtils.fillBitMask(0,
221 out.skipBytes(PADDING_IN_FLOW_MOD_MESSAGE);
224 int matchLength = 15;
225 assertEquals(out.readShort(), 1); // OXM match type
226 assertEquals(out.readUnsignedShort(), matchLength); // OXM match length
229 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
230 assertEquals(out.readUnsignedByte(), OxmMatchConstants.VLAN_VID << 1);
231 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
232 assertEquals(out.readUnsignedShort(), 0);
235 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
236 assertEquals(out.readUnsignedByte(), OxmMatchConstants.IP_PROTO << 1);
237 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_BYTE_IN_BYTES);
238 assertEquals(out.readUnsignedByte(), IP_PROTOCOL_MATCH.shortValue());
240 int paddingRemainder = matchLength % EncodeConstants.PADDING;
241 if (paddingRemainder != 0) {
242 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
245 // Apply actions instruction
246 int applyActionsLength = 32;
247 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
248 assertEquals(out.readUnsignedShort(), applyActionsLength); // length of actions
249 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
251 // Push vlan action (was injected because we had setvlanid action)
252 assertEquals(out.readUnsignedShort(), ActionConstants.PUSH_VLAN_CODE);
253 assertEquals(out.readUnsignedShort(), ActionConstants.GENERAL_ACTION_LENGTH);
254 assertEquals(out.readUnsignedShort(), 0x8100);
255 out.skipBytes(ActionConstants.ETHERTYPE_ACTION_PADDING);
257 // Set vlan id action
258 int setVlanIdLength = 16;
259 final int setVlanStartIndex = out.readerIndex();
260 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
261 assertEquals(out.readUnsignedShort(), setVlanIdLength);
262 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
263 assertEquals(out.readUnsignedByte(), OxmMatchConstants.VLAN_VID << 1);
264 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
265 assertEquals(out.readUnsignedShort(), VLAN_ID | (1 << 12));
267 paddingRemainder = (out.readerIndex() - setVlanStartIndex) % EncodeConstants.PADDING;
268 if (paddingRemainder != 0) {
269 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
272 // Apply actions instruction 2
273 int applyActionsLength2 = 24;
274 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
275 assertEquals(out.readUnsignedShort(), applyActionsLength2); // length of actions
276 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
279 int setTpSrcLength = 16;
280 final int setTpSrcStartIndex = out.readerIndex();
281 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
282 assertEquals(out.readUnsignedShort(), setTpSrcLength);
283 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
284 assertEquals(out.readUnsignedByte(), OxmMatchConstants.UDP_SRC << 1);
285 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
286 assertEquals(out.readUnsignedShort(), TP_SRC_PORT.intValue());
288 paddingRemainder = (out.readerIndex() - setTpSrcStartIndex) % EncodeConstants.PADDING;
289 if (paddingRemainder != 0) {
290 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
293 // Apply actions instruction 3
294 int applyActionsLength3 = 24;
295 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
296 assertEquals(out.readUnsignedShort(), applyActionsLength3); // length of actions
297 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
300 int setTpDstLength = 16;
301 final int setTpDstStartIndex = out.readerIndex();
302 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
303 assertEquals(out.readUnsignedShort(), setTpDstLength);
304 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
305 assertEquals(out.readUnsignedByte(), OxmMatchConstants.UDP_DST << 1);
306 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
307 assertEquals(out.readUnsignedShort(), TP_DST_PORT.intValue());
309 paddingRemainder = (out.readerIndex() - setTpDstStartIndex) % EncodeConstants.PADDING;
310 if (paddingRemainder != 0) {
311 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
315 private void testVlanTrue(final ByteBuf out) {
319 assertEquals(out.readByte(), VERSION.shortValue());
320 assertEquals(out.readByte(), serializer.getMessageType());
321 assertEquals(out.readUnsignedShort(), 144);
322 assertEquals(out.readInt(), XID.intValue());
325 assertEquals(out.readLong(), COOKIE.getValue().longValue());
326 assertEquals(out.readLong(), COOKIE_MASK.getValue().longValue());
327 assertEquals(out.readUnsignedByte(), TABLE_ID.shortValue());
328 assertEquals(out.readUnsignedByte(), COMMAND.getIntValue());
329 assertEquals(out.readUnsignedShort(), IDLE_TIMEOUT.intValue());
330 assertEquals(out.readUnsignedShort(), HARD_TIMEOUT.intValue());
331 assertEquals(out.readUnsignedShort(), PRIORITY.intValue());
332 assertEquals(out.readUnsignedInt(), BUFFER_ID.longValue());
333 assertEquals(out.readUnsignedInt(), OUT_PORT.longValue());
334 assertEquals(out.readUnsignedInt(), OUT_GROUP.longValue());
335 assertEquals(out.readUnsignedShort(), ByteBufUtils.fillBitMask(0,
341 out.skipBytes(PADDING_IN_FLOW_MOD_MESSAGE);
344 int matchLength = 17;
345 assertEquals(out.readShort(), 1); // OXM match type
346 assertEquals(out.readUnsignedShort(), matchLength); // OXM match length
349 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
350 assertEquals(out.readUnsignedByte(), OxmMatchConstants.VLAN_VID << 1 | 1);
351 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES * 2);
352 assertEquals(out.readUnsignedShort(), (1 << 12));
353 byte[] vlanMask = new byte[2];
354 out.readBytes(vlanMask);
355 assertArrayEquals(vlanMask, new byte[] { 16, 0 });
358 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
359 assertEquals(out.readUnsignedByte(), OxmMatchConstants.IP_PROTO << 1);
360 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_BYTE_IN_BYTES);
361 assertEquals(out.readUnsignedByte(), IP_PROTOCOL_MATCH.shortValue());
363 int paddingRemainder = matchLength % EncodeConstants.PADDING;
364 if (paddingRemainder != 0) {
365 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
368 // Apply actions instruction
369 int applyActionsLength = 24;
370 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
371 assertEquals(out.readUnsignedShort(), applyActionsLength); // length of actions
372 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
374 // Set vlan id action
375 int setVlanIdLength = 16;
376 final int setVlanStartIndex = out.readerIndex();
377 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
378 assertEquals(out.readUnsignedShort(), setVlanIdLength);
379 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
380 assertEquals(out.readUnsignedByte(), OxmMatchConstants.VLAN_VID << 1);
381 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
382 assertEquals(out.readUnsignedShort(), VLAN_ID | (1 << 12));
384 paddingRemainder = (out.readerIndex() - setVlanStartIndex) % EncodeConstants.PADDING;
385 if (paddingRemainder != 0) {
386 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
389 // Apply actions instruction 2
390 int applyActionsLength2 = 24;
391 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
392 assertEquals(out.readUnsignedShort(), applyActionsLength2); // length of actions
393 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
396 int setTpSrcLength = 16;
397 final int setTpSrcStartIndex = out.readerIndex();
398 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
399 assertEquals(out.readUnsignedShort(), setTpSrcLength);
400 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
401 assertEquals(out.readUnsignedByte(), OxmMatchConstants.UDP_SRC << 1);
402 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
403 assertEquals(out.readUnsignedShort(), TP_SRC_PORT.intValue());
405 paddingRemainder = (out.readerIndex() - setTpSrcStartIndex) % EncodeConstants.PADDING;
406 if (paddingRemainder != 0) {
407 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
410 // Apply actions instruction 3
411 int applyActionsLength3 = 24;
412 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
413 assertEquals(out.readUnsignedShort(), applyActionsLength3); // length of actions
414 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
417 int setTpDstLength = 16;
418 final int setTpDstStartIndex = out.readerIndex();
419 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
420 assertEquals(out.readUnsignedShort(), setTpDstLength);
421 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
422 assertEquals(out.readUnsignedByte(), OxmMatchConstants.UDP_DST << 1);
423 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
424 assertEquals(out.readUnsignedShort(), TP_DST_PORT.intValue());
426 paddingRemainder = (out.readerIndex() - setTpDstStartIndex) % EncodeConstants.PADDING;
427 if (paddingRemainder != 0) {
428 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);