blob: 0cdadb5d4c75fbf5e516773a830d3e8c55851fc9 [file] [log] [blame]
Rimon Ashkenazya4e3bd32016-02-22 16:12:20 +02001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Rimon Ashkenazya4e3bd32016-02-22 16:12:20 +02003 *
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.net.intent.impl.compiler;
17
18import org.easymock.EasyMock;
19import org.junit.After;
20import org.junit.Before;
21import org.junit.Test;
22import org.onlab.packet.ChassisId;
23import org.onosproject.TestApplicationId;
24import org.onosproject.cfg.ComponentConfigService;
25import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
27import org.onosproject.core.IdGenerator;
28import org.onosproject.net.Annotations;
29import org.onosproject.net.ChannelSpacing;
30import org.onosproject.net.DefaultAnnotations;
31import org.onosproject.net.CltSignalType;
32import org.onosproject.net.ConnectPoint;
33import org.onosproject.net.DefaultDevice;
34import org.onosproject.net.Device;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.OchPort;
37import org.onosproject.net.OchSignal;
38import org.onosproject.net.OduCltPort;
39import org.onosproject.net.OduSignalId;
40import org.onosproject.net.OduSignalType;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020041import org.onosproject.net.OduSignalUtils;
Rimon Ashkenazya4e3bd32016-02-22 16:12:20 +020042import org.onosproject.net.Port;
43import org.onosproject.net.PortNumber;
44import org.onosproject.net.TributarySlot;
45import org.onosproject.net.flow.DefaultTrafficSelector;
46import org.onosproject.net.flow.DefaultTrafficTreatment;
47import org.onosproject.net.flow.FlowRule;
48import org.onosproject.net.flow.TrafficSelector;
49import org.onosproject.net.flow.TrafficTreatment;
50import org.onosproject.net.flow.criteria.Criteria;
51import org.onosproject.net.flow.instructions.Instructions;
52import org.onosproject.net.intent.FlowRuleIntent;
53import org.onosproject.net.intent.Intent;
54import org.onosproject.net.intent.IntentExtensionService;
55import org.onosproject.net.intent.IntentId;
56import org.onosproject.net.intent.IntentServiceAdapter;
57import org.onosproject.net.intent.Key;
58import org.onosproject.net.intent.MockIdGenerator;
59import org.onosproject.net.intent.OpticalCircuitIntent;
60import org.onosproject.net.provider.ProviderId;
Sho SHIMIZU739873b2016-02-23 17:02:12 -080061import org.onosproject.net.intent.IntentSetMultimap;
Rimon Ashkenazya4e3bd32016-02-22 16:12:20 +020062import org.onosproject.net.behaviour.TributarySlotQuery;
63import org.onosproject.net.device.DeviceServiceAdapter;
64import org.onosproject.net.driver.Behaviour;
65import org.onosproject.net.driver.DefaultDriver;
66import org.onosproject.net.driver.Driver;
67import org.onosproject.net.driver.DriverHandler;
68import org.onosproject.net.driver.DriverService;
69import org.onosproject.net.driver.TestBehaviourImpl;
70import org.onosproject.net.driver.TestBehaviourTwoImpl;
71
72import com.google.common.collect.ImmutableList;
73import com.google.common.collect.ImmutableMap;
74import com.google.common.collect.ImmutableSet;
75import com.google.common.collect.Sets;
76
77import java.util.ArrayList;
78import java.util.Collection;
79import java.util.Collections;
80import java.util.HashSet;
81import java.util.List;
82import java.util.Set;
83
84import static org.easymock.EasyMock.anyObject;
85import static org.easymock.EasyMock.createMock;
86import static org.easymock.EasyMock.expect;
87import static org.easymock.EasyMock.expectLastCall;
88import static org.easymock.EasyMock.replay;
89import static org.hamcrest.MatcherAssert.assertThat;
90import static org.hamcrest.Matchers.hasSize;
91import static org.hamcrest.Matchers.is;
92import static org.junit.Assert.assertEquals;
93import static org.onosproject.net.AnnotationKeys.STATIC_PORT;
94import static org.onosproject.net.AnnotationKeys.PORT_NAME;
95import static org.onosproject.net.Device.Type.ROADM;
96import static org.onosproject.net.DeviceId.deviceId;
97import static org.onosproject.net.NetTestTools.APP_ID;
98
99public class OpticalCircuitIntentCompilerTest {
100
101 private static final String DEV1 = "of:1";
102 private static final String DEV2 = "of:2";
103
104 static final Key KEY1 = Key.of(5L, APP_ID);
105
106 private static final String STATIC_TRUE = "true";
107 private static final String PNAME = "p2";
108
109 private CoreService coreService;
110 private IntentExtensionService intentExtensionService;
111 private final IdGenerator idGenerator = new MockIdGenerator();
112 private OpticalCircuitIntentCompiler sut;
113
114 private final ApplicationId appId = new TestApplicationId("test");
115 private static Device device1 = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), ROADM,
116 "m", "h", "s", "n", new ChassisId(0L));
117 private static Device device2 = new DefaultDevice(ProviderId.NONE, deviceId(DEV2), ROADM,
118 "m", "h", "s", "n", new ChassisId(1L));
119
120 private static Annotations annotations1 = DefaultAnnotations.builder().set(STATIC_PORT, STATIC_TRUE).build();
121 private static Annotations annotations2 = DefaultAnnotations.builder().set(PORT_NAME, PNAME).build();
122
123 // OduClt ports with signalType=1GBE
124 private static final OduCltPort D1P1 =
125 new OduCltPort(device1, PortNumber.portNumber(1), true, CltSignalType.CLT_1GBE, annotations1);
126 private static final OduCltPort D2P1 =
127 new OduCltPort(device2, PortNumber.portNumber(1), true, CltSignalType.CLT_1GBE, annotations1);
128
129 // Och ports with signalType=ODU2
130 private static final OchPort D1P2 =
131 new OchPort(device1, PortNumber.portNumber(2), true, OduSignalType.ODU2,
132 true, OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 1), annotations2);
133 private static final OchPort D2P2 =
134 new OchPort(device2, PortNumber.portNumber(2), true, OduSignalType.ODU2,
135 true, OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 1), annotations2);
136
137 // OduClt ports with signalType=10GBE
138 private static final OduCltPort D1P3 =
139 new OduCltPort(device1, PortNumber.portNumber(3), true, CltSignalType.CLT_10GBE, annotations1);
140 private static final OduCltPort D2P3 =
141 new OduCltPort(device2, PortNumber.portNumber(3), true, CltSignalType.CLT_10GBE, annotations1);
142
143
144 private OpticalCircuitIntent intent;
145
146 /**
147 * Mocks the device service so that devices and ports appear available in the test.
148 */
149 private static class MockDeviceService extends DeviceServiceAdapter {
150 @Override
151 public boolean isAvailable(DeviceId deviceId) {
152 return true;
153 }
154
155 @Override
156 public List<Port> getPorts(DeviceId deviceId) {
157 if (deviceId.equals(deviceId(DEV1))) {
158 return ImmutableList.of((Port) D1P1, (Port) D1P2, (Port) D1P3);
159 }
160
161 if (deviceId.equals(deviceId(DEV2))) {
162 return ImmutableList.of((Port) D2P1, (Port) D2P2, (Port) D2P3);
163 }
164 return Collections.emptyList();
165 }
166
167 @Override
168 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
169 if (deviceId.equals(deviceId(DEV1))) {
170 switch (portNumber.toString()) {
171 case "1":
172 return (Port) D1P1;
173 case "2":
174 return (Port) D1P2;
175 case "3":
176 return (Port) D1P3;
177 default:
178 return null;
179 }
180 }
181 if (deviceId.equals(deviceId(DEV2))) {
182 switch (portNumber.toString()) {
183 case "1":
184 return (Port) D2P1;
185 case "2":
186 return (Port) D2P2;
187 case "3":
188 return (Port) D2P3;
189 default:
190 return null;
191 }
192 }
193 return null;
194 }
195 }
196
197 /**
198 * Mocks the driver service so it will appear supporting TributarySlotQuery Behaviour in the test.
199 */
200 private static class MockDriverServiceWithTs implements DriverService {
201 @Override
202 public Driver getDriver(String driverName) {
203 // TODO Auto-generated method stub
204 return null;
205 }
206
207 @Override
208 public Set<Driver> getDrivers() {
209 // TODO Auto-generated method stub
210 return null;
211 }
212
213 @Override
214 public Set<Driver> getDrivers(Class<? extends Behaviour> withBehaviour) {
215 // TODO Auto-generated method stub
216 return null;
217 }
218
219 @Override
220 public Driver getDriver(String mfr, String hw, String sw) {
221 // TODO Auto-generated method stub
222 return null;
223 }
224
225 @Override
226 public Driver getDriver(DeviceId deviceId) {
227 DefaultDriver ddp = new DefaultDriver("foo.base", new ArrayList<>(), "Circus", "lux", "1.2a",
228 ImmutableMap.of(Behaviour.class,
229 TestBehaviourImpl.class,
230 TributarySlotQuery.class,
231 TestBehaviourTwoImpl.class),
232 ImmutableMap.of("foo", "bar"));
233 return ddp;
234 }
235
236 @Override
237 public DriverHandler createHandler(DeviceId deviceId,
238 String... credentials) {
239 // TODO Auto-generated method stub
240 return null;
241 }
242 }
243
244 /**
245 * Mocks the driver service so it will appear not-supporting TributarySlotQuery Behaviour in the test.
246 */
247 private static class MockDriverServiceNoTs implements DriverService {
248 @Override
249 public Driver getDriver(String driverName) {
250 // TODO Auto-generated method stub
251 return null;
252 }
253
254 @Override
255 public Set<Driver> getDrivers() {
256 // TODO Auto-generated method stub
257 return null;
258 }
259
260 @Override
261 public Set<Driver> getDrivers(Class<? extends Behaviour> withBehaviour) {
262 // TODO Auto-generated method stub
263 return null;
264 }
265
266 @Override
267 public Driver getDriver(String mfr, String hw, String sw) {
268 // TODO Auto-generated method stub
269 return null;
270 }
271
272 @Override
273 public Driver getDriver(DeviceId deviceId) {
274 DefaultDriver ddp = new DefaultDriver("foo.base", new ArrayList<>(), "Circus", "lux", "1.2a",
275 ImmutableMap.of(Behaviour.class,
276 TestBehaviourImpl.class),
277 ImmutableMap.of("foo", "bar"));
278 return ddp;
279 }
280
281 @Override
282 public DriverHandler createHandler(DeviceId deviceId,
283 String... credentials) {
284 // TODO Auto-generated method stub
285 return null;
286 }
287 }
288
289 private static class MockIntentSetMultimap implements IntentSetMultimap {
290 @Override
291 public boolean allocateMapping(IntentId keyIntentId,
292 IntentId valIntentId) {
293 // TODO Auto-generated method stub
294 return false;
295 }
296
297 @Override
298 public Set<IntentId> getMapping(IntentId intentId) {
299 // TODO Auto-generated method stub
300 return null;
301 }
302
303 @Override
304 public void releaseMapping(IntentId intentId) {
305 // TODO Auto-generated method stub
306 }
307
308 }
309
310 /**
311 * Represents a fake IntentService class that easily allows to store and
312 * retrieve intents without implementing the IntentService logic.
313 */
314 private class TestIntentService extends IntentServiceAdapter {
315
316 private Set<Intent> intents;
317
318 public TestIntentService() {
319 intents = Sets.newHashSet();
320 }
321
322 @Override
323 public void submit(Intent intent) {
324 intents.add(intent);
325 }
326
327 @Override
328 public long getIntentCount() {
329 return intents.size();
330 }
331
332 @Override
333 public Iterable<Intent> getIntents() {
334 return intents;
335 }
336
337 @Override
338 public Intent getIntent(Key intentKey) {
339 for (Intent intent : intents) {
340 if (intent.key().equals(intentKey)) {
341 return intent;
342 }
343 }
344 return null;
345 }
346 }
347
348 @Before
349 public void setUp() {
350 sut = new OpticalCircuitIntentCompiler();
351 coreService = createMock(CoreService.class);
352 expect(coreService.registerApplication("org.onosproject.net.intent"))
353 .andReturn(appId);
354 sut.coreService = coreService;
355 sut.deviceService = new MockDeviceService();
356 sut.resourceService = new MockResourceService();
357 sut.intentService = new TestIntentService();
358 sut.intentSetMultimap = new MockIntentSetMultimap();
359
360 Intent.bindIdGenerator(idGenerator);
361
362 intentExtensionService = createMock(IntentExtensionService.class);
363 intentExtensionService.registerCompiler(OpticalCircuitIntent.class, sut);
364 intentExtensionService.unregisterCompiler(OpticalCircuitIntent.class);
365 sut.intentManager = intentExtensionService;
366 replay(coreService, intentExtensionService);
367
368 // mocking ComponentConfigService
369 ComponentConfigService mockConfigService =
370 EasyMock.createMock(ComponentConfigService.class);
371 expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
372 mockConfigService.registerProperties(sut.getClass());
373 expectLastCall();
374 mockConfigService.unregisterProperties(sut.getClass(), false);
375 expectLastCall();
376 expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
377 sut.cfgService = mockConfigService;
378 replay(mockConfigService);
379
380 }
381
382 @After
383 public void tearDown() {
384 Intent.unbindIdGenerator(idGenerator);
385 }
386
387 /**
388 * Tests compile of OpticalCircuitIntent with allocation of TributarySlots.
389 * Compile two ODUCLT ports (with CLT_1GBE), over OCH ports (with ODU2):
390 * - only one TributarySlot is used
391 */
392 @Test
393 public void test1GbeMultiplexOverOdu2() {
394
395 // Use driver with TributarySlotQuery Behaviour
396 sut.driverService = new MockDriverServiceWithTs();
397
398 ConnectPoint oduCltSrcCP = new ConnectPoint(device1.id(), D1P1.number());
399 ConnectPoint oduCltDstCP = new ConnectPoint(device2.id(), D2P1.number());
400 ConnectPoint ochSrcCP = new ConnectPoint(device1.id(), D1P2.number());
401 ConnectPoint ochDstCP = new ConnectPoint(device2.id(), D2P2.number());
402
403 intent = OpticalCircuitIntent.builder()
404 .appId(APP_ID)
405 .key(KEY1)
406 .src(oduCltSrcCP)
407 .dst(oduCltDstCP)
408 .signalType(D1P1.signalType())
409 .bidirectional(false)
410 .build();
411
412 sut.activate(null);
413
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800414 List<Intent> compiled = sut.compile(intent, Collections.emptyList());
Rimon Ashkenazya4e3bd32016-02-22 16:12:20 +0200415 assertThat(compiled, hasSize(1));
416
417 Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
418
419 FlowRule rule1 = rules.stream()
420 .filter(x -> x.deviceId().equals(device1.id()))
421 .findFirst()
422 .get();
423 // validate SRC selector
424 TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
425 selectorBuilder1.matchInPort(oduCltSrcCP.port());
426 selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
427 assertThat(rule1.selector(), is(selectorBuilder1.build()));
428
429 // validate SRC treatment (with OduSignalId, where 1 TributarySlot is used)
430 TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
431 Set<TributarySlot> slots = new HashSet<>();
432 slots.add(TributarySlot.of(1));
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200433 OduSignalId oduSignalId = OduSignalUtils.buildOduSignalId(D1P2.signalType(), slots);
Rimon Ashkenazya4e3bd32016-02-22 16:12:20 +0200434 treatmentBuilder1.add(Instructions.modL1OduSignalId(oduSignalId));
435 treatmentBuilder1.setOutput(ochSrcCP.port());
436 assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
437
438 FlowRule rule2 = rules.stream()
439 .filter(x -> x.deviceId().equals(device2.id()))
440 .findFirst()
441 .get();
442 // validate DST selector (with OduSignalId, where the same TributarySlot is used)
443 TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
444 selectorBuilder2.matchInPort(ochDstCP.port());
445 selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
446 selectorBuilder2.add(Criteria.matchOduSignalId(oduSignalId));
447 assertThat(rule2.selector(), is(selectorBuilder2.build()));
448
449 // validate DST treatment
450 assertThat(rule2.treatment(), is(
451 DefaultTrafficTreatment.builder().setOutput(oduCltDstCP.port()).build()
452 ));
453
454 rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
455 intent.priority(), rule.priority()));
456
457 sut.deactivate();
458 }
459
460 /**
461 * Tests compile of OpticalCircuitIntent with allocation of TributarySlots.
462 * Compile two ODUCLT ports (with CLT_10GBE), over OCH ports (with ODU2):
463 * - All TributarySlots are used
464 */
465 @Test
466 public void test10GbeMultiplexOverOdu2() {
467
468 // Use driver with TributarySlotQuery Behaviour
469 sut.driverService = new MockDriverServiceWithTs();
470
471 ConnectPoint oduCltSrcCP = new ConnectPoint(device1.id(), D1P3.number());
472 ConnectPoint oduCltDstCP = new ConnectPoint(device2.id(), D2P3.number());
473 ConnectPoint ochSrcCP = new ConnectPoint(device1.id(), D1P2.number());
474 ConnectPoint ochDstCP = new ConnectPoint(device2.id(), D2P2.number());
475
476 intent = OpticalCircuitIntent.builder()
477 .appId(APP_ID)
478 .key(KEY1)
479 .src(oduCltSrcCP)
480 .dst(oduCltDstCP)
481 .signalType(D1P3.signalType())
482 .bidirectional(false)
483 .build();
484
485 sut.activate(null);
486
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800487 List<Intent> compiled = sut.compile(intent, Collections.emptyList());
Rimon Ashkenazya4e3bd32016-02-22 16:12:20 +0200488 assertThat(compiled, hasSize(1));
489
490 Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
491
492 FlowRule rule1 = rules.stream()
493 .filter(x -> x.deviceId().equals(device1.id()))
494 .findFirst()
495 .get();
496 // validate SRC selector
497 TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
498 selectorBuilder1.matchInPort(oduCltSrcCP.port());
499 selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
500 assertThat(rule1.selector(), is(selectorBuilder1.build()));
501
502 // validate SRC treatment (without OduSignalId, i.e. All TributarySlots are used)
503 TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
504 treatmentBuilder1.setOutput(ochSrcCP.port());
505 assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
506
507 FlowRule rule2 = rules.stream()
508 .filter(x -> x.deviceId().equals(device2.id()))
509 .findFirst()
510 .get();
511 // validate DST selector (without OduSignalId, i.e. All TributarySlots are used)
512 TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
513 selectorBuilder2.matchInPort(ochDstCP.port());
514 selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
515 assertThat(rule2.selector(), is(selectorBuilder2.build()));
516
517 // validate DST treatment
518 assertThat(rule2.treatment(), is(
519 DefaultTrafficTreatment.builder().setOutput(oduCltDstCP.port()).build()
520 ));
521
522 rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
523 intent.priority(), rule.priority()));
524
525 sut.deactivate();
526 }
527
528 /**
529 * Tests compile of OpticalCircuitIntent without allocation of TributarySlots.
530 * Compile two ODUCLT ports (with CLT_10GBE), over OCH ports (with ODU2):
531 * - No TributarySlots are used
532 */
533 @Test
534 public void test10GbeNoMuxOverOdu2() {
535
536 // Use driver without support for TributarySlotQuery Behaviour
537 sut.driverService = new MockDriverServiceNoTs();
538
539 ConnectPoint oduCltSrcCP = new ConnectPoint(device1.id(), D1P3.number());
540 ConnectPoint oduCltDstCP = new ConnectPoint(device2.id(), D2P3.number());
541 ConnectPoint ochSrcCP = new ConnectPoint(device1.id(), D1P2.number());
542 ConnectPoint ochDstCP = new ConnectPoint(device2.id(), D2P2.number());
543
544 intent = OpticalCircuitIntent.builder()
545 .appId(APP_ID)
546 .key(KEY1)
547 .src(oduCltSrcCP)
548 .dst(oduCltDstCP)
549 .signalType(D1P3.signalType())
550 .bidirectional(false)
551 .build();
552
553 sut.activate(null);
554
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800555 List<Intent> compiled = sut.compile(intent, Collections.emptyList());
Rimon Ashkenazya4e3bd32016-02-22 16:12:20 +0200556 assertThat(compiled, hasSize(1));
557
558 Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
559
560 FlowRule rule1 = rules.stream()
561 .filter(x -> x.deviceId().equals(device1.id()))
562 .findFirst()
563 .get();
564 // validate SRC selector
565 TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
566 selectorBuilder1.matchInPort(oduCltSrcCP.port());
567 assertThat(rule1.selector(), is(selectorBuilder1.build()));
568
569 // validate SRC treatment (without OduSignalType and OduSignalId: i.e. No TributarySlots are used)
570 TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
571 treatmentBuilder1.setOutput(ochSrcCP.port());
572 assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
573
574 FlowRule rule2 = rules.stream()
575 .filter(x -> x.deviceId().equals(device2.id()))
576 .findFirst()
577 .get();
578 // validate DST selector (without OduSignalType and OduSignalId: i.e. No TributarySlots are used)
579 TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
580 selectorBuilder2.matchInPort(ochDstCP.port());
581 assertThat(rule2.selector(), is(selectorBuilder2.build()));
582 // validate DST treatment
583 assertThat(rule2.treatment(), is(
584 DefaultTrafficTreatment.builder().setOutput(oduCltDstCP.port()).build()
585 ));
586
587 rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
588 intent.priority(), rule.priority()));
589
590 sut.deactivate();
591 }
592
593}