blob: c4040ed89aa8448c6456e2c654920fbecb27b637 [file] [log] [blame]
Priyanka Bb6963582016-05-20 20:21:20 +05301/*
2 * Copyright 2016-present 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.pce.pceservice;
17
18import org.junit.After;
19import org.junit.Before;
20import org.junit.Test;
21import org.onlab.graph.AbstractGraphPathSearch;
22import org.onlab.graph.AdjacencyListsGraph;
23import org.onlab.graph.DijkstraGraphSearch;
24import org.onlab.graph.Graph;
25import org.onlab.graph.GraphPathSearch;
26import org.onlab.packet.ChassisId;
27import org.onlab.util.Bandwidth;
28import org.onlab.util.Tools;
29import org.onosproject.net.AnnotationKeys;
30import org.onosproject.net.ConnectPoint;
31import org.onosproject.net.DefaultAnnotations;
32import org.onosproject.net.DefaultDevice;
33import org.onosproject.net.DefaultLink;
34import org.onosproject.net.DefaultPath;
35import org.onosproject.net.Device;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.Link;
38import org.onosproject.net.Path;
39import org.onosproject.net.PortNumber;
40import org.onosproject.net.intent.Constraint;
41import org.onosproject.net.intent.IntentId;
42import org.onosproject.net.Device.Type;
43import org.onosproject.net.intent.constraint.BandwidthConstraint;
44import org.onosproject.net.device.DeviceServiceAdapter;
45import org.onosproject.net.resource.ContinuousResource;
46import org.onosproject.net.resource.ContinuousResourceId;
47import org.onosproject.net.resource.DiscreteResource;
48import org.onosproject.net.resource.DiscreteResourceId;
49import org.onosproject.net.resource.Resource;
50import org.onosproject.net.resource.ResourceAllocation;
51import org.onosproject.net.resource.ResourceConsumer;
52import org.onosproject.net.resource.ResourceId;
53import org.onosproject.net.resource.Resources;
54import org.onosproject.net.provider.ProviderId;
55import org.onosproject.net.topology.DefaultTopologyEdge;
56import org.onosproject.net.topology.DefaultTopologyVertex;
57import org.onosproject.net.topology.LinkWeight;
58import org.onosproject.net.topology.TopologyEdge;
59import org.onosproject.net.topology.TopologyVertex;
60import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
61import org.onosproject.pce.pceservice.constraint.CostConstraint;
62import org.onosproject.pce.pceservice.constraint.SharedBandwidthConstraint;
63
64import com.google.common.collect.ImmutableList;
65import com.google.common.collect.ImmutableSet;
66
67import java.util.Collections;
68import java.util.HashMap;
69import java.util.HashSet;
70import java.util.Iterator;
71import java.util.LinkedList;
72import java.util.List;
73import java.util.Map;
74import java.util.Optional;
75import java.util.Set;
76import java.util.stream.Collectors;
77
78import static org.hamcrest.MatcherAssert.assertThat;
79import static org.hamcrest.core.Is.is;
80import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
81import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
82import static com.google.common.collect.ImmutableSet.of;
83import static org.onosproject.net.resource.Resources.continuous;
84import static org.onosproject.net.Link.Type.DIRECT;
85import static org.onosproject.net.Link.State.ACTIVE;
86import static org.onosproject.net.DeviceId.deviceId;
87import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.COST;
88import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.TE_COST;
89
90/**
91 * Test for CSPF path computation.
92 */
93public class PathComputationTest {
94
95 private final MockPathResourceService resourceService = new MockPathResourceService();
96 private final MockDeviceService deviceService = new MockDeviceService();
97 private PceManager pceManager = new PceManager();
98 public static ProviderId providerId = new ProviderId("pce", "foo");
Avantika-Huaweidbdf7722016-05-21 14:20:31 +053099 public static final String DEVICE1 = "D001";
100 public static final String DEVICE2 = "D002";
101 public static final String DEVICE3 = "D003";
102 public static final String DEVICE4 = "D004";
103 public static final String DEVICE5 = "D005";
Priyanka Bb6963582016-05-20 20:21:20 +0530104 public static final String PCEPDEVICE1 = "PD001";
105 public static final String PCEPDEVICE2 = "PD002";
106 public static final String PCEPDEVICE3 = "PD003";
107 public static final String PCEPDEVICE4 = "PD004";
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530108 public static final TopologyVertex D1 = new DefaultTopologyVertex(DeviceId.deviceId("D001"));
109 public static final TopologyVertex D2 = new DefaultTopologyVertex(DeviceId.deviceId("D002"));
110 public static final TopologyVertex D3 = new DefaultTopologyVertex(DeviceId.deviceId("D003"));
111 public static final TopologyVertex D4 = new DefaultTopologyVertex(DeviceId.deviceId("D004"));
112 public static final TopologyVertex D5 = new DefaultTopologyVertex(DeviceId.deviceId("D005"));
Priyanka Bb6963582016-05-20 20:21:20 +0530113 private static final String ANNOTATION_COST = "cost";
114 private static final String ANNOTATION_TE_COST = "teCost";
115 private static final String UNKNOWN = "unknown";
116 public static final String LSRID = "lsrId";
117 public static final String L3 = "L3";
118 public static final String PCECC_CAPABILITY = "pceccCapability";
119 public static final String SR_CAPABILITY = "srCapability";
120 public static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
121
122 @Before
123 public void startUp() {
124 pceManager.resourceService = resourceService;
125 pceManager.deviceService = deviceService;
126 }
127
128 /**
129 * Selects path computation algorithm.
130 *
131 * @return graph path search algorithm
132 */
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530133 public static AbstractGraphPathSearch<TopologyVertex, TopologyEdge> graphSearch() {
Priyanka Bb6963582016-05-20 20:21:20 +0530134 return new DijkstraGraphSearch<>();
135 }
136
137 /**
138 * Returns link for two devices.
139 *
140 * @param device source device
141 * @param port source port
142 * @param device2 destination device
143 * @param port2 destination port
144 * @return link
145 */
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530146 public static Link addLink(String device, long port, String device2, long port2, boolean setCost, int value) {
Priyanka Bb6963582016-05-20 20:21:20 +0530147 ConnectPoint src = new ConnectPoint(DeviceId.deviceId(device), PortNumber.portNumber(port));
148 ConnectPoint dst = new ConnectPoint(DeviceId.deviceId(device2), PortNumber.portNumber(port2));
149 Link curLink;
150 DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
151 if (setCost) {
152 annotationBuilder.set(ANNOTATION_COST, String.valueOf(value));
153 } else {
154 annotationBuilder.set(ANNOTATION_TE_COST, String.valueOf(value));
155 }
156
157 //TODO:If cost not set cost : default value case
158 curLink = DefaultLink.builder().src(src).dst(dst).state(ACTIVE).type(DIRECT)
159 .providerId(PathComputationTest.providerId).annotations(annotationBuilder.build()).build();
160 return curLink;
161 }
162
163 @After
164 public void tearDown() {
165 pceManager.resourceService = null;
166 pceManager.deviceService = null;
167 }
168
169 /**
170 * Returns an edge-weight capable of evaluating links on the basis of the
171 * specified constraints.
172 *
173 * @param constraints path constraints
174 * @return edge-weight function
175 */
176 private LinkWeight weight(List<Constraint> constraints) {
177 return new MockTeConstraintBasedLinkWeight(constraints);
178 }
179
180 private Set<Path> computePath(Link link1, Link link2, Link link3, Link link4, List<Constraint> constraints) {
181 Graph<TopologyVertex, TopologyEdge> graph = new AdjacencyListsGraph<>(of(D1, D2, D3, D4),
182 of(new DefaultTopologyEdge(D1, D2, link1),
183 new DefaultTopologyEdge(D2, D4, link2),
184 new DefaultTopologyEdge(D1, D3, link3),
185 new DefaultTopologyEdge(D3, D4, link4)));
186
187 GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
188 graphSearch().search(graph, D1, D4, weight(constraints), ALL_PATHS);
189 ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
190 for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
191 builder.add(networkPath(path));
192 }
193 return builder.build();
194 }
195
196 private class MockDeviceService extends DeviceServiceAdapter {
197 List<Device> devices = new LinkedList<>();
198
199 private void addDevice(Device dev) {
200 devices.add(dev);
201 }
202
203 @Override
204 public Device getDevice(DeviceId deviceId) {
205 for (Device dev : devices) {
206 if (dev.id().equals(deviceId)) {
207 return dev;
208 }
209 }
210 return null;
211 }
212
213 @Override
214 public Iterable<Device> getAvailableDevices() {
215 return devices;
216 }
217 }
218
219 private class MockTeConstraintBasedLinkWeight implements LinkWeight {
220
221 private final List<Constraint> constraints;
222
223 /**
224 * Creates a new edge-weight function capable of evaluating links
225 * on the basis of the specified constraints.
226 *
227 * @param constraints path constraints
228 */
229 MockTeConstraintBasedLinkWeight(List<Constraint> constraints) {
230 if (constraints == null) {
231 this.constraints = Collections.emptyList();
232 } else {
233 this.constraints = ImmutableList.copyOf(constraints);
234 }
235 }
236
237 public double weight(TopologyEdge edge) {
238 if (!constraints.iterator().hasNext()) {
239 //Takes default cost/hopcount as 1 if no constraints specified
240 return 1.0;
241 }
242
243 Iterator<Constraint> it = constraints.iterator();
244 double cost = 1;
245
246 //If any constraint fails return -1 also value of cost returned from cost constraint can't be negative
247 while (it.hasNext() && cost > 0) {
248 Constraint constraint = it.next();
249 if (constraint instanceof CapabilityConstraint) {
250 cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService) ? 1 : -1;
251 } else {
252 cost = constraint.cost(edge.link(), resourceService::isAvailable);
253 }
254 }
255 return cost;
256 }
257 }
258
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530259 /**
260 * Returns the path in Path object format.
261 */
262 public static Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
Priyanka Bb6963582016-05-20 20:21:20 +0530263 List<Link> links = path.edges().stream().map(TopologyEdge::link).collect(Collectors.toList());
264 return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
265 }
266
267 /**
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530268 * Tests Resource service for path computation.
Priyanka Bb6963582016-05-20 20:21:20 +0530269 */
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530270 public class MockPathResourceService extends ResourceServiceAdapter {
Priyanka Bb6963582016-05-20 20:21:20 +0530271 private final Map<Resource, ResourceConsumer> assignment = new HashMap<>();
272 private Map<ResourceId, List<ResourceAllocation>> resourcesAllocations = new HashMap<>();
273
274 @Override
Avantika-Huaweidbdf7722016-05-21 14:20:31 +0530275 public Optional<ResourceAllocation> allocate(ResourceConsumer consumer, Resource resources) {
276 List<ResourceAllocation> allocations = allocate(consumer, ImmutableList.of(resources));
277 if (allocations.isEmpty()) {
278 return Optional.empty();
279 }
280
281 assert allocations.size() == 1;
282 ResourceAllocation allocation = allocations.get(0);
283 assert allocation.resource().equals(resources);
284
285 // cast is ensured by the assertions above
286 return Optional.of(allocation);
287 }
288
289 @Override
Priyanka Bb6963582016-05-20 20:21:20 +0530290 public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<Resource> resources) {
291 for (Resource resource: resources) {
292 if (resource instanceof ContinuousResource) {
293 List<ResourceAllocation> allocs = new LinkedList<>();
294 allocs.add(new ResourceAllocation(resource, consumer));
295 resourcesAllocations.put(resource.id(), allocs);
296 }
297 }
298 return resources.stream()
299 .map(x -> new ResourceAllocation(x, consumer))
300 .collect(Collectors.toList());
301 }
302
303 @Override
304 public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
305 if (id instanceof ContinuousResourceId) {
306 return resourcesAllocations.get(id);
307 }
308 DiscreteResource discrete = Resources.discrete((DiscreteResourceId) id).resource();
309 return Optional.ofNullable(assignment.get(discrete))
310 .map(x -> ImmutableList.of(new ResourceAllocation(discrete, x)))
311 .orElse(ImmutableList.of());
312 }
313
314 @Override
315 public <T> Set<Resource> getAvailableResources(DiscreteResourceId parent, Class<T> cls) {
316 return getAvailableResources(parent).stream()
317 .filter(x -> x.isTypeOf(cls))
318 .collect(Collectors.toSet());
319 }
320
321 @Override
322 public <T> Set<T> getAvailableResourceValues(DiscreteResourceId parent, Class<T> cls) {
323 return getAvailableResources(parent).stream()
324 .filter(x -> x.isTypeOf(cls))
325 .flatMap(x -> Tools.stream(x.valueAs(cls)))
326 .collect(Collectors.toSet());
327 }
328
329 @Override
330 public boolean isAvailable(Resource resource) {
331 if (resource instanceof DiscreteResource) {
332 return true;
333 }
334
335 if (resource instanceof ContinuousResource) {
336 List<ResourceAllocation> resalloc = resourcesAllocations.get(resource.id());
337
338 if ((resalloc != null) && (!resalloc.isEmpty())) {
339 if (((ContinuousResource) resalloc.iterator().next().resource()).value()
340 >= ((ContinuousResource) resource).value()) {
341 return true;
342 }
343 }
344 }
345 return false;
346 }
347 }
348
349 /**
350 * All links with different costs with L1-L2 as least cost path.
351 */
352 @Test
353 public void testpathComputationCase1() {
354 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
355 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
356 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
357 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 50);
358
359 CostConstraint costConst = CostConstraint.of(COST);
360 List<Constraint> constraints = new LinkedList<>();
361 constraints.add(costConst);
362
363 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
364
365 List<Link> links = new LinkedList<>();
366
367 links.add(link1);
368 links.add(link2);
369
370 assertThat(paths.iterator().next().links(), is(links));
371 assertThat(paths.iterator().next().cost(), is((double) 70));
372 }
373
374 /**
375 * Links with same cost 100 except link3.
376 */
377 @Test
378 public void testpathComputationCase2() {
379 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 100);
380 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 100);
381 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 1000);
382 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 100);
383
384 CostConstraint costConst = CostConstraint.of(COST);
385 List<Constraint> constraints = new LinkedList<>();
386 constraints.add(costConst);
387 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
388
389 List<Link> links = new LinkedList<>();
390 links.add(link1);
391 links.add(link2);
392
393 assertThat(paths.iterator().next().links(), is(links));
394 assertThat(paths.iterator().next().cost(), is((double) 200));
395 }
396
397 /**
398 * Path which satisfy bandwidth as a constraint with 10bps.
399 */
400 @Test
401 public void testpathComputationCase3() {
402 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
403 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
404 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
405 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 50);
406
407 List<Resource> resources = new LinkedList<>();
408
409 resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class)
410 .resource(50));
411 resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class)
412 .resource(50));
413 resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class)
414 .resource(100));
415 resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class)
416 .resource(100));
417
418 resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class)
419 .resource(50));
420 resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class)
421 .resource(50));
422 resources.add(continuous(link3.dst().deviceId(), link3.src().port(), Bandwidth.class)
423 .resource(100));
424 resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class)
425 .resource(100));
426
427 resourceService.allocate(IntentId.valueOf(70), resources);
428
429 BandwidthConstraint bandwidthConst = new BandwidthConstraint(Bandwidth.bps(10.0));
430
431 List<Constraint> constraints = new LinkedList<>();
432 constraints.add(bandwidthConst);
433
434 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
435
436 assertThat(paths.iterator().next().cost(), is((double) 2));
437 }
438
439 /**
440 * Path which satisfy bandwidth as a constraint with 60bps.
441 */
442 @Test
443 public void testpathComputationCase4() {
444 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
445 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 50);
446 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
447 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 100);
448
449 List<Resource> resources = new LinkedList<>();
450
451 resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50));
452 resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50));
453 resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100));
454 resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100));
455
456 resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50));
457 resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50));
458 resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100));
459 resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100));
460
461 resourceService.allocate(IntentId.valueOf(70), resources);
462
463 BandwidthConstraint bandwidthConst = new BandwidthConstraint(Bandwidth.bps(60.0));
464
465 List<Constraint> constraints = new LinkedList<>();
466 constraints.add(bandwidthConst);
467 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
468
469 assertThat(paths.iterator().next().cost(), is((double) 2));
470 }
471
472 /**
473 * Shared bandwidth as L1, L2 with its value 10 bps and bandwidth constraint as 20 bps.
474 */
475 @Test
476 public void testpathComputationCase5() {
477 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
478 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
479 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
480 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
481
482 List<Resource> resources = new LinkedList<>();
483
484 resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50));
485 resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50));
486 resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100));
487 resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100));
488
489 resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50));
490 resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50));
491 resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100));
492 resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100));
493 resourceService.allocate(IntentId.valueOf(70), resources);
494
495 List<Constraint> constraints = new LinkedList<>();
496
497 List<Link> sharedLinks = new LinkedList<>();
498
499 List<Link> links = new LinkedList<>();
500 links.add(link1);
501 links.add(link2);
502
503 CostConstraint costConst = CostConstraint.of(COST);
504 sharedLinks.addAll(links);
505 SharedBandwidthConstraint sharedBw = new SharedBandwidthConstraint(sharedLinks, Bandwidth.bps(10),
506 Bandwidth.bps(20.0));
507 constraints.add(sharedBw);
508 constraints.add(costConst);
509 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
510 assertThat(paths.iterator().next().links(), is(links));
511 assertThat(paths.iterator().next().cost(), is((double) 70));
512 }
513
514 /**
515 * Shared bandwidth as L1, L2 with its value 20 bps and bandwidth constraint as 10 bps.
516 */
517 @Test
518 public void testpathComputationCase6() {
519 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
520 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
521 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
522 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
523
524 List<Resource> resources = new LinkedList<>();
525
526 resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50));
527 resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50));
528 resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100));
529 resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100));
530
531 resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50));
532 resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50));
533 resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100));
534 resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100));
535 resourceService.allocate(IntentId.valueOf(70), resources);
536
537 List<Constraint> constraints = new LinkedList<>();
538
539 List<Link> sharedLinks = new LinkedList<>();
540
541 List<Link> links = new LinkedList<>();
542 links.add(link1);
543 links.add(link2);
544 CostConstraint costConst = CostConstraint.of(COST);
545 sharedLinks.addAll(links);
546 SharedBandwidthConstraint sharedBwConst = new SharedBandwidthConstraint(sharedLinks, Bandwidth.bps(20),
547 Bandwidth.bps(10.0));
548 constraints.add(sharedBwConst);
549 constraints.add(costConst);
550 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
551
552 assertThat(paths.iterator().next().links(), is(links));
553 assertThat(paths.iterator().next().cost(), is((double) 70));
554 }
555
556 /**
557 * Path without constraints.
558 */
559 @Test
560 public void testpathComputationCase7() {
561 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
562 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
563 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
564 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
565 List<Constraint> constraints = new LinkedList<>();
566 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
567
568 assertThat(paths.iterator().next().cost(), is((double) 2));
569 }
570
571 /**
572 * With TeCost as a constraints.
573 */
574 @Test
575 public void testpathComputationCase8() {
576 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
577 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
578 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
579 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
580
581 CostConstraint tecostConst = CostConstraint.of(TE_COST);
582
583 List<Constraint> constraints = new LinkedList<>();
584 constraints.add(tecostConst);
585 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
586
587 List<Link> links = new LinkedList<>();
588 links.add(link1);
589 links.add(link2);
590 assertThat(paths.iterator().next().links(), is(links));
591 assertThat(paths.iterator().next().cost(), is((double) 70));
592 }
593
594 /**
595 * With device supporting RSVP capability as a constraints.
596 */
597 @Test
598 public void testpathComputationCase9() {
599 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
600 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
601 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
602 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
603
604 CostConstraint tecostConst = CostConstraint.of(TE_COST);
605 CapabilityConstraint capabilityConst = CapabilityConstraint
606 .of(CapabilityConstraint.CapabilityType.WITH_SIGNALLING);
607
608 List<Constraint> constraints = new LinkedList<>();
609 constraints.add(capabilityConst);
610 constraints.add(tecostConst);
611 //Device1
612 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
613 builder.set(AnnotationKeys.TYPE, L3);
614 builder.set(LSRID, "1.1.1.1");
615 addDevice(DEVICE1, builder);
616
617 //Device2
618 builder = DefaultAnnotations.builder();
619 builder.set(AnnotationKeys.TYPE, L3);
620 builder.set(LSRID, "2.2.2.2");
621 addDevice(DEVICE2, builder);
622
623 //Device3
624 builder = DefaultAnnotations.builder();
625 builder.set(AnnotationKeys.TYPE, L3);
626 builder.set(LSRID, "3.3.3.3");
627 addDevice(DEVICE3, builder);
628
629 //Device4
630 builder = DefaultAnnotations.builder();
631 builder.set(AnnotationKeys.TYPE, L3);
632 builder.set(LSRID, "4.4.4.4");
633 addDevice(DEVICE4, builder);
634
635 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
636
637 List<Link> links = new LinkedList<>();
638 links.add(link1);
639 links.add(link2);
640 assertThat(paths.iterator().next().links(), is(links));
641 assertThat(paths.iterator().next().cost(), is((double) 70));
642 }
643
644 /**
645 * Devices supporting CR capability.
646 */
647 @Test
648 public void testpathComputationCase10() {
649 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
650 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
651 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
652 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
653
654 CapabilityConstraint capabilityConst = CapabilityConstraint
655 .of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR);
656
657 List<Constraint> constraints = new LinkedList<>();
658 constraints.add(capabilityConst);
659 CostConstraint costConst = CostConstraint.of(COST);
660 constraints.add(costConst);
661 //Device1
662 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
663 builder.set(AnnotationKeys.TYPE, L3);
664 builder.set(LSRID, "1.1.1.1");
665 addDevice(DEVICE1, builder);
666 builder.set(PCECC_CAPABILITY, "true");
667 addDevice(PCEPDEVICE1, builder);
668
669 //Device2
670 builder = DefaultAnnotations.builder();
671 builder.set(AnnotationKeys.TYPE, L3);
672 builder.set(LSRID, "2.2.2.2");
673 addDevice(DEVICE2, builder);
674 builder.set(PCECC_CAPABILITY, "true");
675 addDevice(PCEPDEVICE2, builder);
676
677 //Device3
678 builder = DefaultAnnotations.builder();
679 builder.set(AnnotationKeys.TYPE, L3);
680 builder.set(LSRID, "3.3.3.3");
681 addDevice(DEVICE3, builder);
682 builder.set(PCECC_CAPABILITY, "true");
683 addDevice(PCEPDEVICE3, builder);
684
685 //Device4
686 builder = DefaultAnnotations.builder();
687 builder.set(AnnotationKeys.TYPE, L3);
688 builder.set(LSRID, "4.4.4.4");
689 addDevice(DEVICE4, builder);
690 builder.set(PCECC_CAPABILITY, "true");
691 addDevice(PCEPDEVICE4, builder);
692
693 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
694
695 List<Link> links = new LinkedList<>();
696 links.add(link1);
697 links.add(link2);
698 assertThat(paths.iterator().next().links(), is(links));
699 assertThat(paths.iterator().next().cost(), is((double) 70));
700 }
701
702 /**
703 * Device supporting SR capability.
704 */
705 @Test
706 public void testpathComputationCase11() {
707 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
708 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
709 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
710 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
711
712 CapabilityConstraint capabilityConst = CapabilityConstraint
713 .of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING);
714
715 List<Constraint> constraints = new LinkedList<>();
716 constraints.add(capabilityConst);
717 CostConstraint costConst = CostConstraint.of(COST);
718 constraints.add(costConst);
719 //Device1
720 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
721 builder.set(AnnotationKeys.TYPE, L3);
722 builder.set(LSRID, "1.1.1.1");
723 addDevice(DEVICE1, builder);
724 builder.set(SR_CAPABILITY, "true");
725 builder.set(LABEL_STACK_CAPABILITY, "true");
726 addDevice(PCEPDEVICE1, builder);
727
728 //Device2
729 builder = DefaultAnnotations.builder();
730 builder.set(AnnotationKeys.TYPE, L3);
731 builder.set(LSRID, "2.2.2.2");
732 addDevice(DEVICE2, builder);
733 builder.set(SR_CAPABILITY, "true");
734 builder.set(LABEL_STACK_CAPABILITY, "true");
735 addDevice(PCEPDEVICE2, builder);
736
737 //Device3
738 builder = DefaultAnnotations.builder();
739 builder.set(AnnotationKeys.TYPE, L3);
740 builder.set(LSRID, "3.3.3.3");
741 addDevice(DEVICE3, builder);
742 builder.set(SR_CAPABILITY, "true");
743 builder.set(LABEL_STACK_CAPABILITY, "true");
744 addDevice(PCEPDEVICE3, builder);
745
746 //Device4
747 builder = DefaultAnnotations.builder();
748 builder.set(AnnotationKeys.TYPE, L3);
749 builder.set(LSRID, "4.4.4.4");
750 addDevice(DEVICE4, builder);
751 builder.set(SR_CAPABILITY, "true");
752 builder.set(LABEL_STACK_CAPABILITY, "true");
753 addDevice(PCEPDEVICE4, builder);
754 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
755
756 List<Link> links = new LinkedList<>();
757 links.add(link1);
758 links.add(link2);
759 assertThat(paths.iterator().next().links(), is(links));
760 assertThat(paths.iterator().next().cost(), is((double) 70));
761 }
762
763 /**
764 * Path with TE and SR capability constraint.
765 */
766 @Test
767 public void testpathComputationCase12() {
768 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
769 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
770 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
771 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
772
773 CostConstraint tecostConst = CostConstraint.of(TE_COST);
774 CapabilityConstraint capabilityConst = CapabilityConstraint
775 .of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING);
776
777 List<Constraint> constraints = new LinkedList<>();
778
779 constraints.add(capabilityConst);
780 constraints.add(tecostConst);
781 //Device1
782 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
783 builder.set(AnnotationKeys.TYPE, L3);
784 builder.set(LSRID, "1.1.1.1");
785 addDevice(DEVICE1, builder);
786 builder.set(SR_CAPABILITY, "true");
787 builder.set(LABEL_STACK_CAPABILITY, "true");
788 addDevice(PCEPDEVICE1, builder);
789
790 //Device2
791 builder = DefaultAnnotations.builder();
792 builder.set(AnnotationKeys.TYPE, L3);
793 builder.set(LSRID, "2.2.2.2");
794 addDevice(DEVICE2, builder);
795 builder.set(SR_CAPABILITY, "true");
796 builder.set(LABEL_STACK_CAPABILITY, "true");
797 addDevice(PCEPDEVICE2, builder);
798
799 //Device3
800 builder = DefaultAnnotations.builder();
801 builder.set(AnnotationKeys.TYPE, L3);
802 builder.set(LSRID, "3.3.3.3");
803 addDevice(DEVICE3, builder);
804 builder.set(SR_CAPABILITY, "true");
805 builder.set(LABEL_STACK_CAPABILITY, "true");
806 addDevice(PCEPDEVICE3, builder);
807
808 //Device4
809 builder = DefaultAnnotations.builder();
810 builder.set(AnnotationKeys.TYPE, L3);
811 builder.set(LSRID, "4.4.4.4");
812 addDevice(DEVICE4, builder);
813 builder.set(SR_CAPABILITY, "true");
814 builder.set(LABEL_STACK_CAPABILITY, "true");
815 addDevice(PCEPDEVICE4, builder);
816 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
817
818 List<Link> links = new LinkedList<>();
819 links.add(link1);
820 links.add(link2);
821 assertThat(paths.iterator().next().links(), is(links));
822 assertThat(paths.iterator().next().cost(), is((double) 70));
823 }
824
825 /**
826 * Path with capability constraint and with default cost.
827 */
828 @Test
829 public void testpathComputationCase13() {
830 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
831 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
832 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
833 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
834
835 CapabilityConstraint capabilityConst = CapabilityConstraint
836 .of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING);
837
838 List<Constraint> constraints = new LinkedList<>();
839 constraints.add(capabilityConst);
840 //Device1
841 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
842 builder.set(AnnotationKeys.TYPE, L3);
843 builder.set(LSRID, "1.1.1.1");
844 addDevice(DEVICE1, builder);
845 builder.set(SR_CAPABILITY, "true");
846 builder.set(LABEL_STACK_CAPABILITY, "true");
847 addDevice(PCEPDEVICE1, builder);
848
849 //Device2
850 builder = DefaultAnnotations.builder();
851 builder.set(AnnotationKeys.TYPE, L3);
852 builder.set(LSRID, "2.2.2.2");
853 addDevice(DEVICE2, builder);
854 builder.set(SR_CAPABILITY, "true");
855 builder.set(LABEL_STACK_CAPABILITY, "true");
856 addDevice(PCEPDEVICE2, builder);
857
858 //Device3
859 builder = DefaultAnnotations.builder();
860 builder.set(AnnotationKeys.TYPE, L3);
861 builder.set(LSRID, "3.3.3.3");
862 addDevice(DEVICE3, builder);
863 builder.set(SR_CAPABILITY, "true");
864 builder.set(LABEL_STACK_CAPABILITY, "true");
865 addDevice(PCEPDEVICE3, builder);
866
867 //Device4
868 builder = DefaultAnnotations.builder();
869 builder.set(AnnotationKeys.TYPE, L3);
870 builder.set(LSRID, "4.4.4.4");
871 addDevice(DEVICE4, builder);
872 builder.set(SR_CAPABILITY, "true");
873 builder.set(LABEL_STACK_CAPABILITY, "true");
874 addDevice(PCEPDEVICE4, builder);
875 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
876
877 List<Link> links = new LinkedList<>();
878 links.add(link1);
879 links.add(link2);
880 assertThat(paths.iterator().next().cost(), is((double) 2));
881 }
882
883 /**
884 * Test case with empty constraints.
885 */
886 @Test
887 public void testpathComputationCase14() {
888 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
889 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
890 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
891 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
892
893 List<Constraint> constraints = new LinkedList<>();
894 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
895
896 assertThat(paths.iterator().next().cost(), is((double) 2));
897 }
898
899 /**
900 * Test case with constraints as null.
901 */
902 @Test
903 public void testpathComputationCase15() {
904 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
905 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
906 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
907 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
908
909 List<Constraint> constraints = null;
910 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
911
912 assertThat(paths.iterator().next().cost(), is((double) 2));
913 }
914
915 /**
916 * Path with cost constraint.
917 */
918 @Test
919 public void testpathComputationCase16() {
920 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
921 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 100);
922 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 10);
923 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 10);
924 Link link5 = addLink(DEVICE4, 90, DEVICE5, 100, true, 20);
925
926 CostConstraint costConst = CostConstraint.of(COST);
927
928 List<Constraint> constraints = new LinkedList<>();
929 constraints.add(costConst);
930 Graph<TopologyVertex, TopologyEdge> graph = new AdjacencyListsGraph<>(of(D1, D2, D3, D4, D5),
931 of(new DefaultTopologyEdge(D1, D2, link1),
932 new DefaultTopologyEdge(D2, D4, link2),
933 new DefaultTopologyEdge(D1, D3, link3),
934 new DefaultTopologyEdge(D3, D4, link4),
935 new DefaultTopologyEdge(D4, D5, link5)));
936
937 GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
938 graphSearch().search(graph, D1, D5, weight(constraints), ALL_PATHS);
939 ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
940 for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
941 builder.add(networkPath(path));
942 }
943
944 List<Link> links = new LinkedList<>();
945 links.add(link3);
946 links.add(link4);
947 links.add(link5);
948 assertThat(builder.build().iterator().next().links(), is(links));
949 assertThat(builder.build().iterator().next().cost(), is((double) 40));
950 }
951
952 /**
953 * D3 doesn't support capability constraint, so path is L1-L2.
954 */
955 @Test
956 public void testpathComputationCase17() {
957 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
958 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
959 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
960 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
961
962 CapabilityConstraint capabilityConst = CapabilityConstraint
963 .of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR);
964
965 List<Constraint> constraints = new LinkedList<>();
966 constraints.add(capabilityConst);
967 //Device1
968 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
969 builder.set(AnnotationKeys.TYPE, L3);
970 builder.set(LSRID, "1.1.1.1");
971 addDevice(DEVICE1, builder);
972 builder.set(PCECC_CAPABILITY, "true");
973 addDevice(PCEPDEVICE1, builder);
974
975 //Device2
976 builder = DefaultAnnotations.builder();
977 builder.set(AnnotationKeys.TYPE, L3);
978 builder.set(LSRID, "2.2.2.2");
979 addDevice(DEVICE2, builder);
980 builder.set(PCECC_CAPABILITY, "true");
981 addDevice(PCEPDEVICE2, builder);
982
983 //Device4
984 builder = DefaultAnnotations.builder();
985 builder.set(AnnotationKeys.TYPE, L3);
986 builder.set(LSRID, "4.4.4.4");
987 addDevice(DEVICE4, builder);
988 builder.set(PCECC_CAPABILITY, "true");
989 addDevice(PCEPDEVICE4, builder);
990 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
991
992 List<Link> links = new LinkedList<>();
993 links.add(link1);
994 links.add(link2);
995
996 assertThat(paths.iterator().next().links(), is(links));
997 assertThat(paths.iterator().next().cost(), is((double) 2));
998 }
999
1000 /**
1001 * L2 doesn't support cost constraint and D3 doesn't support capability constraint, both constraint fails hence no
1002 * path.
1003 */
1004 @Test
1005 public void testpathComputationCase18() {
1006 Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
1007 Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
1008 Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 10);
1009 Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 10);
1010
1011 CapabilityConstraint capabilityConst = CapabilityConstraint
1012 .of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR);
1013 CostConstraint costConst = CostConstraint.of(COST);
1014 List<Constraint> constraints = new LinkedList<>();
1015 constraints.add(capabilityConst);
1016 constraints.add(costConst);
1017 //Device1
1018 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
1019 builder.set(AnnotationKeys.TYPE, L3);
1020 builder.set(LSRID, "1.1.1.1");
1021 addDevice(DEVICE2, builder);
1022 builder.set(PCECC_CAPABILITY, "true");
1023 addDevice(PCEPDEVICE1, builder);
1024
1025 //Device2
1026 builder = DefaultAnnotations.builder();
1027 builder.set(AnnotationKeys.TYPE, L3);
1028 builder.set(LSRID, "2.2.2.2");
1029 addDevice(DEVICE2, builder);
1030 builder.set(PCECC_CAPABILITY, "true");
1031 addDevice(PCEPDEVICE2, builder);
1032
1033 //Device4
1034 builder = DefaultAnnotations.builder();
1035 builder.set(AnnotationKeys.TYPE, L3);
1036 builder.set(LSRID, "4.4.4.4");
1037 addDevice(DEVICE4, builder);
1038 builder.set(PCECC_CAPABILITY, "true");
1039 addDevice(PCEPDEVICE4, builder);
1040 Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
1041
1042 assertThat(paths, is(new HashSet<>()));
1043 }
1044
1045 private void addDevice(String device, DefaultAnnotations.Builder builder) {
1046 deviceService.addDevice(new DefaultDevice(ProviderId.NONE, deviceId(device), Type.ROUTER,
1047 UNKNOWN, UNKNOWN, UNKNOWN,
1048 UNKNOWN, new ChassisId(), builder.build()));
1049 }
1050}