blob: 810e89795dc30377f8e425a6a0943edfb1634b55 [file] [log] [blame]
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +02001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +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 */
Yuta HIGUCHId95d5902016-06-27 00:18:45 -070016package org.onosproject.net.optical.intent.impl.compiler;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020017
18import org.junit.After;
19import org.junit.Before;
20import org.junit.Test;
21import org.onlab.packet.ChassisId;
22import org.onosproject.TestApplicationId;
23import org.onosproject.core.ApplicationId;
24import org.onosproject.core.CoreService;
25import org.onosproject.core.IdGenerator;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070026import org.onosproject.net.AbstractProjectableModel;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020027import org.onosproject.net.Annotations;
28import org.onosproject.net.DefaultAnnotations;
29import org.onosproject.net.CltSignalType;
30import org.onosproject.net.ConnectPoint;
31import org.onosproject.net.DefaultDevice;
32import org.onosproject.net.DefaultLink;
33import org.onosproject.net.DefaultPath;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070034import org.onosproject.net.DefaultPort;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020035import org.onosproject.net.Device;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.Link;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020038import org.onosproject.net.OduSignalId;
39import org.onosproject.net.OduSignalType;
40import org.onosproject.net.OduSignalUtils;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020041import org.onosproject.net.OtuSignalType;
42import org.onosproject.net.Path;
43import org.onosproject.net.Port;
44import org.onosproject.net.PortNumber;
45import org.onosproject.net.TributarySlot;
46import org.onosproject.net.flow.DefaultTrafficSelector;
47import org.onosproject.net.flow.DefaultTrafficTreatment;
48import org.onosproject.net.flow.FlowRule;
49import org.onosproject.net.flow.TrafficSelector;
50import org.onosproject.net.flow.TrafficTreatment;
51import org.onosproject.net.flow.criteria.Criteria;
52import org.onosproject.net.flow.instructions.Instructions;
53import org.onosproject.net.intent.FlowRuleIntent;
54import org.onosproject.net.intent.Intent;
55import org.onosproject.net.intent.IntentExtensionService;
56import org.onosproject.net.intent.Key;
57import org.onosproject.net.intent.MockIdGenerator;
58import org.onosproject.net.intent.OpticalOduIntent;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070059import org.onosproject.net.optical.OduCltPort;
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -070060import org.onosproject.net.optical.OtuPort;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070061import org.onosproject.net.optical.impl.DefaultOduCltPort;
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -070062import org.onosproject.net.optical.impl.DefaultOtuPort;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020063import org.onosproject.net.provider.ProviderId;
Yuta HIGUCHId95d5902016-06-27 00:18:45 -070064import org.onosproject.net.resource.MockResourceService;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020065import org.onosproject.net.topology.LinkWeight;
66import org.onosproject.net.topology.Topology;
67import org.onosproject.net.topology.TopologyServiceAdapter;
68import org.onosproject.net.device.DeviceServiceAdapter;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070069import org.onosproject.net.driver.DriverService;
70import org.onosproject.net.driver.DriverServiceAdapter;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020071
72import com.google.common.collect.ImmutableList;
73import com.google.common.collect.Sets;
74
75import java.util.Arrays;
76import java.util.Collection;
77import java.util.Collections;
78import java.util.HashSet;
79import java.util.List;
80import java.util.Set;
81
82import static org.easymock.EasyMock.createMock;
83import static org.easymock.EasyMock.expect;
84import static org.easymock.EasyMock.replay;
85import static org.hamcrest.MatcherAssert.assertThat;
86import static org.hamcrest.Matchers.hasSize;
87import static org.hamcrest.Matchers.is;
88import static org.junit.Assert.assertEquals;
89import static org.onosproject.net.AnnotationKeys.STATIC_PORT;
90import static org.onosproject.net.AnnotationKeys.PORT_NAME;
91import static org.onosproject.net.Device.Type.OTN;
92import static org.onosproject.net.DeviceId.deviceId;
93import static org.onosproject.net.Link.Type.OPTICAL;
94import static org.onosproject.net.NetTestTools.APP_ID;
95import static org.onosproject.net.NetTestTools.PID;
96
97public class OpticalOduIntentCompilerTest {
98
99 private static final String DEV1 = "of:1";
100 private static final String DEV2 = "of:2";
101 private static final String DEV3 = "of:3";
102
103 static final Key KEY1 = Key.of(5L, APP_ID);
104
105 private static final String STATIC_TRUE = "true";
106 private static final String PNAME = "p2";
107
108 private CoreService coreService;
109 private IntentExtensionService intentExtensionService;
110 private final IdGenerator idGenerator = new MockIdGenerator();
111 private OpticalOduIntentCompiler sut;
112
113 private final ApplicationId appId = new TestApplicationId("test");
114 private static Device device1 = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), OTN,
115 "m", "h", "s", "n", new ChassisId(0L));
116 private static Device device2 = new DefaultDevice(ProviderId.NONE, deviceId(DEV2), OTN,
117 "m", "h", "s", "n", new ChassisId(1L));
118 private static Device device3 = new DefaultDevice(ProviderId.NONE, deviceId(DEV3), OTN,
119 "m", "h", "s", "n", new ChassisId(2L));
120
121 private static Annotations annotations1 = DefaultAnnotations.builder().set(STATIC_PORT, STATIC_TRUE).build();
122 private static Annotations annotations2 = DefaultAnnotations.builder().set(PORT_NAME, PNAME).build();
123
124 // OduClt ports with signalType=1GBE
125 private static final OduCltPort D1P1 =
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700126 new DefaultOduCltPort(new DefaultPort(device1, PortNumber.portNumber(1), true, annotations1),
127 CltSignalType.CLT_1GBE);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200128 private static final OduCltPort D3P2 =
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700129 new DefaultOduCltPort(new DefaultPort(device3, PortNumber.portNumber(2), true, annotations1),
130 CltSignalType.CLT_1GBE);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200131
132 // Otu ports with signalType=ODU2
133 private static final OtuPort D1P2 =
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -0700134 new DefaultOtuPort(new DefaultPort(device1, PortNumber.portNumber(2), true, annotations2),
135 OtuSignalType.OTU2);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200136 private static final OtuPort D2P1 =
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -0700137 new DefaultOtuPort(new DefaultPort(device2, PortNumber.portNumber(1), true, annotations2),
138 OtuSignalType.OTU2);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200139 private static final OtuPort D2P2 =
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -0700140 new DefaultOtuPort(new DefaultPort(device2, PortNumber.portNumber(2), true, annotations2),
141 OtuSignalType.OTU2);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200142 private static final OtuPort D3P1 =
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -0700143 new DefaultOtuPort(new DefaultPort(device3, PortNumber.portNumber(1), true, annotations2),
144 OtuSignalType.OTU2);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200145
146 // OduClt ports with signalType=10GBE
147 private static final OduCltPort D1P3 =
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700148 new DefaultOduCltPort(new DefaultPort(device1, PortNumber.portNumber(3), true, annotations1),
149 CltSignalType.CLT_10GBE);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200150 private static final OduCltPort D3P3 =
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700151 new DefaultOduCltPort(new DefaultPort(device3, PortNumber.portNumber(3), true, annotations1),
152 CltSignalType.CLT_10GBE);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200153
154 // OduCltPort ConnectPoints
155 private final ConnectPoint d1p1 = new ConnectPoint(device1.id(), D1P1.number());
156 private final ConnectPoint d1p3 = new ConnectPoint(device1.id(), D1P3.number());
157 private final ConnectPoint d3p2 = new ConnectPoint(device3.id(), D3P2.number());
158 private final ConnectPoint d3p3 = new ConnectPoint(device3.id(), D3P3.number());
159
160 // OtuPort ConnectPoints
161 private final ConnectPoint d1p2 = new ConnectPoint(device1.id(), D1P2.number());
162 private final ConnectPoint d2p1 = new ConnectPoint(device2.id(), D2P1.number());
163 private final ConnectPoint d2p2 = new ConnectPoint(device2.id(), D2P2.number());
164 private final ConnectPoint d3p1 = new ConnectPoint(device3.id(), D3P1.number());
165
166 private final List<Link> links = Arrays.asList(
167 DefaultLink.builder().providerId(PID).src(d1p2).dst(d2p1).type(OPTICAL).build(),
168 DefaultLink.builder().providerId(PID).src(d2p2).dst(d3p1).type(OPTICAL).build()
169 );
170 private final Path path = new DefaultPath(PID, links, 3);
171
172 private OpticalOduIntent intent;
173
174 /**
175 * Mocks the topology service to give paths in the test.
176 */
177 private class MockTopologyService extends TopologyServiceAdapter {
178 Set<Path> paths = Sets.newHashSet(path);
179
180 @Override
181 public Topology currentTopology() {
182 return null;
183 }
184
185 @Override
186 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
187 return paths;
188 }
189 }
190
191 /**
192 * Mocks the device service so that devices and ports appear available in the test.
193 */
194 private static class MockDeviceService extends DeviceServiceAdapter {
195 @Override
196 public boolean isAvailable(DeviceId deviceId) {
197 return true;
198 }
199
200 @Override
201 public List<Port> getPorts(DeviceId deviceId) {
202 if (deviceId.equals(deviceId(DEV1))) {
203 return ImmutableList.of((Port) D1P1, (Port) D1P2, (Port) D1P3);
204 }
205
206 if (deviceId.equals(deviceId(DEV2))) {
207 return ImmutableList.of((Port) D2P1, (Port) D2P2);
208 }
209
210 if (deviceId.equals(deviceId(DEV3))) {
211 return ImmutableList.of((Port) D3P1, (Port) D3P2, (Port) D3P3);
212 }
213
214 return Collections.emptyList();
215 }
216
217 @Override
218 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
219 if (deviceId.equals(deviceId(DEV1))) {
220 switch (portNumber.toString()) {
221 case "1":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700222 return D1P1;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200223 case "2":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700224 return D1P2;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200225 case "3":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700226 return D1P3;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200227 default:
228 return null;
229 }
230 }
231 if (deviceId.equals(deviceId(DEV2))) {
232 switch (portNumber.toString()) {
233 case "1":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700234 return D2P1;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200235 case "2":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700236 return D2P2;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200237 default:
238 return null;
239 }
240 }
241 if (deviceId.equals(deviceId(DEV3))) {
242 switch (portNumber.toString()) {
243 case "1":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700244 return D3P1;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200245 case "2":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700246 return D3P2;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200247 case "3":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700248 return D3P3;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200249 default:
250 return null;
251 }
252 }
253 return null;
254 }
255 }
256
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700257 private static class MockDriverService extends DriverServiceAdapter
258 implements DriverService {
259 // TODO override to return appropriate driver,
260 // with DefaultOpticalDevice support, etc.
261 }
262
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200263 @Before
264 public void setUp() {
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700265 AbstractProjectableModel.setDriverService(null, new MockDriverService());
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200266 sut = new OpticalOduIntentCompiler();
267 coreService = createMock(CoreService.class);
268 expect(coreService.registerApplication("org.onosproject.net.intent"))
269 .andReturn(appId);
270 sut.coreService = coreService;
271 sut.deviceService = new MockDeviceService();
272 sut.resourceService = new MockResourceService();
273 sut.topologyService = new MockTopologyService();
274
275 Intent.bindIdGenerator(idGenerator);
276
277 intentExtensionService = createMock(IntentExtensionService.class);
278 intentExtensionService.registerCompiler(OpticalOduIntent.class, sut);
279 intentExtensionService.unregisterCompiler(OpticalOduIntent.class);
280 sut.intentManager = intentExtensionService;
281
282 replay(coreService, intentExtensionService);
283 }
284
285 @After
286 public void tearDown() {
287 Intent.unbindIdGenerator(idGenerator);
288 }
289
290 /**
291 * Tests compile of OpticalOduIntent with allocation of TributarySlots.
292 * Compile two ODUCLT ports (with CLT_1GBE), over OTU ports (with OTU2):
293 * - only one TributarySlot is used
294 */
295 @Test
296 public void test1GbeMultiplexOverOdu2() {
297
298 intent = OpticalOduIntent.builder()
299 .appId(APP_ID)
300 .key(KEY1)
301 .src(d1p1)
302 .dst(d3p2)
303 .signalType(D1P1.signalType())
304 .bidirectional(false)
305 .build();
306
307 sut.activate();
308
309 List<Intent> compiled = sut.compile(intent, Collections.emptyList());
310 assertThat(compiled, hasSize(1));
311
312 Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
313
314 // 1st Device
315 FlowRule rule1 = rules.stream()
316 .filter(x -> x.deviceId().equals(device1.id()))
317 .findFirst()
318 .get();
319 // validate SRC selector
320 TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
321 selectorBuilder1.matchInPort(d1p1.port());
322 selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
323 assertThat(rule1.selector(), is(selectorBuilder1.build()));
324
325 // validate SRC treatment (with OduSignalId, where 1 TributarySlot is used)
326 TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
327 Set<TributarySlot> slots = new HashSet<>();
328 slots.add(TributarySlot.of(1));
329 OduSignalId oduSignalId = OduSignalUtils.buildOduSignalId(OduSignalType.ODU2, slots);
330 treatmentBuilder1.add(Instructions.modL1OduSignalId(oduSignalId));
331 treatmentBuilder1.setOutput(d1p2.port());
332 assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
333
334 // 2nd Device
335 FlowRule rule2 = rules.stream()
336 .filter(x -> x.deviceId().equals(device2.id()))
337 .findFirst()
338 .get();
339 // validate SRC selector
340 TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
341 selectorBuilder2.matchInPort(d2p1.port());
342 selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
343 selectorBuilder2.add(Criteria.matchOduSignalId(oduSignalId));
344 assertThat(rule2.selector(), is(selectorBuilder2.build()));
345
346 // validate SRC treatment (with OduSignalId, where 1 TributarySlot is used)
347 TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder();
348 treatmentBuilder2.add(Instructions.modL1OduSignalId(oduSignalId));
349 treatmentBuilder2.setOutput(d2p2.port());
350 assertThat(rule2.treatment(), is(treatmentBuilder2.build()));
351
352
353 // 3rd Device
354 FlowRule rule3 = rules.stream()
355 .filter(x -> x.deviceId().equals(device3.id()))
356 .findFirst()
357 .get();
358 // validate DST selector (with OduSignalId, where the same TributarySlot is used)
359 TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder();
360 selectorBuilder3.matchInPort(d3p1.port());
361 selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
362 selectorBuilder3.add(Criteria.matchOduSignalId(oduSignalId));
363 assertThat(rule3.selector(), is(selectorBuilder3.build()));
364
365 // validate DST treatment
366 assertThat(rule3.treatment(), is(
367 DefaultTrafficTreatment.builder().setOutput(d3p2.port()).build()
368 ));
369
370 rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
371 intent.priority(), rule.priority()));
372
373 sut.deactivate();
374 }
375
376 /**
377 * Tests compile of OpticalOduIntent with allocation of TributarySlots.
378 * Compile two ODUCLT ports (with CLT_10GBE), over OTU ports (with OTU2):
379 * - All TributarySlots are used
380 */
381 @Test
382 public void test10GbeMultiplexOverOdu2() {
383
384 intent = OpticalOduIntent.builder()
385 .appId(APP_ID)
386 .key(KEY1)
387 .src(d1p3)
388 .dst(d3p3)
389 .signalType(D1P3.signalType())
390 .bidirectional(false)
391 .build();
392
393 sut.activate();
394
395 List<Intent> compiled = sut.compile(intent, Collections.emptyList());
396 assertThat(compiled, hasSize(1));
397
398 Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
399
400 // 1st Device
401 FlowRule rule1 = rules.stream()
402 .filter(x -> x.deviceId().equals(device1.id()))
403 .findFirst()
404 .get();
405 // validate SRC selector
406 TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
407 selectorBuilder1.matchInPort(d1p3.port());
408 selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
409 assertThat(rule1.selector(), is(selectorBuilder1.build()));
410
411 // validate SRC treatment (without OduSignalId - all TributarySlots are used)
412 TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
413 treatmentBuilder1.setOutput(d1p2.port());
414 assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
415
416 // 2nd Device
417 FlowRule rule2 = rules.stream()
418 .filter(x -> x.deviceId().equals(device2.id()))
419 .findFirst()
420 .get();
421 // validate SRC selector
422 TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
423 selectorBuilder2.matchInPort(d2p1.port());
424 selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
425 assertThat(rule2.selector(), is(selectorBuilder2.build()));
426
427 // validate SRC treatment (without OduSignalId - all TributarySlots are used)
428 TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder();
429 treatmentBuilder2.setOutput(d2p2.port());
430 assertThat(rule2.treatment(), is(treatmentBuilder2.build()));
431
432
433 // 3rd Device
434 FlowRule rule3 = rules.stream()
435 .filter(x -> x.deviceId().equals(device3.id()))
436 .findFirst()
437 .get();
438 // validate DST selector (without OduSignalId - all TributarySlots are used)
439 TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder();
440 selectorBuilder3.matchInPort(d3p1.port());
441 selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
442 assertThat(rule3.selector(), is(selectorBuilder3.build()));
443
444 // validate DST treatment
445 assertThat(rule3.treatment(), is(
446 DefaultTrafficTreatment.builder().setOutput(d3p3.port()).build()
447 ));
448
449 rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
450 intent.priority(), rule.priority()));
451
452 sut.deactivate();
453 }
454
455}