blob: a6ba3fefafd77837787c5261fb105f058ddd4dbe [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 */
16package org.onosproject.net.intent.impl.compiler;
17
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;
64import org.onosproject.net.topology.LinkWeight;
65import org.onosproject.net.topology.Topology;
66import org.onosproject.net.topology.TopologyServiceAdapter;
67import org.onosproject.net.device.DeviceServiceAdapter;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070068import org.onosproject.net.driver.DriverService;
69import org.onosproject.net.driver.DriverServiceAdapter;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +020070
71import com.google.common.collect.ImmutableList;
72import com.google.common.collect.Sets;
73
74import java.util.Arrays;
75import java.util.Collection;
76import java.util.Collections;
77import java.util.HashSet;
78import java.util.List;
79import java.util.Set;
80
81import static org.easymock.EasyMock.createMock;
82import static org.easymock.EasyMock.expect;
83import static org.easymock.EasyMock.replay;
84import static org.hamcrest.MatcherAssert.assertThat;
85import static org.hamcrest.Matchers.hasSize;
86import static org.hamcrest.Matchers.is;
87import static org.junit.Assert.assertEquals;
88import static org.onosproject.net.AnnotationKeys.STATIC_PORT;
89import static org.onosproject.net.AnnotationKeys.PORT_NAME;
90import static org.onosproject.net.Device.Type.OTN;
91import static org.onosproject.net.DeviceId.deviceId;
92import static org.onosproject.net.Link.Type.OPTICAL;
93import static org.onosproject.net.NetTestTools.APP_ID;
94import static org.onosproject.net.NetTestTools.PID;
95
96public class OpticalOduIntentCompilerTest {
97
98 private static final String DEV1 = "of:1";
99 private static final String DEV2 = "of:2";
100 private static final String DEV3 = "of:3";
101
102 static final Key KEY1 = Key.of(5L, APP_ID);
103
104 private static final String STATIC_TRUE = "true";
105 private static final String PNAME = "p2";
106
107 private CoreService coreService;
108 private IntentExtensionService intentExtensionService;
109 private final IdGenerator idGenerator = new MockIdGenerator();
110 private OpticalOduIntentCompiler sut;
111
112 private final ApplicationId appId = new TestApplicationId("test");
113 private static Device device1 = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), OTN,
114 "m", "h", "s", "n", new ChassisId(0L));
115 private static Device device2 = new DefaultDevice(ProviderId.NONE, deviceId(DEV2), OTN,
116 "m", "h", "s", "n", new ChassisId(1L));
117 private static Device device3 = new DefaultDevice(ProviderId.NONE, deviceId(DEV3), OTN,
118 "m", "h", "s", "n", new ChassisId(2L));
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 =
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700125 new DefaultOduCltPort(new DefaultPort(device1, PortNumber.portNumber(1), true, annotations1),
126 CltSignalType.CLT_1GBE);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200127 private static final OduCltPort D3P2 =
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700128 new DefaultOduCltPort(new DefaultPort(device3, PortNumber.portNumber(2), true, annotations1),
129 CltSignalType.CLT_1GBE);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200130
131 // Otu ports with signalType=ODU2
132 private static final OtuPort D1P2 =
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -0700133 new DefaultOtuPort(new DefaultPort(device1, PortNumber.portNumber(2), true, annotations2),
134 OtuSignalType.OTU2);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200135 private static final OtuPort D2P1 =
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -0700136 new DefaultOtuPort(new DefaultPort(device2, PortNumber.portNumber(1), true, annotations2),
137 OtuSignalType.OTU2);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200138 private static final OtuPort D2P2 =
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -0700139 new DefaultOtuPort(new DefaultPort(device2, PortNumber.portNumber(2), true, annotations2),
140 OtuSignalType.OTU2);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200141 private static final OtuPort D3P1 =
HIGUCHI Yuta5be3e822016-05-03 13:51:42 -0700142 new DefaultOtuPort(new DefaultPort(device3, PortNumber.portNumber(1), true, annotations2),
143 OtuSignalType.OTU2);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200144
145 // OduClt ports with signalType=10GBE
146 private static final OduCltPort D1P3 =
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700147 new DefaultOduCltPort(new DefaultPort(device1, PortNumber.portNumber(3), true, annotations1),
148 CltSignalType.CLT_10GBE);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200149 private static final OduCltPort D3P3 =
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700150 new DefaultOduCltPort(new DefaultPort(device3, PortNumber.portNumber(3), true, annotations1),
151 CltSignalType.CLT_10GBE);
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200152
153 // OduCltPort ConnectPoints
154 private final ConnectPoint d1p1 = new ConnectPoint(device1.id(), D1P1.number());
155 private final ConnectPoint d1p3 = new ConnectPoint(device1.id(), D1P3.number());
156 private final ConnectPoint d3p2 = new ConnectPoint(device3.id(), D3P2.number());
157 private final ConnectPoint d3p3 = new ConnectPoint(device3.id(), D3P3.number());
158
159 // OtuPort ConnectPoints
160 private final ConnectPoint d1p2 = new ConnectPoint(device1.id(), D1P2.number());
161 private final ConnectPoint d2p1 = new ConnectPoint(device2.id(), D2P1.number());
162 private final ConnectPoint d2p2 = new ConnectPoint(device2.id(), D2P2.number());
163 private final ConnectPoint d3p1 = new ConnectPoint(device3.id(), D3P1.number());
164
165 private final List<Link> links = Arrays.asList(
166 DefaultLink.builder().providerId(PID).src(d1p2).dst(d2p1).type(OPTICAL).build(),
167 DefaultLink.builder().providerId(PID).src(d2p2).dst(d3p1).type(OPTICAL).build()
168 );
169 private final Path path = new DefaultPath(PID, links, 3);
170
171 private OpticalOduIntent intent;
172
173 /**
174 * Mocks the topology service to give paths in the test.
175 */
176 private class MockTopologyService extends TopologyServiceAdapter {
177 Set<Path> paths = Sets.newHashSet(path);
178
179 @Override
180 public Topology currentTopology() {
181 return null;
182 }
183
184 @Override
185 public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
186 return paths;
187 }
188 }
189
190 /**
191 * Mocks the device service so that devices and ports appear available in the test.
192 */
193 private static class MockDeviceService extends DeviceServiceAdapter {
194 @Override
195 public boolean isAvailable(DeviceId deviceId) {
196 return true;
197 }
198
199 @Override
200 public List<Port> getPorts(DeviceId deviceId) {
201 if (deviceId.equals(deviceId(DEV1))) {
202 return ImmutableList.of((Port) D1P1, (Port) D1P2, (Port) D1P3);
203 }
204
205 if (deviceId.equals(deviceId(DEV2))) {
206 return ImmutableList.of((Port) D2P1, (Port) D2P2);
207 }
208
209 if (deviceId.equals(deviceId(DEV3))) {
210 return ImmutableList.of((Port) D3P1, (Port) D3P2, (Port) D3P3);
211 }
212
213 return Collections.emptyList();
214 }
215
216 @Override
217 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
218 if (deviceId.equals(deviceId(DEV1))) {
219 switch (portNumber.toString()) {
220 case "1":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700221 return D1P1;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200222 case "2":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700223 return D1P2;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200224 case "3":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700225 return D1P3;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200226 default:
227 return null;
228 }
229 }
230 if (deviceId.equals(deviceId(DEV2))) {
231 switch (portNumber.toString()) {
232 case "1":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700233 return D2P1;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200234 case "2":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700235 return D2P2;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200236 default:
237 return null;
238 }
239 }
240 if (deviceId.equals(deviceId(DEV3))) {
241 switch (portNumber.toString()) {
242 case "1":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700243 return D3P1;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200244 case "2":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700245 return D3P2;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200246 case "3":
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700247 return D3P3;
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200248 default:
249 return null;
250 }
251 }
252 return null;
253 }
254 }
255
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700256 private static class MockDriverService extends DriverServiceAdapter
257 implements DriverService {
258 // TODO override to return appropriate driver,
259 // with DefaultOpticalDevice support, etc.
260 }
261
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200262 @Before
263 public void setUp() {
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700264 AbstractProjectableModel.setDriverService(null, new MockDriverService());
Rimon Ashkenazy27438ff2016-03-22 15:57:45 +0200265 sut = new OpticalOduIntentCompiler();
266 coreService = createMock(CoreService.class);
267 expect(coreService.registerApplication("org.onosproject.net.intent"))
268 .andReturn(appId);
269 sut.coreService = coreService;
270 sut.deviceService = new MockDeviceService();
271 sut.resourceService = new MockResourceService();
272 sut.topologyService = new MockTopologyService();
273
274 Intent.bindIdGenerator(idGenerator);
275
276 intentExtensionService = createMock(IntentExtensionService.class);
277 intentExtensionService.registerCompiler(OpticalOduIntent.class, sut);
278 intentExtensionService.unregisterCompiler(OpticalOduIntent.class);
279 sut.intentManager = intentExtensionService;
280
281 replay(coreService, intentExtensionService);
282 }
283
284 @After
285 public void tearDown() {
286 Intent.unbindIdGenerator(idGenerator);
287 }
288
289 /**
290 * Tests compile of OpticalOduIntent with allocation of TributarySlots.
291 * Compile two ODUCLT ports (with CLT_1GBE), over OTU ports (with OTU2):
292 * - only one TributarySlot is used
293 */
294 @Test
295 public void test1GbeMultiplexOverOdu2() {
296
297 intent = OpticalOduIntent.builder()
298 .appId(APP_ID)
299 .key(KEY1)
300 .src(d1p1)
301 .dst(d3p2)
302 .signalType(D1P1.signalType())
303 .bidirectional(false)
304 .build();
305
306 sut.activate();
307
308 List<Intent> compiled = sut.compile(intent, Collections.emptyList());
309 assertThat(compiled, hasSize(1));
310
311 Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
312
313 // 1st Device
314 FlowRule rule1 = rules.stream()
315 .filter(x -> x.deviceId().equals(device1.id()))
316 .findFirst()
317 .get();
318 // validate SRC selector
319 TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
320 selectorBuilder1.matchInPort(d1p1.port());
321 selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
322 assertThat(rule1.selector(), is(selectorBuilder1.build()));
323
324 // validate SRC treatment (with OduSignalId, where 1 TributarySlot is used)
325 TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
326 Set<TributarySlot> slots = new HashSet<>();
327 slots.add(TributarySlot.of(1));
328 OduSignalId oduSignalId = OduSignalUtils.buildOduSignalId(OduSignalType.ODU2, slots);
329 treatmentBuilder1.add(Instructions.modL1OduSignalId(oduSignalId));
330 treatmentBuilder1.setOutput(d1p2.port());
331 assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
332
333 // 2nd Device
334 FlowRule rule2 = rules.stream()
335 .filter(x -> x.deviceId().equals(device2.id()))
336 .findFirst()
337 .get();
338 // validate SRC selector
339 TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
340 selectorBuilder2.matchInPort(d2p1.port());
341 selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
342 selectorBuilder2.add(Criteria.matchOduSignalId(oduSignalId));
343 assertThat(rule2.selector(), is(selectorBuilder2.build()));
344
345 // validate SRC treatment (with OduSignalId, where 1 TributarySlot is used)
346 TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder();
347 treatmentBuilder2.add(Instructions.modL1OduSignalId(oduSignalId));
348 treatmentBuilder2.setOutput(d2p2.port());
349 assertThat(rule2.treatment(), is(treatmentBuilder2.build()));
350
351
352 // 3rd Device
353 FlowRule rule3 = rules.stream()
354 .filter(x -> x.deviceId().equals(device3.id()))
355 .findFirst()
356 .get();
357 // validate DST selector (with OduSignalId, where the same TributarySlot is used)
358 TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder();
359 selectorBuilder3.matchInPort(d3p1.port());
360 selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
361 selectorBuilder3.add(Criteria.matchOduSignalId(oduSignalId));
362 assertThat(rule3.selector(), is(selectorBuilder3.build()));
363
364 // validate DST treatment
365 assertThat(rule3.treatment(), is(
366 DefaultTrafficTreatment.builder().setOutput(d3p2.port()).build()
367 ));
368
369 rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
370 intent.priority(), rule.priority()));
371
372 sut.deactivate();
373 }
374
375 /**
376 * Tests compile of OpticalOduIntent with allocation of TributarySlots.
377 * Compile two ODUCLT ports (with CLT_10GBE), over OTU ports (with OTU2):
378 * - All TributarySlots are used
379 */
380 @Test
381 public void test10GbeMultiplexOverOdu2() {
382
383 intent = OpticalOduIntent.builder()
384 .appId(APP_ID)
385 .key(KEY1)
386 .src(d1p3)
387 .dst(d3p3)
388 .signalType(D1P3.signalType())
389 .bidirectional(false)
390 .build();
391
392 sut.activate();
393
394 List<Intent> compiled = sut.compile(intent, Collections.emptyList());
395 assertThat(compiled, hasSize(1));
396
397 Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
398
399 // 1st Device
400 FlowRule rule1 = rules.stream()
401 .filter(x -> x.deviceId().equals(device1.id()))
402 .findFirst()
403 .get();
404 // validate SRC selector
405 TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
406 selectorBuilder1.matchInPort(d1p3.port());
407 selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
408 assertThat(rule1.selector(), is(selectorBuilder1.build()));
409
410 // validate SRC treatment (without OduSignalId - all TributarySlots are used)
411 TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
412 treatmentBuilder1.setOutput(d1p2.port());
413 assertThat(rule1.treatment(), is(treatmentBuilder1.build()));
414
415 // 2nd Device
416 FlowRule rule2 = rules.stream()
417 .filter(x -> x.deviceId().equals(device2.id()))
418 .findFirst()
419 .get();
420 // validate SRC selector
421 TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
422 selectorBuilder2.matchInPort(d2p1.port());
423 selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
424 assertThat(rule2.selector(), is(selectorBuilder2.build()));
425
426 // validate SRC treatment (without OduSignalId - all TributarySlots are used)
427 TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder();
428 treatmentBuilder2.setOutput(d2p2.port());
429 assertThat(rule2.treatment(), is(treatmentBuilder2.build()));
430
431
432 // 3rd Device
433 FlowRule rule3 = rules.stream()
434 .filter(x -> x.deviceId().equals(device3.id()))
435 .findFirst()
436 .get();
437 // validate DST selector (without OduSignalId - all TributarySlots are used)
438 TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder();
439 selectorBuilder3.matchInPort(d3p1.port());
440 selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
441 assertThat(rule3.selector(), is(selectorBuilder3.build()));
442
443 // validate DST treatment
444 assertThat(rule3.treatment(), is(
445 DefaultTrafficTreatment.builder().setOutput(d3p3.port()).build()
446 ));
447
448 rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
449 intent.priority(), rule.priority()));
450
451 sut.deactivate();
452 }
453
454}