Priyanka B
Committed by Gerrit Code Review

[ONOS-4051] Path computation algorithm implementation (Coding & UT).

Change-Id: If94be2ba2a010a203003b7ce38289b516ab20f59
......@@ -18,8 +18,10 @@ package org.onosproject.pce.pceservice;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
......@@ -34,8 +36,15 @@ import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.tunnel.TunnelService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Path;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.resource.ResourceService;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.PathService;
import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.pce.pceservice.api.PceService;
import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.DistributedSet;
import org.onosproject.store.service.Serializer;
......@@ -43,6 +52,8 @@ import org.onosproject.store.service.StorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
/**
* Implementation of PCE service.
*/
......@@ -66,6 +77,15 @@ public class PceManager implements PceService {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PathService pathService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ResourceService resourceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
private ApplicationId appId;
/**
......@@ -92,6 +112,36 @@ public class PceManager implements PceService {
log.info("Stopped");
}
/**
* Returns an edge-weight capable of evaluating links on the basis of the
* specified constraints.
*
* @param constraints path constraints
* @return edge-weight function
*/
private LinkWeight weight(List<Constraint> constraints) {
return new TeConstraintBasedLinkWeight(constraints);
}
/**
* Computes a path between two devices.
*
* @param src ingress device
* @param dst egress device
* @param constraints path constraints
* @return computed path based on constraints
*/
protected Set<Path> computePath(DeviceId src, DeviceId dst, List<Constraint> constraints) {
if (pathService == null) {
return null;
}
Set<Path> paths = pathService.getPaths(src, dst, weight(constraints));
if (!paths.isEmpty()) {
return paths;
}
return null;
}
//[TODO:] handle requests in queue
@Override
public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
......@@ -103,8 +153,8 @@ public class PceManager implements PceService {
checkNotNull(lspType);
// TODO: compute and setup path.
return true;
//TODO: gets the path based on constraints and creates a tunnel in network via tunnel manager
return computePath(src, dst, constraints) != null ? true : false;
}
......@@ -159,4 +209,44 @@ public class PceManager implements PceService {
return value;
}
protected class TeConstraintBasedLinkWeight implements LinkWeight {
private final List<Constraint> constraints;
/**
* Creates a new edge-weight function capable of evaluating links
* on the basis of the specified constraints.
*
* @param constraints path constraints
*/
public TeConstraintBasedLinkWeight(List<Constraint> constraints) {
if (constraints == null) {
this.constraints = Collections.emptyList();
} else {
this.constraints = ImmutableList.copyOf(constraints);
}
}
@Override
public double weight(TopologyEdge edge) {
if (!constraints.iterator().hasNext()) {
//Takes default cost/hopcount as 1 if no constraints specified
return 1.0;
}
Iterator<Constraint> it = constraints.iterator();
double cost = 1;
//If any constraint fails return -1 also value of cost returned from cost constraint can't be negative
while (it.hasNext() && cost > 0) {
Constraint constraint = it.next();
if (constraint instanceof CapabilityConstraint) {
cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService) ? 1 : -1;
} else {
cost = constraint.cost(edge.link(), resourceService::isAvailable);
}
}
return cost;
}
}
}
\ No newline at end of file
......
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pce.pceservice.constraint;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.Device;
import org.onosproject.net.Link;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.ResourceContext;
import org.onosproject.net.intent.constraint.BooleanConstraint;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Constraint that evaluates whether devices satisfies capability.
*/
public final class CapabilityConstraint extends BooleanConstraint {
private final CapabilityType capabilityType;
public static final String PCECC_CAPABILITY = "pceccCapability";
public static final String SR_CAPABILITY = "srCapability";
public static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
public static final String LSRID = "lsrId";
public static final String L3 = "L3";
public static final String TRUE = "true";
/**
* Represents about capability type.
*/
public enum CapabilityType {
/**
* Signifies that path is created via signaling mode.
*/
WITH_SIGNALLING(0),
/**
* Signifies that path is created via SR mode.
*/
SR_WITHOUT_SIGNALLING(1),
/**
* Signifies that path is created via without signaling and without SR mode.
*/
WITHOUT_SIGNALLING_AND_WITHOUT_SR(2);
int value;
/**
* Assign val with the value as the capability type.
*
* @param val capability type
*/
CapabilityType(int val) {
value = val;
}
/**
* Returns value of capability type.
*
* @return capability type
*/
public byte type() {
return (byte) value;
}
}
// Constructor for serialization
private CapabilityConstraint() {
capabilityType = null;
}
/**
* Creates a new capability constraint.
*
* @param capabilityType type of capability device supports
*/
public CapabilityConstraint(CapabilityType capabilityType) {
this.capabilityType = capabilityType;
}
/**
* Creates a new capability constraint.
*
* @param capabilityType type of capability device supports
* @return instance of CapabilityConstraint for specified capability type
*/
public static CapabilityConstraint of(CapabilityType capabilityType) {
return new CapabilityConstraint(capabilityType);
}
/**
* Obtains type of capability.
*
* @return type of capability
*/
public CapabilityType capabilityType() {
return capabilityType;
}
/**
* Validates the link based on capability constraint.
*
* @param link to validate source and destination based on capability constraint
* @param deviceService instance of DeviceService
* @return true if link satisfies capability constraint otherwise false
*/
public boolean isValidLink(Link link, DeviceService deviceService) {
if (deviceService == null) {
return false;
}
Device srcDevice = deviceService.getDevice(link.src().deviceId());
Device dstDevice = deviceService.getDevice(link.dst().deviceId());
//TODO: Usage of annotations are for transient solution. In future will be replaces with the
// network config service / Projection model.
// L3 device
if (srcDevice == null
|| dstDevice == null
|| srcDevice.annotations().value(AnnotationKeys.TYPE) == null
|| dstDevice.annotations().value(AnnotationKeys.TYPE) == null
|| !srcDevice.annotations().value(AnnotationKeys.TYPE).equals(L3)
|| !dstDevice.annotations().value(AnnotationKeys.TYPE).equals(L3)) {
return false;
}
String scrLsrId = srcDevice.annotations().value(LSRID);
String dstLsrId = dstDevice.annotations().value(LSRID);
Device srcCapDevice = null;
Device dstCapDevice = null;
// Get Capability device
Iterable<Device> devices = deviceService.getAvailableDevices();
for (Device dev : devices) {
if (dev.annotations().value(LSRID).equals(scrLsrId)) {
srcCapDevice = dev;
} else if (dev.annotations().value(LSRID).equals(dstLsrId)) {
dstCapDevice = dev;
}
}
if (srcCapDevice == null || dstCapDevice == null) {
return false;
}
switch (capabilityType) {
case WITH_SIGNALLING:
return true;
case WITHOUT_SIGNALLING_AND_WITHOUT_SR:
if (srcCapDevice.annotations().value(PCECC_CAPABILITY) != null
&& dstCapDevice.annotations().value(PCECC_CAPABILITY) != null) {
return srcCapDevice.annotations().value(PCECC_CAPABILITY).equals(TRUE)
&& dstCapDevice.annotations().value(PCECC_CAPABILITY).equals(TRUE);
}
return false;
case SR_WITHOUT_SIGNALLING:
if (srcCapDevice.annotations().value(LABEL_STACK_CAPABILITY) != null
&& dstCapDevice.annotations().value(LABEL_STACK_CAPABILITY) != null
&& srcCapDevice.annotations().value(SR_CAPABILITY) != null
&& dstCapDevice.annotations().value(SR_CAPABILITY) != null) {
return srcCapDevice.annotations().value(LABEL_STACK_CAPABILITY).equals(TRUE)
&& dstCapDevice.annotations().value(LABEL_STACK_CAPABILITY).equals(TRUE)
&& srcCapDevice.annotations().value(SR_CAPABILITY).equals(TRUE)
&& dstCapDevice.annotations().value(SR_CAPABILITY).equals(TRUE);
}
return false;
default:
return false;
}
}
@Override
public boolean isValid(Link link, ResourceContext context) {
return false;
//Do nothing instead using isValidLink needs device service to validate link
}
@Override
public int hashCode() {
return Objects.hash(capabilityType);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof CapabilityConstraint) {
CapabilityConstraint other = (CapabilityConstraint) obj;
return Objects.equals(this.capabilityType, other.capabilityType);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this)
.add("capabilityType", capabilityType)
.toString();
}
}
\ No newline at end of file
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pce.pceservice.constraint;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.onosproject.net.intent.ResourceContext;
import org.onosproject.net.intent.Constraint;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Constraint that evaluates whether cost for a link is available, if yes return cost for that link.
*/
public final class CostConstraint implements Constraint {
/**
* Represents about cost types.
*/
public enum Type {
/**
* Signifies that cost is IGP cost.
*/
COST(1),
/**
* Signifies that cost is TE cost.
*/
TE_COST(2);
int value;
/**
* Assign val with the value as the Cost type.
*
* @param val Cost type
*/
Type(int val) {
value = val;
}
/**
* Returns value of Cost type.
*
* @return Cost type
*/
public byte type() {
return (byte) value;
}
}
private final Type type;
public static final String TE_COST = "teCost";
public static final String COST = "cost";
// Constructor for serialization
private CostConstraint() {
this.type = null;
}
/**
* Creates a new cost constraint.
*
* @param type of a link
*/
public CostConstraint(Type type) {
this.type = checkNotNull(type, "Type cannot be null");
}
/**
* Creates new CostConstraint with specified cost type.
*
* @param type of cost
* @return instance of CostConstraint
*/
public static CostConstraint of(Type type) {
return new CostConstraint(type);
}
/**
* Returns the type of a cost specified in a constraint.
*
* @return required cost type
*/
public Type type() {
return type;
}
@Override
public int hashCode() {
return Objects.hash(type);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof CostConstraint) {
CostConstraint other = (CostConstraint) obj;
return Objects.equals(this.type, other.type);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this)
.add("type", type)
.toString();
}
@Override
public double cost(Link link, ResourceContext context) {
//TODO: Usage of annotations are for transient solution. In future will be replaces with the
// network config service / Projection model.
switch (type) {
case COST:
if (link.annotations().value(COST) != null) {
return Double.parseDouble(link.annotations().value(COST));
}
//If cost annotations absent return -1[It is not L3 device]
return -1;
case TE_COST:
if (link.annotations().value(TE_COST) != null) {
return Double.parseDouble(link.annotations().value(TE_COST));
}
//If TE cost annotations absent return -1[It is not L3 device]
return -1;
default:
return -1;
}
}
@Override
public boolean validate(Path path, ResourceContext context) {
// TODO Auto-generated method stub
return false;
}
}
\ No newline at end of file
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pce.pceservice.constraint;
import org.onlab.util.Bandwidth;
import org.onosproject.net.Link;
import org.onosproject.net.intent.ResourceContext;
import org.onosproject.net.intent.constraint.BooleanConstraint;
import org.onosproject.net.resource.Resources;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Constraint that evaluates whether links satisfies sharedbandwidth request.
*/
public final class SharedBandwidthConstraint extends BooleanConstraint {
private final List<Link> links;
private final Bandwidth sharedBwValue;
private final Bandwidth requestBwValue;
//temporary variable declared to hold changed bandwidth value
private Bandwidth changedBwValue;
// Constructor for serialization
private SharedBandwidthConstraint() {
links = null;
sharedBwValue = null;
requestBwValue = null;
}
/**
* Creates a new SharedBandwidth constraint.
*
* @param links shared links
* @param sharedBwValue shared bandwidth of the links
* @param requestBwValue requested bandwidth value
*/
public SharedBandwidthConstraint(List<Link> links, Bandwidth sharedBwValue, Bandwidth requestBwValue) {
this.links = links;
this.sharedBwValue = sharedBwValue;
this.requestBwValue = requestBwValue;
}
/**
* Creates a new SharedBandwidth constraint.
*
* @param links shared links
* @param sharedBwValue shared bandwidth of the links
* @param requestBwValue requested bandwidth value
* @return SharedBandwidth instance
*/
public static SharedBandwidthConstraint of(List<Link> links, Bandwidth sharedBwValue, Bandwidth requestBwValue) {
return new SharedBandwidthConstraint(links, sharedBwValue, requestBwValue);
}
/**
* Obtains shared links.
*
* @return shared links
*/
public List<Link> links() {
return links;
}
/**
* Obtains shared bandwidth of the links.
*
* @return shared bandwidth
*/
public Bandwidth sharedBwValue() {
return sharedBwValue;
}
/**
* Obtains requested bandwidth value.
*
* @return requested bandwidth value
*/
public Bandwidth requestBwValue() {
return requestBwValue;
}
@Override
public boolean isValid(Link link, ResourceContext context) {
changedBwValue = requestBwValue;
if (links.contains(link)) {
changedBwValue = requestBwValue.isGreaterThan(sharedBwValue) ? requestBwValue.subtract(sharedBwValue)
: Bandwidth.bps(0);
}
return Stream
.of(link.src(), link.dst())
.map(cp -> Resources.continuous(cp.deviceId(), cp.port(), Bandwidth.class).resource(
changedBwValue.bps())).allMatch(context::isAvailable);
}
@Override
public int hashCode() {
return Objects.hash(requestBwValue, sharedBwValue, links);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof SharedBandwidthConstraint) {
SharedBandwidthConstraint other = (SharedBandwidthConstraint) obj;
return Objects.equals(this.requestBwValue, other.requestBwValue)
&& Objects.equals(this.sharedBwValue, other.sharedBwValue)
&& Objects.equals(this.links, other.links);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this)
.add("requestBwValue", requestBwValue)
.add("sharedBwValue", sharedBwValue)
.add("links", links)
.toString();
}
}
\ No newline at end of file
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Constraints for path computation for PCE service.
*/
package org.onosproject.pce.pceservice.constraint;
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pce.pceservice;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.graph.AbstractGraphPathSearch;
import org.onlab.graph.AdjacencyListsGraph;
import org.onlab.graph.DijkstraGraphSearch;
import org.onlab.graph.Graph;
import org.onlab.graph.GraphPathSearch;
import org.onlab.packet.ChassisId;
import org.onlab.util.Bandwidth;
import org.onlab.util.Tools;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.Device.Type;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.resource.ContinuousResource;
import org.onosproject.net.resource.ContinuousResourceId;
import org.onosproject.net.resource.DiscreteResource;
import org.onosproject.net.resource.DiscreteResourceId;
import org.onosproject.net.resource.Resource;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceConsumer;
import org.onosproject.net.resource.ResourceId;
import org.onosproject.net.resource.Resources;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.DefaultTopologyEdge;
import org.onosproject.net.topology.DefaultTopologyVertex;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.net.topology.TopologyVertex;
import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
import org.onosproject.pce.pceservice.constraint.CostConstraint;
import org.onosproject.pce.pceservice.constraint.SharedBandwidthConstraint;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
import static com.google.common.collect.ImmutableSet.of;
import static org.onosproject.net.resource.Resources.continuous;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.onosproject.net.Link.State.ACTIVE;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.COST;
import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.TE_COST;
/**
* Test for CSPF path computation.
*/
public class PathComputationTest {
private final MockPathResourceService resourceService = new MockPathResourceService();
private final MockDeviceService deviceService = new MockDeviceService();
private PceManager pceManager = new PceManager();
public static ProviderId providerId = new ProviderId("pce", "foo");
private static final String DEVICE1 = "D001";
private static final String DEVICE2 = "D002";
private static final String DEVICE3 = "D003";
private static final String DEVICE4 = "D004";
private static final String DEVICE5 = "D005";
public static final String PCEPDEVICE1 = "PD001";
public static final String PCEPDEVICE2 = "PD002";
public static final String PCEPDEVICE3 = "PD003";
public static final String PCEPDEVICE4 = "PD004";
private static final TopologyVertex D1 = new DefaultTopologyVertex(DeviceId.deviceId("D001"));
private static final TopologyVertex D2 = new DefaultTopologyVertex(DeviceId.deviceId("D002"));
private static final TopologyVertex D3 = new DefaultTopologyVertex(DeviceId.deviceId("D003"));
private static final TopologyVertex D4 = new DefaultTopologyVertex(DeviceId.deviceId("D004"));
private static final TopologyVertex D5 = new DefaultTopologyVertex(DeviceId.deviceId("D005"));
private static final String ANNOTATION_COST = "cost";
private static final String ANNOTATION_TE_COST = "teCost";
private static final String UNKNOWN = "unknown";
public static final String LSRID = "lsrId";
public static final String L3 = "L3";
public static final String PCECC_CAPABILITY = "pceccCapability";
public static final String SR_CAPABILITY = "srCapability";
public static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
@Before
public void startUp() {
pceManager.resourceService = resourceService;
pceManager.deviceService = deviceService;
}
/**
* Selects path computation algorithm.
*
* @return graph path search algorithm
*/
private AbstractGraphPathSearch<TopologyVertex, TopologyEdge> graphSearch() {
return new DijkstraGraphSearch<>();
}
/**
* Returns link for two devices.
*
* @param device source device
* @param port source port
* @param device2 destination device
* @param port2 destination port
* @return link
*/
private Link addLink(String device, long port, String device2, long port2, boolean setCost, int value) {
ConnectPoint src = new ConnectPoint(DeviceId.deviceId(device), PortNumber.portNumber(port));
ConnectPoint dst = new ConnectPoint(DeviceId.deviceId(device2), PortNumber.portNumber(port2));
Link curLink;
DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
if (setCost) {
annotationBuilder.set(ANNOTATION_COST, String.valueOf(value));
} else {
annotationBuilder.set(ANNOTATION_TE_COST, String.valueOf(value));
}
//TODO:If cost not set cost : default value case
curLink = DefaultLink.builder().src(src).dst(dst).state(ACTIVE).type(DIRECT)
.providerId(PathComputationTest.providerId).annotations(annotationBuilder.build()).build();
return curLink;
}
@After
public void tearDown() {
pceManager.resourceService = null;
pceManager.deviceService = null;
}
/**
* Returns an edge-weight capable of evaluating links on the basis of the
* specified constraints.
*
* @param constraints path constraints
* @return edge-weight function
*/
private LinkWeight weight(List<Constraint> constraints) {
return new MockTeConstraintBasedLinkWeight(constraints);
}
private Set<Path> computePath(Link link1, Link link2, Link link3, Link link4, List<Constraint> constraints) {
Graph<TopologyVertex, TopologyEdge> graph = new AdjacencyListsGraph<>(of(D1, D2, D3, D4),
of(new DefaultTopologyEdge(D1, D2, link1),
new DefaultTopologyEdge(D2, D4, link2),
new DefaultTopologyEdge(D1, D3, link3),
new DefaultTopologyEdge(D3, D4, link4)));
GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
graphSearch().search(graph, D1, D4, weight(constraints), ALL_PATHS);
ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
builder.add(networkPath(path));
}
return builder.build();
}
private class MockDeviceService extends DeviceServiceAdapter {
List<Device> devices = new LinkedList<>();
private void addDevice(Device dev) {
devices.add(dev);
}
@Override
public Device getDevice(DeviceId deviceId) {
for (Device dev : devices) {
if (dev.id().equals(deviceId)) {
return dev;
}
}
return null;
}
@Override
public Iterable<Device> getAvailableDevices() {
return devices;
}
}
private class MockTeConstraintBasedLinkWeight implements LinkWeight {
private final List<Constraint> constraints;
/**
* Creates a new edge-weight function capable of evaluating links
* on the basis of the specified constraints.
*
* @param constraints path constraints
*/
MockTeConstraintBasedLinkWeight(List<Constraint> constraints) {
if (constraints == null) {
this.constraints = Collections.emptyList();
} else {
this.constraints = ImmutableList.copyOf(constraints);
}
}
public double weight(TopologyEdge edge) {
if (!constraints.iterator().hasNext()) {
//Takes default cost/hopcount as 1 if no constraints specified
return 1.0;
}
Iterator<Constraint> it = constraints.iterator();
double cost = 1;
//If any constraint fails return -1 also value of cost returned from cost constraint can't be negative
while (it.hasNext() && cost > 0) {
Constraint constraint = it.next();
if (constraint instanceof CapabilityConstraint) {
cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService) ? 1 : -1;
} else {
cost = constraint.cost(edge.link(), resourceService::isAvailable);
}
}
return cost;
}
}
private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
List<Link> links = path.edges().stream().map(TopologyEdge::link).collect(Collectors.toList());
return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
}
/**
* Test Resource service for path computation.
*/
private class MockPathResourceService extends ResourceServiceAdapter {
private final Map<Resource, ResourceConsumer> assignment = new HashMap<>();
private Map<ResourceId, List<ResourceAllocation>> resourcesAllocations = new HashMap<>();
@Override
public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<Resource> resources) {
for (Resource resource: resources) {
if (resource instanceof ContinuousResource) {
List<ResourceAllocation> allocs = new LinkedList<>();
allocs.add(new ResourceAllocation(resource, consumer));
resourcesAllocations.put(resource.id(), allocs);
}
}
return resources.stream()
.map(x -> new ResourceAllocation(x, consumer))
.collect(Collectors.toList());
}
@Override
public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
if (id instanceof ContinuousResourceId) {
return resourcesAllocations.get(id);
}
DiscreteResource discrete = Resources.discrete((DiscreteResourceId) id).resource();
return Optional.ofNullable(assignment.get(discrete))
.map(x -> ImmutableList.of(new ResourceAllocation(discrete, x)))
.orElse(ImmutableList.of());
}
@Override
public <T> Set<Resource> getAvailableResources(DiscreteResourceId parent, Class<T> cls) {
return getAvailableResources(parent).stream()
.filter(x -> x.isTypeOf(cls))
.collect(Collectors.toSet());
}
@Override
public <T> Set<T> getAvailableResourceValues(DiscreteResourceId parent, Class<T> cls) {
return getAvailableResources(parent).stream()
.filter(x -> x.isTypeOf(cls))
.flatMap(x -> Tools.stream(x.valueAs(cls)))
.collect(Collectors.toSet());
}
@Override
public boolean isAvailable(Resource resource) {
if (resource instanceof DiscreteResource) {
return true;
}
if (resource instanceof ContinuousResource) {
List<ResourceAllocation> resalloc = resourcesAllocations.get(resource.id());
if ((resalloc != null) && (!resalloc.isEmpty())) {
if (((ContinuousResource) resalloc.iterator().next().resource()).value()
>= ((ContinuousResource) resource).value()) {
return true;
}
}
}
return false;
}
}
/**
* All links with different costs with L1-L2 as least cost path.
*/
@Test
public void testpathComputationCase1() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 50);
CostConstraint costConst = CostConstraint.of(COST);
List<Constraint> constraints = new LinkedList<>();
constraints.add(costConst);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 70));
}
/**
* Links with same cost 100 except link3.
*/
@Test
public void testpathComputationCase2() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 100);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 100);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 1000);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 100);
CostConstraint costConst = CostConstraint.of(COST);
List<Constraint> constraints = new LinkedList<>();
constraints.add(costConst);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 200));
}
/**
* Path which satisfy bandwidth as a constraint with 10bps.
*/
@Test
public void testpathComputationCase3() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 50);
List<Resource> resources = new LinkedList<>();
resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class)
.resource(50));
resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class)
.resource(50));
resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class)
.resource(100));
resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class)
.resource(100));
resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class)
.resource(50));
resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class)
.resource(50));
resources.add(continuous(link3.dst().deviceId(), link3.src().port(), Bandwidth.class)
.resource(100));
resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class)
.resource(100));
resourceService.allocate(IntentId.valueOf(70), resources);
BandwidthConstraint bandwidthConst = new BandwidthConstraint(Bandwidth.bps(10.0));
List<Constraint> constraints = new LinkedList<>();
constraints.add(bandwidthConst);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
assertThat(paths.iterator().next().cost(), is((double) 2));
}
/**
* Path which satisfy bandwidth as a constraint with 60bps.
*/
@Test
public void testpathComputationCase4() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 50);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 100);
List<Resource> resources = new LinkedList<>();
resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50));
resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50));
resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100));
resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100));
resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50));
resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50));
resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100));
resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100));
resourceService.allocate(IntentId.valueOf(70), resources);
BandwidthConstraint bandwidthConst = new BandwidthConstraint(Bandwidth.bps(60.0));
List<Constraint> constraints = new LinkedList<>();
constraints.add(bandwidthConst);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
assertThat(paths.iterator().next().cost(), is((double) 2));
}
/**
* Shared bandwidth as L1, L2 with its value 10 bps and bandwidth constraint as 20 bps.
*/
@Test
public void testpathComputationCase5() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
List<Resource> resources = new LinkedList<>();
resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50));
resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50));
resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100));
resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100));
resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50));
resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50));
resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100));
resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100));
resourceService.allocate(IntentId.valueOf(70), resources);
List<Constraint> constraints = new LinkedList<>();
List<Link> sharedLinks = new LinkedList<>();
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
CostConstraint costConst = CostConstraint.of(COST);
sharedLinks.addAll(links);
SharedBandwidthConstraint sharedBw = new SharedBandwidthConstraint(sharedLinks, Bandwidth.bps(10),
Bandwidth.bps(20.0));
constraints.add(sharedBw);
constraints.add(costConst);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 70));
}
/**
* Shared bandwidth as L1, L2 with its value 20 bps and bandwidth constraint as 10 bps.
*/
@Test
public void testpathComputationCase6() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
List<Resource> resources = new LinkedList<>();
resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(50));
resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(50));
resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(100));
resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(100));
resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(50));
resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(50));
resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(100));
resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(100));
resourceService.allocate(IntentId.valueOf(70), resources);
List<Constraint> constraints = new LinkedList<>();
List<Link> sharedLinks = new LinkedList<>();
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
CostConstraint costConst = CostConstraint.of(COST);
sharedLinks.addAll(links);
SharedBandwidthConstraint sharedBwConst = new SharedBandwidthConstraint(sharedLinks, Bandwidth.bps(20),
Bandwidth.bps(10.0));
constraints.add(sharedBwConst);
constraints.add(costConst);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 70));
}
/**
* Path without constraints.
*/
@Test
public void testpathComputationCase7() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
List<Constraint> constraints = new LinkedList<>();
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
assertThat(paths.iterator().next().cost(), is((double) 2));
}
/**
* With TeCost as a constraints.
*/
@Test
public void testpathComputationCase8() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
CostConstraint tecostConst = CostConstraint.of(TE_COST);
List<Constraint> constraints = new LinkedList<>();
constraints.add(tecostConst);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 70));
}
/**
* With device supporting RSVP capability as a constraints.
*/
@Test
public void testpathComputationCase9() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
CostConstraint tecostConst = CostConstraint.of(TE_COST);
CapabilityConstraint capabilityConst = CapabilityConstraint
.of(CapabilityConstraint.CapabilityType.WITH_SIGNALLING);
List<Constraint> constraints = new LinkedList<>();
constraints.add(capabilityConst);
constraints.add(tecostConst);
//Device1
DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "1.1.1.1");
addDevice(DEVICE1, builder);
//Device2
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "2.2.2.2");
addDevice(DEVICE2, builder);
//Device3
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "3.3.3.3");
addDevice(DEVICE3, builder);
//Device4
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "4.4.4.4");
addDevice(DEVICE4, builder);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 70));
}
/**
* Devices supporting CR capability.
*/
@Test
public void testpathComputationCase10() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
CapabilityConstraint capabilityConst = CapabilityConstraint
.of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR);
List<Constraint> constraints = new LinkedList<>();
constraints.add(capabilityConst);
CostConstraint costConst = CostConstraint.of(COST);
constraints.add(costConst);
//Device1
DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "1.1.1.1");
addDevice(DEVICE1, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE1, builder);
//Device2
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "2.2.2.2");
addDevice(DEVICE2, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE2, builder);
//Device3
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "3.3.3.3");
addDevice(DEVICE3, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE3, builder);
//Device4
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "4.4.4.4");
addDevice(DEVICE4, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE4, builder);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 70));
}
/**
* Device supporting SR capability.
*/
@Test
public void testpathComputationCase11() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 80);
CapabilityConstraint capabilityConst = CapabilityConstraint
.of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING);
List<Constraint> constraints = new LinkedList<>();
constraints.add(capabilityConst);
CostConstraint costConst = CostConstraint.of(COST);
constraints.add(costConst);
//Device1
DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "1.1.1.1");
addDevice(DEVICE1, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE1, builder);
//Device2
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "2.2.2.2");
addDevice(DEVICE2, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE2, builder);
//Device3
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "3.3.3.3");
addDevice(DEVICE3, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE3, builder);
//Device4
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "4.4.4.4");
addDevice(DEVICE4, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE4, builder);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 70));
}
/**
* Path with TE and SR capability constraint.
*/
@Test
public void testpathComputationCase12() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
CostConstraint tecostConst = CostConstraint.of(TE_COST);
CapabilityConstraint capabilityConst = CapabilityConstraint
.of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING);
List<Constraint> constraints = new LinkedList<>();
constraints.add(capabilityConst);
constraints.add(tecostConst);
//Device1
DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "1.1.1.1");
addDevice(DEVICE1, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE1, builder);
//Device2
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "2.2.2.2");
addDevice(DEVICE2, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE2, builder);
//Device3
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "3.3.3.3");
addDevice(DEVICE3, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE3, builder);
//Device4
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "4.4.4.4");
addDevice(DEVICE4, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE4, builder);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 70));
}
/**
* Path with capability constraint and with default cost.
*/
@Test
public void testpathComputationCase13() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
CapabilityConstraint capabilityConst = CapabilityConstraint
.of(CapabilityConstraint.CapabilityType.SR_WITHOUT_SIGNALLING);
List<Constraint> constraints = new LinkedList<>();
constraints.add(capabilityConst);
//Device1
DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "1.1.1.1");
addDevice(DEVICE1, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE1, builder);
//Device2
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "2.2.2.2");
addDevice(DEVICE2, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE2, builder);
//Device3
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "3.3.3.3");
addDevice(DEVICE3, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE3, builder);
//Device4
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "4.4.4.4");
addDevice(DEVICE4, builder);
builder.set(SR_CAPABILITY, "true");
builder.set(LABEL_STACK_CAPABILITY, "true");
addDevice(PCEPDEVICE4, builder);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(paths.iterator().next().cost(), is((double) 2));
}
/**
* Test case with empty constraints.
*/
@Test
public void testpathComputationCase14() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
List<Constraint> constraints = new LinkedList<>();
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
assertThat(paths.iterator().next().cost(), is((double) 2));
}
/**
* Test case with constraints as null.
*/
@Test
public void testpathComputationCase15() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
List<Constraint> constraints = null;
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
assertThat(paths.iterator().next().cost(), is((double) 2));
}
/**
* Path with cost constraint.
*/
@Test
public void testpathComputationCase16() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, true, 100);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 10);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 10);
Link link5 = addLink(DEVICE4, 90, DEVICE5, 100, true, 20);
CostConstraint costConst = CostConstraint.of(COST);
List<Constraint> constraints = new LinkedList<>();
constraints.add(costConst);
Graph<TopologyVertex, TopologyEdge> graph = new AdjacencyListsGraph<>(of(D1, D2, D3, D4, D5),
of(new DefaultTopologyEdge(D1, D2, link1),
new DefaultTopologyEdge(D2, D4, link2),
new DefaultTopologyEdge(D1, D3, link3),
new DefaultTopologyEdge(D3, D4, link4),
new DefaultTopologyEdge(D4, D5, link5)));
GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
graphSearch().search(graph, D1, D5, weight(constraints), ALL_PATHS);
ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
builder.add(networkPath(path));
}
List<Link> links = new LinkedList<>();
links.add(link3);
links.add(link4);
links.add(link5);
assertThat(builder.build().iterator().next().links(), is(links));
assertThat(builder.build().iterator().next().cost(), is((double) 40));
}
/**
* D3 doesn't support capability constraint, so path is L1-L2.
*/
@Test
public void testpathComputationCase17() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, false, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, false, 100);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, false, 80);
CapabilityConstraint capabilityConst = CapabilityConstraint
.of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR);
List<Constraint> constraints = new LinkedList<>();
constraints.add(capabilityConst);
//Device1
DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "1.1.1.1");
addDevice(DEVICE1, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE1, builder);
//Device2
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "2.2.2.2");
addDevice(DEVICE2, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE2, builder);
//Device4
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "4.4.4.4");
addDevice(DEVICE4, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE4, builder);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(paths.iterator().next().links(), is(links));
assertThat(paths.iterator().next().cost(), is((double) 2));
}
/**
* L2 doesn't support cost constraint and D3 doesn't support capability constraint, both constraint fails hence no
* path.
*/
@Test
public void testpathComputationCase18() {
Link link1 = addLink(DEVICE1, 10, DEVICE2, 20, true, 50);
Link link2 = addLink(DEVICE2, 30, DEVICE4, 40, false, 20);
Link link3 = addLink(DEVICE1, 80, DEVICE3, 70, true, 10);
Link link4 = addLink(DEVICE3, 60, DEVICE4, 50, true, 10);
CapabilityConstraint capabilityConst = CapabilityConstraint
.of(CapabilityConstraint.CapabilityType.WITHOUT_SIGNALLING_AND_WITHOUT_SR);
CostConstraint costConst = CostConstraint.of(COST);
List<Constraint> constraints = new LinkedList<>();
constraints.add(capabilityConst);
constraints.add(costConst);
//Device1
DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "1.1.1.1");
addDevice(DEVICE2, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE1, builder);
//Device2
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "2.2.2.2");
addDevice(DEVICE2, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE2, builder);
//Device4
builder = DefaultAnnotations.builder();
builder.set(AnnotationKeys.TYPE, L3);
builder.set(LSRID, "4.4.4.4");
addDevice(DEVICE4, builder);
builder.set(PCECC_CAPABILITY, "true");
addDevice(PCEPDEVICE4, builder);
Set<Path> paths = computePath(link1, link2, link3, link4, constraints);
assertThat(paths, is(new HashSet<>()));
}
private void addDevice(String device, DefaultAnnotations.Builder builder) {
deviceService.addDevice(new DefaultDevice(ProviderId.NONE, deviceId(device), Type.ROUTER,
UNKNOWN, UNKNOWN, UNKNOWN,
UNKNOWN, new ChassisId(), builder.build()));
}
}
\ No newline at end of file
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pce.pceservice;
import org.onosproject.net.resource.DiscreteResourceId;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceConsumer;
import org.onosproject.net.resource.ResourceId;
import org.onosproject.net.resource.ResourceListener;
import org.onosproject.net.resource.Resource;
import org.onosproject.net.resource.ResourceService;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Adapter for resource service for path computation.
*/
public class ResourceServiceAdapter implements ResourceService {
@Override
public void addListener(ResourceListener listener) {
// TODO Auto-generated method stub
}
@Override
public void removeListener(ResourceListener listener) {
// TODO Auto-generated method stub
}
@Override
public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<Resource> resources) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean release(List<ResourceAllocation> allocations) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean release(ResourceConsumer consumer) {
// TODO Auto-generated method stub
return false;
}
@Override
public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
// TODO Auto-generated method stub
return null;
}
@Override
public <T> Collection<ResourceAllocation> getResourceAllocations(DiscreteResourceId parent, Class<T> cls) {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Resource> getAvailableResources(DiscreteResourceId parent) {
// TODO Auto-generated method stub
return null;
}
@Override
public <T> Set<Resource> getAvailableResources(DiscreteResourceId parent, Class<T> cls) {
// TODO Auto-generated method stub
return null;
}
@Override
public <T> Set<T> getAvailableResourceValues(DiscreteResourceId parent, Class<T> cls) {
// TODO Auto-generated method stub
return null;
}
@Override
public Set<Resource> getRegisteredResources(DiscreteResourceId parent) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isAvailable(Resource resource) {
// TODO Auto-generated method stub
return false;
}
}