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 .setKey(new InstructionKey(0))
96 .setInstruction(new ApplyActionsCaseBuilder()
97 .setApplyActions(new ApplyActionsBuilder()
98 .setAction(Collections.singletonList(new ActionBuilder()
100 .setKey(new ActionKey(0))
101 .setAction(new SetVlanIdActionCaseBuilder()
102 .setSetVlanIdAction(new SetVlanIdActionBuilder()
103 .setVlanId(new VlanId(VLAN_ID))
110 new InstructionBuilder()
112 .setKey(new InstructionKey(2))
113 .setInstruction(new ApplyActionsCaseBuilder()
114 .setApplyActions(new ApplyActionsBuilder()
115 .setAction(Collections.singletonList(new ActionBuilder()
117 .setKey(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 .setKey(new InstructionKey(1))
131 .setInstruction(new ApplyActionsCaseBuilder()
132 .setApplyActions(new ApplyActionsBuilder()
133 .setAction(Collections.singletonList(new ActionBuilder()
135 .setKey(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().getSerializer(new MessageTypeKey<>(EncodeConstants.OF13_VERSION_ID, FlowMessage.class));
186 public void testSerialize() throws Exception {
187 final ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer();
188 serializer.serialize(MESSAGE, out);
190 // Our message was split to 2 flows because it contained set_vlan_id action
193 assertEquals(out.readableBytes(), 0);
196 private void testVlanFalse(final ByteBuf out) {
198 assertEquals(out.readByte(), VERSION.shortValue());
199 assertEquals(out.readByte(), serializer.getMessageType());
200 assertEquals(out.readUnsignedShort(), 144);
201 assertEquals(out.readInt(), XID.intValue());
204 assertEquals(out.readLong(), COOKIE.getValue().longValue());
205 assertEquals(out.readLong(), COOKIE_MASK.getValue().longValue());
206 assertEquals(out.readUnsignedByte(), TABLE_ID.shortValue());
207 assertEquals(out.readUnsignedByte(), COMMAND.getIntValue());
208 assertEquals(out.readUnsignedShort(), IDLE_TIMEOUT.intValue());
209 assertEquals(out.readUnsignedShort(), HARD_TIMEOUT.intValue());
210 assertEquals(out.readUnsignedShort(), PRIORITY.intValue());
211 assertEquals(out.readUnsignedInt(), BUFFER_ID.longValue());
212 assertEquals(out.readUnsignedInt(), OUT_PORT.longValue());
213 assertEquals(out.readUnsignedInt(), OUT_GROUP.longValue());
214 assertEquals(out.readUnsignedShort(), ByteBufUtils.fillBitMask(0,
220 out.skipBytes(PADDING_IN_FLOW_MOD_MESSAGE);
223 int matchLength = 15;
224 assertEquals(out.readShort(), 1); // OXM match type
225 assertEquals(out.readUnsignedShort(), matchLength); // OXM match length
228 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
229 assertEquals(out.readUnsignedByte(), OxmMatchConstants.VLAN_VID << 1);
230 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
231 assertEquals(out.readUnsignedShort(), 0);
234 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
235 assertEquals(out.readUnsignedByte(), OxmMatchConstants.IP_PROTO << 1);
236 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_BYTE_IN_BYTES);
237 assertEquals(out.readUnsignedByte(), IP_PROTOCOL_MATCH.shortValue());
239 int paddingRemainder = matchLength % EncodeConstants.PADDING;
240 if (paddingRemainder != 0) {
241 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
244 // Apply actions instruction
245 int applyActionsLength = 32;
246 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
247 assertEquals(out.readUnsignedShort(), applyActionsLength); // length of actions
248 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
250 // Push vlan action (was injected because we had setvlanid action)
251 assertEquals(out.readUnsignedShort(), ActionConstants.PUSH_VLAN_CODE);
252 assertEquals(out.readUnsignedShort(), ActionConstants.GENERAL_ACTION_LENGTH);
253 assertEquals(out.readUnsignedShort(), 0x8100);
254 out.skipBytes(ActionConstants.ETHERTYPE_ACTION_PADDING);
256 // Set vlan id action
257 int setVlanIdLength = 16;
258 int setVlanStartIndex = out.readerIndex();
259 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
260 assertEquals(out.readUnsignedShort(), setVlanIdLength);
261 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
262 assertEquals(out.readUnsignedByte(), OxmMatchConstants.VLAN_VID << 1);
263 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
264 assertEquals(out.readUnsignedShort(), VLAN_ID | (1 << 12));
266 paddingRemainder = (out.readerIndex() - setVlanStartIndex) % EncodeConstants.PADDING;
267 if (paddingRemainder != 0) {
268 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
271 // Apply actions instruction 2
272 int applyActionsLength2 = 24;
273 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
274 assertEquals(out.readUnsignedShort(), applyActionsLength2); // length of actions
275 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
278 int setTpSrcLength = 16;
279 int setTpSrcStartIndex = out.readerIndex();
280 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
281 assertEquals(out.readUnsignedShort(), setTpSrcLength);
282 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
283 assertEquals(out.readUnsignedByte(), OxmMatchConstants.UDP_SRC << 1);
284 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
285 assertEquals(out.readUnsignedShort(), TP_SRC_PORT.intValue());
287 paddingRemainder = (out.readerIndex() - setTpSrcStartIndex) % EncodeConstants.PADDING;
288 if (paddingRemainder != 0) {
289 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
292 // Apply actions instruction 3
293 int applyActionsLength3 = 24;
294 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
295 assertEquals(out.readUnsignedShort(), applyActionsLength3); // length of actions
296 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
299 int setTpDstLength = 16;
300 int setTpDstStartIndex = out.readerIndex();
301 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
302 assertEquals(out.readUnsignedShort(), setTpDstLength);
303 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
304 assertEquals(out.readUnsignedByte(), OxmMatchConstants.UDP_DST << 1);
305 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
306 assertEquals(out.readUnsignedShort(), TP_DST_PORT.intValue());
308 paddingRemainder = (out.readerIndex() - setTpDstStartIndex) % EncodeConstants.PADDING;
309 if (paddingRemainder != 0) {
310 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
314 private void testVlanTrue(final ByteBuf out) {
318 assertEquals(out.readByte(), VERSION.shortValue());
319 assertEquals(out.readByte(), serializer.getMessageType());
320 assertEquals(out.readUnsignedShort(), 144);
321 assertEquals(out.readInt(), XID.intValue());
324 assertEquals(out.readLong(), COOKIE.getValue().longValue());
325 assertEquals(out.readLong(), COOKIE_MASK.getValue().longValue());
326 assertEquals(out.readUnsignedByte(), TABLE_ID.shortValue());
327 assertEquals(out.readUnsignedByte(), COMMAND.getIntValue());
328 assertEquals(out.readUnsignedShort(), IDLE_TIMEOUT.intValue());
329 assertEquals(out.readUnsignedShort(), HARD_TIMEOUT.intValue());
330 assertEquals(out.readUnsignedShort(), PRIORITY.intValue());
331 assertEquals(out.readUnsignedInt(), BUFFER_ID.longValue());
332 assertEquals(out.readUnsignedInt(), OUT_PORT.longValue());
333 assertEquals(out.readUnsignedInt(), OUT_GROUP.longValue());
334 assertEquals(out.readUnsignedShort(), ByteBufUtils.fillBitMask(0,
340 out.skipBytes(PADDING_IN_FLOW_MOD_MESSAGE);
343 int matchLength = 17;
344 assertEquals(out.readShort(), 1); // OXM match type
345 assertEquals(out.readUnsignedShort(), matchLength); // OXM match length
348 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
349 assertEquals(out.readUnsignedByte(), OxmMatchConstants.VLAN_VID << 1 | 1);
350 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES * 2);
351 assertEquals(out.readUnsignedShort(), (1 << 12));
352 byte[] vlanMask = new byte[2];
353 out.readBytes(vlanMask);
354 assertArrayEquals(vlanMask, new byte[] { 16, 0 });
357 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
358 assertEquals(out.readUnsignedByte(), OxmMatchConstants.IP_PROTO << 1);
359 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_BYTE_IN_BYTES);
360 assertEquals(out.readUnsignedByte(), IP_PROTOCOL_MATCH.shortValue());
362 int paddingRemainder = matchLength % EncodeConstants.PADDING;
363 if (paddingRemainder != 0) {
364 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
367 // Apply actions instruction
368 int applyActionsLength = 24;
369 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
370 assertEquals(out.readUnsignedShort(), applyActionsLength); // length of actions
371 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
373 // Set vlan id action
374 int setVlanIdLength = 16;
375 int setVlanStartIndex = out.readerIndex();
376 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
377 assertEquals(out.readUnsignedShort(), setVlanIdLength);
378 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
379 assertEquals(out.readUnsignedByte(), OxmMatchConstants.VLAN_VID << 1);
380 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
381 assertEquals(out.readUnsignedShort(), VLAN_ID | (1 << 12));
383 paddingRemainder = (out.readerIndex() - setVlanStartIndex) % EncodeConstants.PADDING;
384 if (paddingRemainder != 0) {
385 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
388 // Apply actions instruction 2
389 int applyActionsLength2 = 24;
390 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
391 assertEquals(out.readUnsignedShort(), applyActionsLength2); // length of actions
392 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
395 int setTpSrcLength = 16;
396 int setTpSrcStartIndex = out.readerIndex();
397 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
398 assertEquals(out.readUnsignedShort(), setTpSrcLength);
399 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
400 assertEquals(out.readUnsignedByte(), OxmMatchConstants.UDP_SRC << 1);
401 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
402 assertEquals(out.readUnsignedShort(), TP_SRC_PORT.intValue());
404 paddingRemainder = (out.readerIndex() - setTpSrcStartIndex) % EncodeConstants.PADDING;
405 if (paddingRemainder != 0) {
406 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);
409 // Apply actions instruction 3
410 int applyActionsLength3 = 24;
411 assertEquals(out.readUnsignedShort(), InstructionConstants.APPLY_ACTIONS_TYPE);
412 assertEquals(out.readUnsignedShort(), applyActionsLength3); // length of actions
413 out.skipBytes(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION);
416 int setTpDstLength = 16;
417 int setTpDstStartIndex = out.readerIndex();
418 assertEquals(out.readUnsignedShort(), ActionConstants.SET_FIELD_CODE);
419 assertEquals(out.readUnsignedShort(), setTpDstLength);
420 assertEquals(out.readUnsignedShort(), OxmMatchConstants.OPENFLOW_BASIC_CLASS);
421 assertEquals(out.readUnsignedByte(), OxmMatchConstants.UDP_DST << 1);
422 assertEquals(out.readUnsignedByte(), EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
423 assertEquals(out.readUnsignedShort(), TP_DST_PORT.intValue());
425 paddingRemainder = (out.readerIndex() - setTpDstStartIndex) % EncodeConstants.PADDING;
426 if (paddingRemainder != 0) {
427 out.skipBytes(EncodeConstants.PADDING - paddingRemainder);