blob: 2a93b558e18316d57c6c159a384377d10d3d4414 [file] [log] [blame]
Ray Milkeyd43fe452015-05-29 09:35:12 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.codec.impl;
17
18import java.io.IOException;
19import java.io.InputStream;
20import java.util.SortedMap;
21import java.util.TreeMap;
22
23import org.junit.Before;
24import org.junit.Test;
alshabibcaf1ca22015-06-25 15:18:16 -070025import org.onlab.packet.EthType;
Ray Milkeyd43fe452015-05-29 09:35:12 -070026import org.onlab.packet.Ethernet;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.IpPrefix;
29import org.onlab.packet.MacAddress;
30import org.onlab.packet.MplsLabel;
31import org.onlab.packet.VlanId;
32import org.onosproject.codec.JsonCodec;
33import org.onosproject.core.CoreService;
34import org.onosproject.net.ChannelSpacing;
35import org.onosproject.net.GridType;
36import org.onosproject.net.Lambda;
37import org.onosproject.net.OchSignal;
38import org.onosproject.net.PortNumber;
39import org.onosproject.net.flow.FlowRule;
40import org.onosproject.net.flow.criteria.Criterion;
41import org.onosproject.net.flow.criteria.EthCriterion;
42import org.onosproject.net.flow.criteria.EthTypeCriterion;
43import org.onosproject.net.flow.criteria.IPCriterion;
44import org.onosproject.net.flow.criteria.IPDscpCriterion;
45import org.onosproject.net.flow.criteria.IPEcnCriterion;
46import org.onosproject.net.flow.criteria.IPProtocolCriterion;
47import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
48import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
49import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
50import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
51import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
52import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
53import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
54import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
55import org.onosproject.net.flow.criteria.IndexedLambdaCriterion;
56import org.onosproject.net.flow.criteria.MplsCriterion;
57import org.onosproject.net.flow.criteria.OchSignalCriterion;
58import org.onosproject.net.flow.criteria.PortCriterion;
59import org.onosproject.net.flow.criteria.SctpPortCriterion;
60import org.onosproject.net.flow.criteria.TcpPortCriterion;
61import org.onosproject.net.flow.criteria.UdpPortCriterion;
62import org.onosproject.net.flow.criteria.VlanIdCriterion;
63import org.onosproject.net.flow.criteria.VlanPcpCriterion;
64import org.onosproject.net.flow.instructions.Instruction;
65import org.onosproject.net.flow.instructions.Instructions;
66import org.onosproject.net.flow.instructions.L0ModificationInstruction;
67import org.onosproject.net.flow.instructions.L2ModificationInstruction;
68import org.onosproject.net.flow.instructions.L3ModificationInstruction;
69
70import com.fasterxml.jackson.databind.JsonNode;
71import com.fasterxml.jackson.databind.node.ObjectNode;
72
73import static org.easymock.EasyMock.createMock;
74import static org.easymock.EasyMock.expect;
75import static org.easymock.EasyMock.replay;
76import static org.hamcrest.MatcherAssert.assertThat;
77import static org.hamcrest.Matchers.instanceOf;
78import static org.hamcrest.Matchers.is;
79import static org.hamcrest.Matchers.notNullValue;
80import static org.onosproject.net.NetTestTools.APP_ID;
81
82/**
83 * Flow rule codec unit tests.
84 */
85public class FlowRuleCodecTest {
86
87 MockCodecContext context;
88 JsonCodec<FlowRule> flowRuleCodec;
89 final CoreService mockCoreService = createMock(CoreService.class);
90
91 /**
92 * Sets up for each test. Creates a context and fetches the flow rule
93 * codec.
94 */
95 @Before
96 public void setUp() {
97 context = new MockCodecContext();
98 flowRuleCodec = context.codec(FlowRule.class);
99 assertThat(flowRuleCodec, notNullValue());
100
Ray Milkeyeb5c7172015-06-23 14:59:27 -0700101 expect(mockCoreService.registerApplication(FlowRuleCodec.REST_APP_ID))
Ray Milkeyd43fe452015-05-29 09:35:12 -0700102 .andReturn(APP_ID).anyTimes();
103 replay(mockCoreService);
104 context.registerService(CoreService.class, mockCoreService);
105 }
106
107 /**
108 * Reads in a rule from the given resource and decodes it.
109 *
110 * @param resourceName resource to use to read the JSON for the rule
111 * @return decoded flow rule
112 * @throws IOException if processing the resource fails
113 */
114 private FlowRule getRule(String resourceName) throws IOException {
115 InputStream jsonStream = FlowRuleCodecTest.class
116 .getResourceAsStream(resourceName);
117 JsonNode json = context.mapper().readTree(jsonStream);
118 assertThat(json, notNullValue());
119 FlowRule rule = flowRuleCodec.decode((ObjectNode) json, context);
120 assertThat(rule, notNullValue());
121 return rule;
122 }
123
124 /**
125 * Checks that the data shared by all the resources is correct for a
126 * given rule.
127 *
128 * @param rule rule to check
129 */
130 private void checkCommonData(FlowRule rule) {
131 assertThat(rule.appId(), is(APP_ID.id()));
132 assertThat(rule.isPermanent(), is(false));
133 assertThat(rule.timeout(), is(1));
134 assertThat(rule.priority(), is(1));
135 assertThat(rule.deviceId().toString(), is("of:0000000000000001"));
136 }
137
138 /**
139 * Checks that a simple rule decodes properly.
140 *
141 * @throws IOException if the resource cannot be processed
142 */
143 @Test
144 public void codecSimpleFlowTest() throws IOException {
145 FlowRule rule = getRule("simple-flow.json");
146
147 checkCommonData(rule);
148
149 assertThat(rule.selector().criteria().size(), is(1));
150 Criterion criterion1 = rule.selector().criteria().iterator().next();
151 assertThat(criterion1.type(), is(Criterion.Type.ETH_TYPE));
alshabibcaf1ca22015-06-25 15:18:16 -0700152 assertThat(((EthTypeCriterion) criterion1).ethType(), is(new EthType(2054)));
Ray Milkeyd43fe452015-05-29 09:35:12 -0700153
154 assertThat(rule.treatment().allInstructions().size(), is(1));
155 Instruction instruction1 = rule.treatment().allInstructions().get(0);
156 assertThat(instruction1.type(), is(Instruction.Type.OUTPUT));
157 assertThat(((Instructions.OutputInstruction) instruction1).port(), is(PortNumber.CONTROLLER));
158 }
159
160 SortedMap<String, Instruction> instructions = new TreeMap<>();
161
162 /**
163 * Looks up an instruction in the instruction map based on type and subtype.
164 *
165 * @param type type string
166 * @param subType subtype string
167 * @return instruction that matches
168 */
169 private Instruction getInstruction(Instruction.Type type, String subType) {
170 Instruction instruction = instructions.get(type.name() + "/" + subType);
171 assertThat(instruction, notNullValue());
172 assertThat(instruction.type(), is(type));
173 return instruction;
174 }
175
176 /**
177 * Checks that a rule with one of each instruction type decodes properly.
178 *
179 * @throws IOException if the resource cannot be processed
180 */
181 @Test
182 public void decodeInstructionsFlowTest() throws Exception {
183 FlowRule rule = getRule("instructions-flow.json");
184
185 checkCommonData(rule);
186
187 rule.treatment().allInstructions()
188 .stream()
189 .forEach(instruction ->
190 {
191 String subType;
192 if (instruction.type() == Instruction.Type.L0MODIFICATION) {
193 subType = ((L0ModificationInstruction) instruction)
194 .subtype().name();
195 } else if (instruction.type() == Instruction.Type.L2MODIFICATION) {
196 subType = ((L2ModificationInstruction) instruction)
197 .subtype().name();
198 } else if (instruction.type() == Instruction.Type.L3MODIFICATION) {
199 subType = ((L3ModificationInstruction) instruction)
200 .subtype().name();
201 } else {
202 subType = "";
203 }
204 instructions.put(
205 instruction.type().name() + "/" + subType, instruction);
206 });
207
208 assertThat(rule.treatment().allInstructions().size(), is(19));
209
210 Instruction instruction;
211
212 instruction = getInstruction(Instruction.Type.OUTPUT, "");
213 assertThat(instruction.type(), is(Instruction.Type.OUTPUT));
214 assertThat(((Instructions.OutputInstruction) instruction).port(), is(PortNumber.CONTROLLER));
215
216 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
217 L2ModificationInstruction.L2SubType.ETH_SRC.name());
218 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
219 assertThat(((L2ModificationInstruction.ModEtherInstruction) instruction).mac(),
220 is(MacAddress.valueOf("12:34:56:78:90:12")));
221
222 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
223 L2ModificationInstruction.L2SubType.ETH_DST.name());
224 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
225 assertThat(((L2ModificationInstruction.ModEtherInstruction) instruction).mac(),
226 is(MacAddress.valueOf("98:76:54:32:01:00")));
227
228 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
229 L2ModificationInstruction.L2SubType.VLAN_ID.name());
230 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
231 assertThat(((L2ModificationInstruction.ModVlanIdInstruction) instruction).vlanId().toShort(),
232 is((short) 22));
233
234 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
235 L2ModificationInstruction.L2SubType.VLAN_PCP.name());
236 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
237 assertThat(((L2ModificationInstruction.ModVlanPcpInstruction) instruction).vlanPcp(),
238 is((byte) 1));
239
240 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
241 L2ModificationInstruction.L2SubType.MPLS_LABEL.name());
242 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
243 assertThat(((L2ModificationInstruction.ModMplsLabelInstruction) instruction)
244 .label().shortValue(),
245 is((short) 777));
246
247 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
248 L2ModificationInstruction.L2SubType.MPLS_PUSH.name());
249 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
250 assertThat((short) ((L2ModificationInstruction.PushHeaderInstructions) instruction)
251 .ethernetType(),
252 is(Ethernet.MPLS_UNICAST));
253
254 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
255 L2ModificationInstruction.L2SubType.MPLS_POP.name());
256 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
257 assertThat((short) ((L2ModificationInstruction.PushHeaderInstructions) instruction)
258 .ethernetType(),
259 is(Ethernet.MPLS_UNICAST));
260
261 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
262 L2ModificationInstruction.L2SubType.DEC_MPLS_TTL.name());
263 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
264 assertThat(instruction, instanceOf(L2ModificationInstruction.ModMplsTtlInstruction.class));
265
266 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
267 L2ModificationInstruction.L2SubType.VLAN_POP.name());
268 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
269 assertThat(instruction, instanceOf(L2ModificationInstruction.PopVlanInstruction.class));
270
271 instruction = getInstruction(Instruction.Type.L2MODIFICATION,
272 L2ModificationInstruction.L2SubType.VLAN_PUSH.name());
273 assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
274 assertThat(instruction, instanceOf(L2ModificationInstruction.PushHeaderInstructions.class));
275
276 instruction = getInstruction(Instruction.Type.L3MODIFICATION,
277 L3ModificationInstruction.L3SubType.IPV4_SRC.name());
278 assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
279 assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
280 is(IpAddress.valueOf("1.2.3.4")));
281
282 instruction = getInstruction(Instruction.Type.L3MODIFICATION,
283 L3ModificationInstruction.L3SubType.IPV4_DST.name());
284 assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
285 assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
286 is(IpAddress.valueOf("1.2.3.3")));
287
288 instruction = getInstruction(Instruction.Type.L3MODIFICATION,
289 L3ModificationInstruction.L3SubType.IPV6_SRC.name());
290 assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
291 assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
292 is(IpAddress.valueOf("1.2.3.2")));
293
294 instruction = getInstruction(Instruction.Type.L3MODIFICATION,
295 L3ModificationInstruction.L3SubType.IPV6_DST.name());
296 assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
297 assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
298 is(IpAddress.valueOf("1.2.3.1")));
299
300 instruction = getInstruction(Instruction.Type.L3MODIFICATION,
301 L3ModificationInstruction.L3SubType.IPV6_FLABEL.name());
302 assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
303 assertThat(((L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction)
304 .flowLabel(),
305 is(8));
306
307 instruction = getInstruction(Instruction.Type.L0MODIFICATION,
308 L0ModificationInstruction.L0SubType.LAMBDA.name());
309 assertThat(instruction.type(), is(Instruction.Type.L0MODIFICATION));
310 assertThat(((L0ModificationInstruction.ModLambdaInstruction) instruction)
311 .lambda(),
312 is((short) 7));
313
314 instruction = getInstruction(Instruction.Type.L0MODIFICATION,
315 L0ModificationInstruction.L0SubType.OCH.name());
316 assertThat(instruction.type(), is(Instruction.Type.L0MODIFICATION));
317 L0ModificationInstruction.ModOchSignalInstruction och =
318 (L0ModificationInstruction.ModOchSignalInstruction) instruction;
319 assertThat(och.lambda().spacingMultiplier(), is(4));
320 assertThat(och.lambda().slotGranularity(), is(8));
321 assertThat(och.lambda().gridType(), is(GridType.DWDM));
322 assertThat(och.lambda().channelSpacing(), is(ChannelSpacing.CHL_100GHZ));
323 }
324
325 SortedMap<String, Criterion> criteria = new TreeMap<>();
326
327 /**
328 * Looks up a criterion in the instruction map based on type and subtype.
329 *
330 * @param type type string
331 * @return criterion that matches
332 */
333 private Criterion getCriterion(Criterion.Type type) {
334 Criterion criterion = criteria.get(type.name());
335 assertThat(criterion.type(), is(type));
336 return criterion;
337 }
338
339 /**
340 * Checks that a rule with one of each kind of criterion decodes properly.
341 *
342 * @throws IOException if the resource cannot be processed
343 */
344 @Test
345 public void codecCriteriaFlowTest() throws Exception {
346 FlowRule rule = getRule("criteria-flow.json");
347
348 checkCommonData(rule);
349
350 assertThat(rule.selector().criteria().size(), is(32));
351
352 rule.selector().criteria()
353 .stream()
354 .forEach(criterion ->
355 criteria.put(criterion.type().name(), criterion));
356
357 Criterion criterion;
358
359 criterion = getCriterion(Criterion.Type.ETH_TYPE);
alshabibcaf1ca22015-06-25 15:18:16 -0700360 assertThat(((EthTypeCriterion) criterion).ethType(), is(new EthType(2054)));
Ray Milkeyd43fe452015-05-29 09:35:12 -0700361
362 criterion = getCriterion(Criterion.Type.ETH_DST);
363 assertThat(((EthCriterion) criterion).mac(),
364 is(MacAddress.valueOf("00:11:22:33:44:55")));
365
366 criterion = getCriterion(Criterion.Type.ETH_SRC);
367 assertThat(((EthCriterion) criterion).mac(),
368 is(MacAddress.valueOf("00:11:22:33:44:55")));
369
370 criterion = getCriterion(Criterion.Type.IN_PORT);
371 assertThat(((PortCriterion) criterion).port(),
372 is(PortNumber.portNumber(23)));
373
374 criterion = getCriterion(Criterion.Type.IN_PHY_PORT);
375 assertThat(((PortCriterion) criterion).port(),
376 is(PortNumber.portNumber(44)));
377
378 criterion = getCriterion(Criterion.Type.VLAN_VID);
379 assertThat(((VlanIdCriterion) criterion).vlanId(),
380 is(VlanId.vlanId((short) 777)));
381
382 criterion = getCriterion(Criterion.Type.VLAN_PCP);
383 assertThat(((VlanPcpCriterion) criterion).priority(),
384 is(((byte) 3)));
385
386 criterion = getCriterion(Criterion.Type.IP_DSCP);
387 assertThat(((IPDscpCriterion) criterion).ipDscp(),
388 is(((byte) 2)));
389
390 criterion = getCriterion(Criterion.Type.IP_ECN);
391 assertThat(((IPEcnCriterion) criterion).ipEcn(),
392 is(((byte) 1)));
393
394 criterion = getCriterion(Criterion.Type.IP_PROTO);
395 assertThat(((IPProtocolCriterion) criterion).protocol(),
396 is(((short) 4)));
397
398 criterion = getCriterion(Criterion.Type.IPV4_SRC);
399 assertThat(((IPCriterion) criterion).ip(),
400 is((IpPrefix.valueOf("1.2.0.0/32"))));
401
402 criterion = getCriterion(Criterion.Type.IPV4_DST);
403 assertThat(((IPCriterion) criterion).ip(),
404 is((IpPrefix.valueOf("2.2.0.0/32"))));
405
406 criterion = getCriterion(Criterion.Type.IPV6_SRC);
407 assertThat(((IPCriterion) criterion).ip(),
408 is((IpPrefix.valueOf("3.2.0.0/32"))));
409
410 criterion = getCriterion(Criterion.Type.IPV6_DST);
411 assertThat(((IPCriterion) criterion).ip(),
412 is((IpPrefix.valueOf("4.2.0.0/32"))));
413
414 criterion = getCriterion(Criterion.Type.TCP_SRC);
415 assertThat(((TcpPortCriterion) criterion).tcpPort(),
416 is(80));
417
418 criterion = getCriterion(Criterion.Type.TCP_DST);
419 assertThat(((TcpPortCriterion) criterion).tcpPort(),
420 is(443));
421
422 criterion = getCriterion(Criterion.Type.UDP_SRC);
423 assertThat(((UdpPortCriterion) criterion).udpPort(),
424 is(180));
425
426 criterion = getCriterion(Criterion.Type.UDP_DST);
427 assertThat(((UdpPortCriterion) criterion).udpPort(),
428 is(1443));
429
430 criterion = getCriterion(Criterion.Type.SCTP_SRC);
431 assertThat(((SctpPortCriterion) criterion).sctpPort(),
432 is(280));
433
434 criterion = getCriterion(Criterion.Type.SCTP_DST);
435 assertThat(((SctpPortCriterion) criterion).sctpPort(),
436 is(2443));
437
438 criterion = getCriterion(Criterion.Type.ICMPV4_TYPE);
439 assertThat(((IcmpTypeCriterion) criterion).icmpType(),
440 is((short) 24));
441
442 criterion = getCriterion(Criterion.Type.ICMPV4_CODE);
443 assertThat(((IcmpCodeCriterion) criterion).icmpCode(),
444 is((short) 16));
445
446 criterion = getCriterion(Criterion.Type.ICMPV6_TYPE);
447 assertThat(((Icmpv6TypeCriterion) criterion).icmpv6Type(),
448 is((short) 14));
449
450 criterion = getCriterion(Criterion.Type.ICMPV6_CODE);
451 assertThat(((Icmpv6CodeCriterion) criterion).icmpv6Code(),
452 is((short) 6));
453
454 criterion = getCriterion(Criterion.Type.IPV6_FLABEL);
455 assertThat(((IPv6FlowLabelCriterion) criterion).flowLabel(),
456 is(8));
457
458 criterion = getCriterion(Criterion.Type.IPV6_ND_TARGET);
459 assertThat(((IPv6NDTargetAddressCriterion) criterion)
460 .targetAddress().toString(),
461 is("1111:2222:3333:4444:5555:6666:7777:8888"));
462
463 criterion = getCriterion(Criterion.Type.IPV6_ND_SLL);
464 assertThat(((IPv6NDLinkLayerAddressCriterion) criterion).mac(),
465 is(MacAddress.valueOf("00:11:22:33:44:56")));
466
467 criterion = getCriterion(Criterion.Type.IPV6_ND_TLL);
468 assertThat(((IPv6NDLinkLayerAddressCriterion) criterion).mac(),
469 is(MacAddress.valueOf("00:11:22:33:44:57")));
470
471 criterion = getCriterion(Criterion.Type.MPLS_LABEL);
472 assertThat(((MplsCriterion) criterion).label(),
473 is(MplsLabel.mplsLabel(123)));
474
475 criterion = getCriterion(Criterion.Type.IPV6_EXTHDR);
476 assertThat(((IPv6ExthdrFlagsCriterion) criterion).exthdrFlags(),
477 is(99));
478
479 criterion = getCriterion(Criterion.Type.OCH_SIGID);
480 assertThat(((IndexedLambdaCriterion) criterion).lambda(),
481 is(Lambda.indexedLambda(122)));
482 }
483
484 /**
485 * Checks that a rule with a SigId criterion decodes properly.
486 *
487 * @throws IOException if the resource cannot be processed
488 */
489 @Test
490 public void codecSigIdCriteriaFlowTest() throws Exception {
491 FlowRule rule = getRule("sigid-flow.json");
492
493 checkCommonData(rule);
494
495 assertThat(rule.selector().criteria().size(), is(1));
496 Criterion criterion = rule.selector().criteria().iterator().next();
497 assertThat(criterion.type(), is(Criterion.Type.OCH_SIGID));
498 Lambda lambda = ((OchSignalCriterion) criterion).lambda();
499 assertThat(lambda, instanceOf(OchSignal.class));
500 OchSignal ochSignal = (OchSignal) lambda;
501 assertThat(ochSignal.spacingMultiplier(), is(3));
502 assertThat(ochSignal.slotGranularity(), is(4));
503 assertThat(ochSignal.gridType(), is(GridType.CWDM));
504 assertThat(ochSignal.channelSpacing(), is(ChannelSpacing.CHL_25GHZ));
505 }
506
507}