Priyanka B
Committed by Gerrit Code Review

[ONOS-5187] Compute path with Explicit path objects

Change-Id: Id34dbef9bd6cfa9971d0d10adf4bbc141f03a913
Showing 22 changed files with 1143 additions and 93 deletions
......@@ -105,5 +105,10 @@
<groupId>org.onosproject</groupId>
<artifactId>onos-app-pcep-api</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
......
......@@ -24,10 +24,13 @@ import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.api.PceService;
import org.slf4j.Logger;
import java.util.List;
/**
* Supports quering PCE path.
*/
......@@ -72,17 +75,28 @@ public class PceQueryPathCommand extends AbstractShellCommand {
* @param tunnel pce tunnel
*/
void display(Tunnel tunnel) {
print("\npath-id : %s \n" +
"source : %s \n" +
"destination : %s \n" +
"path-type : %s \n" +
"symbolic-path-name : %s \n" +
List<ExplicitPathInfo> explicitPathInfoList = AbstractShellCommand.get(PceService.class)
.explicitPathInfoList(tunnel.tunnelName().value());
print("\npath-id : %s \n" +
"source : %s \n" +
"destination : %s \n" +
"path-type : %s \n" +
"symbolic-path-name : %s \n" +
"constraints: \n" +
" cost : %s \n" +
" bandwidth : %s",
" cost : %s \n" +
" bandwidth : %s",
tunnel.tunnelId().id(), tunnel.path().src().deviceId().toString(),
tunnel.path().dst().deviceId().toString(),
tunnel.type().name(), tunnel.tunnelName(), tunnel.annotations().value(COST_TYPE),
tunnel.annotations().value(AnnotationKeys.BANDWIDTH));
if (explicitPathInfoList != null) {
for (ExplicitPathInfo e : explicitPathInfoList) {
print("explicitPathObjects : \n" +
" type : %s \n" +
" value : %s ",
String.valueOf(e.type().type()), e.value().toString());
}
}
}
}
......
......@@ -15,27 +15,35 @@
*/
package org.onosproject.pce.cli;
import static org.onosproject.net.Link.State.ACTIVE;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collection;
import java.util.List;
import java.util.LinkedList;
import com.google.common.collect.Lists;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onlab.util.DataRateUnit;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.PortNumber;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.constraint.CostConstraint;
import org.onosproject.pce.pceservice.LspType;
import org.onosproject.pce.pceservice.api.PceService;
import org.slf4j.Logger;
/**
......@@ -44,6 +52,16 @@ import org.slf4j.Logger;
@Command(scope = "onos", name = "pce-setup-path", description = "Supports creating pce path.")
public class PceSetupPathCommand extends AbstractShellCommand {
private final Logger log = getLogger(getClass());
public static final byte SUBTYPE_DEVICEID = 0;
public static final byte SUBTYPE_LINK = 1;
public static final byte SUBTYPE_INDEX = 1;
public static final byte TYPE_INDEX = 0;
public static final byte DEVICEID_INDEX = 2;
public static final byte SOURCE_DEVICEID_INDEX = 2;
public static final byte SOURCE_PORTNO_INDEX = 3;
public static final byte DESTINATION_DEVICEID_INDEX = 4;
public static final byte DESTINATION_PORTNO_INDEX = 5;
@Argument(index = 0, name = "src", description = "source device.", required = true, multiValued = false)
String src = null;
......@@ -69,6 +87,15 @@ public class PceSetupPathCommand extends AbstractShellCommand {
+ "Data rate unit is in BPS.", required = false, multiValued = false)
double bandwidth = 0.0;
@Option(name = "-e", aliases = "--explicitPathObjects", description = "List of strict and loose hopes",
required = false, multiValued = true)
String[] explicitPathInfoStrings;
//explicitPathInfo format : Type/SubType/Value(DeviceId or Link info)
//If Value is Device : Type/SubType/deviceId
//If Value is Link : Type/SubType/SourceDeviceId/SourcePortNo/DestinationDeviceId/DestinationPortNo
List<ExplicitPathInfo> explicitPathInfo = Lists.newLinkedList();
@Override
protected void execute() {
log.info("executing pce-setup-path");
......@@ -114,7 +141,50 @@ public class PceSetupPathCommand extends AbstractShellCommand {
CostConstraint.Type costType = CostConstraint.Type.values()[cost - 1];
listConstrnt.add(CostConstraint.of(costType));
if (!service.setupPath(srcDevice, dstDevice, name, listConstrnt, lspType)) {
if (explicitPathInfoStrings != null) {
for (String str : explicitPathInfoStrings) {
String[] splitted = str.split("/");
DeviceId deviceId;
NetworkResource res = null;
PortNumber portNo;
int explicitPathType = Integer.parseInt(splitted[TYPE_INDEX]);
if ((explicitPathType < 0) || (explicitPathType > 1)) {
error("Explicit path validation failed");
return;
}
//subtype 0 = deviceId, 1 = link
//subtype is required to store either as deviceId or Link
if (splitted[DEVICEID_INDEX] != null && Integer.parseInt(splitted[SUBTYPE_INDEX]) == SUBTYPE_DEVICEID) {
res = DeviceId.deviceId(splitted[DEVICEID_INDEX]);
} else if (Integer.parseInt(splitted[SUBTYPE_INDEX]) == SUBTYPE_LINK
&& splitted[SOURCE_DEVICEID_INDEX] != null
&& splitted[SOURCE_PORTNO_INDEX] != null
&& splitted[DESTINATION_DEVICEID_INDEX] != null
&& splitted[DESTINATION_PORTNO_INDEX] != null) {
deviceId = DeviceId.deviceId(splitted[SOURCE_DEVICEID_INDEX]);
portNo = PortNumber.portNumber(splitted[SOURCE_PORTNO_INDEX]);
ConnectPoint cpSrc = new ConnectPoint(deviceId, portNo);
deviceId = DeviceId.deviceId(splitted[DESTINATION_DEVICEID_INDEX]);
portNo = PortNumber.portNumber(splitted[DESTINATION_PORTNO_INDEX]);
ConnectPoint cpDst = new ConnectPoint(deviceId, portNo);
res = DefaultLink.builder()
.providerId(ProviderId.NONE)
.src(cpSrc)
.dst(cpDst)
.type(DIRECT)
.state(ACTIVE)
.build();
} else {
error("Explicit path validation failed");
return;
}
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.values()[explicitPathType], res);
explicitPathInfo.add(obj);
}
}
if (!service.setupPath(srcDevice, dstDevice, name, listConstrnt, lspType, explicitPathInfo)) {
error("Path creation failed.");
}
}
......
......@@ -18,14 +18,18 @@ package org.onosproject.pce.pceservice;
import static com.google.common.base.MoreObjects.toStringHelper;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import org.onlab.rest.BaseResource;
import org.onlab.util.DataRateUnit;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.Constraint;
import org.onosproject.pce.pceservice.constraint.CostConstraint;
import org.onosproject.pce.pcestore.api.PceStore;
/**
* Implementation of an entity which provides functionalities of pce path.
......@@ -39,6 +43,7 @@ public final class DefaultPcePath implements PcePath {
private String name; // symbolic-path-name
private Constraint costConstraint; // cost constraint
private Constraint bandwidthConstraint; // bandwidth constraint
private Collection<ExplicitPathInfo> explicitPathInfo; //list of explicit path info
/**
* Initializes PCE path attributes.
......@@ -50,10 +55,11 @@ public final class DefaultPcePath implements PcePath {
* @param name symbolic-path-name
* @param costConstrnt cost constraint
* @param bandwidthConstrnt bandwidth constraint
* @param explicitPathInfo list of explicit path info
*/
private DefaultPcePath(TunnelId id, String src, String dst, LspType lspType,
String name, Constraint costConstrnt, Constraint bandwidthConstrnt) {
String name, Constraint costConstrnt, Constraint bandwidthConstrnt,
Collection<ExplicitPathInfo> explicitPathInfo) {
this.id = id;
this.source = src;
this.destination = dst;
......@@ -61,6 +67,7 @@ public final class DefaultPcePath implements PcePath {
this.name = name;
this.costConstraint = costConstrnt;
this.bandwidthConstraint = bandwidthConstrnt;
this.explicitPathInfo = explicitPathInfo;
}
@Override
......@@ -114,6 +121,11 @@ public final class DefaultPcePath implements PcePath {
}
@Override
public Collection<ExplicitPathInfo> explicitPathInfo() {
return explicitPathInfo;
}
@Override
public PcePath copy(PcePath path) {
if (null != path.source()) {
this.source = path.source();
......@@ -138,7 +150,8 @@ public final class DefaultPcePath implements PcePath {
@Override
public int hashCode() {
return Objects.hash(id, source, destination, lspType, name, costConstraint, bandwidthConstraint);
return Objects.hash(id, source, destination, lspType, name, costConstraint, bandwidthConstraint,
explicitPathInfo);
}
@Override
......@@ -154,7 +167,8 @@ public final class DefaultPcePath implements PcePath {
&& Objects.equals(lspType, that.lspType)
&& Objects.equals(name, that.name)
&& Objects.equals(costConstraint, that.costConstraint)
&& Objects.equals(bandwidthConstraint, that.bandwidthConstraint);
&& Objects.equals(bandwidthConstraint, that.bandwidthConstraint)
&& Objects.equals(explicitPathInfo, that.explicitPathInfo);
}
return false;
}
......@@ -170,6 +184,7 @@ public final class DefaultPcePath implements PcePath {
.add("name", name)
.add("costConstraint", costConstraint)
.add("bandwidthConstraint", bandwidthConstraint)
.add("explicitPathInfo", explicitPathInfo)
.toString();
}
......@@ -185,7 +200,7 @@ public final class DefaultPcePath implements PcePath {
/**
* Builder class for pce path.
*/
public static final class Builder implements PcePath.Builder {
public static final class Builder extends BaseResource implements PcePath.Builder {
private TunnelId id;
private String source;
private String destination;
......@@ -193,6 +208,7 @@ public final class DefaultPcePath implements PcePath {
private String name;
private Constraint costConstraint;
private Constraint bandwidthConstraint;
private Collection<ExplicitPathInfo> explicitPathInfo;
@Override
public Builder id(String id) {
......@@ -240,6 +256,12 @@ public final class DefaultPcePath implements PcePath {
}
@Override
public Builder explicitPathInfo(Collection<ExplicitPathInfo> explicitPathInfo) {
this.explicitPathInfo = explicitPathInfo;
return this;
}
@Override
public Builder of(Tunnel tunnel) {
this.id = TunnelId.valueOf(tunnel.tunnelId().id());
this.source = tunnel.path().src().deviceId().toString();
......@@ -264,13 +286,20 @@ public final class DefaultPcePath implements PcePath {
DataRateUnit.valueOf("BPS"));
}
PceStore pceStore = get(PceStore.class);
List<ExplicitPathInfo> explicitPathInfoList = pceStore
.getTunnelNameExplicitPathInfoMap(tunnel.tunnelName().value());
if (explicitPathInfoList != null) {
this.explicitPathInfo = explicitPathInfoList;
}
return this;
}
@Override
public PcePath build() {
return new DefaultPcePath(id, source, destination, lspType, name,
costConstraint, bandwidthConstraint);
costConstraint, bandwidthConstraint, explicitPathInfo);
}
}
}
......
/*
* 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.NetworkResource;
import com.google.common.annotations.Beta;
import java.util.Objects;
/**
* Representation of explicit path info consists of contraints (strict / loose) to compute path.
*/
@Beta
public final class ExplicitPathInfo {
private final Type type;
//Can be Link or DeviceId
private final NetworkResource value;
public enum Type {
/**
* Signifies that path includes strict node or link.
*/
STRICT(0),
/**
* Signifies that path includes loose node or link.
*/
LOOSE(1);
int value;
/**
* Assign val with the value as the type.
*
* @param val type
*/
Type(int val) {
value = val;
}
/**
* Returns value of type.
*
* @return type
*/
public byte type() {
return (byte) value;
}
}
/**
* Creates instance of explicit path object.
*
* @param type specifies whether strict or loose node/link
* @param value specifies deviceId or link
*/
public ExplicitPathInfo(Type type, NetworkResource value) {
this.type = type;
this.value = value;
}
/**
* Returns explicit path type.
*
* @return explicit path type as strict/loose
*/
public Type type() {
return type;
}
/**
* Returns deviceId or link.
*
* @return deviceId or link
*/
public NetworkResource value() {
return value;
}
@Override
public int hashCode() {
return Objects.hash(type, value);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ExplicitPathInfo) {
final ExplicitPathInfo other = (ExplicitPathInfo) obj;
return Objects.equals(this.type, other.type)
&& Objects.equals(this.value, other.value);
}
return false;
}
}
......@@ -24,6 +24,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -48,9 +49,11 @@ import org.onosproject.mastership.MastershipService;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultAnnotations.Builder;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.Path;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.Constraint;
......@@ -86,6 +89,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import static org.onosproject.incubator.net.tunnel.Tunnel.State.INIT;
import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
......@@ -230,10 +234,177 @@ public class PceManager implements PceService {
return ImmutableSet.of();
}
//[TODO:] handle requests in queue
//Computes the partial path from partial computed path to specified dst.
private List<Path> computePartialPath(List<Path> computedPath, DeviceId src, DeviceId dst,
List<Constraint> constraints) {
int size = computedPath.size();
Path path = null;
DeviceId deviceId = size == 0 ? src :
computedPath.get(size - 1).dst().deviceId();
Set<Path> tempComputePath = computePath(deviceId, dst, constraints);
if (tempComputePath.isEmpty()) {
return null;
}
//if path validation fails return null
//Validate computed path to avoid loop in the path
for (Path p : tempComputePath) {
if (pathValidation(computedPath, p)) {
path = p;
break;
}
}
if (path == null) {
return null;
}
//Store the partial path result in a list
computedPath.add(path);
return computedPath;
}
private List<DeviceId> createListOfDeviceIds(List<? extends NetworkResource> list) {
List<Link> links = new LinkedList<>();
if (!list.isEmpty() && list.iterator().next() instanceof Path) {
for (Path path : (List<Path>) list) {
links.addAll(path.links());
}
} else if (!list.isEmpty() && list.iterator().next() instanceof Link) {
links.addAll((List<Link>) list);
}
//List of devices for new path computed
DeviceId source = null;
DeviceId destination = null;
List<DeviceId> devList = new LinkedList<>();
for (Link l : links) {
if (!devList.contains(l.src().deviceId())) {
devList.add(l.src().deviceId());
}
if (!devList.contains(l.dst().deviceId())) {
devList.add(l.dst().deviceId());
}
}
return devList;
}
//To dectect loops in the path i.e if the partial paths has intersection node avoid it.
private boolean pathValidation(List<Path> partialPath, Path path) {
//List of devices in new path computed
List<DeviceId> newPartialPathDevList;
newPartialPathDevList = createListOfDeviceIds(path.links());
//List of devices in partial computed path
List<DeviceId> partialComputedPathDevList;
partialComputedPathDevList = createListOfDeviceIds(partialPath);
for (DeviceId deviceId : newPartialPathDevList) {
for (DeviceId devId : partialComputedPathDevList) {
if (!newPartialPathDevList.get(0).equals(deviceId) &&
!partialComputedPathDevList.get(partialComputedPathDevList.size() - 1).equals(devId)
&& deviceId.equals(devId)) {
return false;
}
}
}
return true;
}
//Returns final computed explicit path (list of partial computed paths).
private List<Path> computeExplicitPath(List<ExplicitPathInfo> explicitPathInfo, DeviceId src, DeviceId dst,
List<Constraint> constraints) {
List<Path> finalComputedPath = new LinkedList<>();
for (ExplicitPathInfo info : explicitPathInfo) {
/*
* If explicit path object is LOOSE,
* 1) If specified as DeviceId (node) :
* If it is source , compute from source to destination (partial computation not required),
* otherwise compute from specified source to specified device
* 2) If specified as Link :
* Compute partial path from source to link's source , if path exists compute from link's source to dst
*/
if (info.type().equals(ExplicitPathInfo.Type.LOOSE)) {
if (info.value() instanceof DeviceId) {
// If deviceId is source no need to compute
if (!(info.value()).equals(src)) {
finalComputedPath = computePartialPath(finalComputedPath, src, (DeviceId) info.value(),
constraints);
}
} else if (info.value() instanceof Link) {
if ((((Link) info.value()).src().deviceId().equals(src))
|| (!finalComputedPath.isEmpty()
&& finalComputedPath.get(finalComputedPath.size() - 1).dst().equals(
((Link) info.value()).src().deviceId()))) {
finalComputedPath = computePartialPath(finalComputedPath, src, ((Link) info.value()).dst()
.deviceId(), constraints);
} else {
finalComputedPath = computePartialPath(finalComputedPath, src, ((Link) info.value()).src()
.deviceId(), constraints) != null ? computePartialPath(finalComputedPath, src,
((Link) info.value()).dst().deviceId(), constraints) : null;
}
}
/*
* If explicit path object is STRICT,
* 1) If specified as DeviceId (node) :
* Check whether partial computed path has reachable to strict specified node or
* strict node is the source, if no set path as null else do nothing
* 2) If specified as Link :
* Check whether partial computed path has reachable to strict link's src, if yes compute
* path from strict link's src to link's dst (to include specified link)
*/
} else if (info.type().equals(ExplicitPathInfo.Type.STRICT)) {
if (info.value() instanceof DeviceId) {
if (!(!finalComputedPath.isEmpty() && finalComputedPath.get(finalComputedPath.size() - 1).dst()
.deviceId().equals(info.value()))
&& !info.value().equals(src)) {
finalComputedPath = null;
}
} else if (info.value() instanceof Link) {
finalComputedPath = ((Link) info.value()).src().deviceId().equals(src)
|| !finalComputedPath.isEmpty()
&& finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId()
.equals(((Link) info.value()).src().deviceId()) ? computePartialPath(
finalComputedPath, src, ((Link) info.value()).dst().deviceId(), constraints) : null;
}
}
if (finalComputedPath == null) {
return null;
}
}
// Destination is not reached in Partial computed path then compute till destination
if (finalComputedPath.isEmpty() || !finalComputedPath.isEmpty()
&& !finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId().equals(dst)) {
finalComputedPath = computePartialPath(finalComputedPath, src, dst, constraints);
if (finalComputedPath == null) {
return null;
}
}
return finalComputedPath;
}
@Override
public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
LspType lspType) {
return setupPath(src, dst, tunnelName, constraints, lspType, null);
}
//[TODO:] handle requests in queue
@Override
public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
LspType lspType, List<ExplicitPathInfo> explicitPathInfo) {
checkNotNull(src);
checkNotNull(dst);
checkNotNull(tunnelName);
......@@ -245,7 +416,7 @@ public class PceManager implements PceService {
if (srcDevice == null || dstDevice == null) {
// Device is not known.
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
return false;
}
......@@ -255,7 +426,7 @@ public class PceManager implements PceService {
if (srcLsrId == null || dstLsrId == null) {
// LSR id is not known.
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
return false;
}
......@@ -263,7 +434,7 @@ public class PceManager implements PceService {
DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(srcLsrId), DeviceCapability.class);
if (cfg == null) {
log.debug("No session to ingress.");
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
return false;
}
......@@ -299,12 +470,30 @@ public class PceManager implements PceService {
constraints = new LinkedList<>();
constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
}
Set<Path> computedPathSet = Sets.newLinkedHashSet();
if (explicitPathInfo != null && !explicitPathInfo.isEmpty()) {
List<Path> finalComputedPath = computeExplicitPath(explicitPathInfo, src, dst, constraints);
if (finalComputedPath == null) {
return false;
}
Set<Path> computedPathSet = computePath(src, dst, constraints);
pceStore.tunnelNameExplicitPathInfoMap(tunnelName, explicitPathInfo);
List<Link> links = new LinkedList<>();
double totalCost = 0;
// Add all partial computed paths
for (Path path : finalComputedPath) {
links.addAll(path.links());
totalCost = totalCost + path.cost();
}
computedPathSet.add(new DefaultPath(finalComputedPath.iterator().next().providerId(), links, totalCost));
} else {
computedPathSet = computePath(src, dst, constraints);
}
// NO-PATH
if (computedPathSet.isEmpty()) {
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
return false;
}
......@@ -339,14 +528,15 @@ public class PceManager implements PceService {
if (bwConstraintValue != 0) {
consumerId = reserveBandwidth(computedPath, bwConstraintValue, null);
if (consumerId == null) {
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints,
lspType, explicitPathInfo));
return false;
}
}
TunnelId tunnelId = tunnelService.setupTunnel(appId, src, tunnel, computedPath);
if (tunnelId == null) {
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType));
pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo));
if (consumerId != null) {
resourceService.release(consumerId);
}
......@@ -363,7 +553,7 @@ public class PceManager implements PceService {
@Override
public boolean updatePath(TunnelId tunnelId, List<Constraint> constraints) {
checkNotNull(tunnelId);
Set<Path> computedPathSet = null;
Set<Path> computedPathSet = Sets.newLinkedHashSet();
Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
if (tunnel == null) {
......@@ -441,8 +631,30 @@ public class PceManager implements PceService {
constraints.add(costConstraint);
}
computedPathSet = computePath(links.get(0).src().deviceId(), links.get(links.size() - 1).dst().deviceId(),
constraints);
List<ExplicitPathInfo> explicitPathInfo = pceStore
.getTunnelNameExplicitPathInfoMap(tunnel.tunnelName().value());
if (explicitPathInfo != null) {
List<Path> finalComputedPath = computeExplicitPath(explicitPathInfo,
tunnel.path().src().deviceId(), tunnel.path().dst().deviceId(),
constraints);
if (finalComputedPath == null) {
return false;
}
List<Link> totalLinks = new LinkedList<>();
double totalCost = 0;
//Add all partial computed paths
for (Path path : finalComputedPath) {
totalLinks.addAll(path.links());
totalCost = totalCost + path.cost();
}
computedPathSet.add(new DefaultPath(finalComputedPath.iterator().next().providerId(),
totalLinks, totalCost));
} else {
computedPathSet = computePath(tunnel.path().src().deviceId(), tunnel.path().dst().deviceId(),
constraints);
}
// NO-PATH
if (computedPathSet.isEmpty()) {
......@@ -636,7 +848,8 @@ public class PceManager implements PceService {
// then PCInitiate (Remove)
pceStore.addFailedPathInfo(new PcePathInfo(tunnel.path().src().deviceId(), tunnel
.path().dst().deviceId(), tunnel.tunnelName().value(), constraintList,
LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))));
LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE)),
pceStore.getTunnelNameExplicitPathInfoMap(tunnel.tunnelName().value())));
//Release that tunnel calling PCInitiate
releasePath(tunnel.tunnelId());
}
......@@ -832,7 +1045,9 @@ public class PceManager implements PceService {
List<Link> links = tunnel.path().links();
pceStore.addFailedPathInfo(new PcePathInfo(links.get(0).src().deviceId(),
links.get(links.size() - 1).dst().deviceId(),
tunnel.tunnelName().value(), constraints, lspType));
tunnel.tunnelName().value(), constraints, lspType,
pceStore.getTunnelNameExplicitPathInfoMap(tunnel
.tunnelName().value())));
}
break;
......@@ -861,6 +1076,11 @@ public class PceManager implements PceService {
}
}
@Override
public List<ExplicitPathInfo> explicitPathInfoList(String tunnelName) {
return pceStore.getTunnelNameExplicitPathInfoMap(tunnelName);
}
//Computes path from tunnel store and also path failed to setup.
private void callForOptimization() {
//Recompute the LSPs which it was delegated [LSPs stored in PCE store (failed paths)]
......@@ -880,7 +1100,7 @@ public class PceManager implements PceService {
*/
if (mastershipService.isLocalMaster(failedPathInfo.src())) {
if (setupPath(failedPathInfo.src(), failedPathInfo.dst(), failedPathInfo.name(),
failedPathInfo.constraints(), failedPathInfo.lspType())) {
failedPathInfo.constraints(), failedPathInfo.lspType(), failedPathInfo.explicitPathInfo())) {
// If computation is success remove that path
pceStore.removeFailedPathInfo(failedPathInfo);
return true;
......
......@@ -19,7 +19,8 @@ package org.onosproject.pce.pceservice;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.net.intent.Constraint;
import org.onosproject.pce.pceservice.DefaultPcePath.Builder;
import java.util.Collection;
/**
* Abstraction of an entity which provides functionalities of pce path.
......@@ -97,6 +98,13 @@ public interface PcePath {
Constraint bandwidthConstraint();
/**
* Returns the list of explicit path objects.
*
* @return list of explicit path objects
*/
Collection<ExplicitPathInfo> explicitPathInfo();
/**
* Copies only non-null or non-zero member variables.
*
* @param id path-id
......@@ -174,6 +182,14 @@ public interface PcePath {
Builder of(Tunnel tunnel);
/**
* Returns the builder object of ExplicitPathInfo.
*
* @param explicitPathInfo list of explicit path obj
* @return builder object of ExplicitPathInfo
*/
Builder explicitPathInfo(Collection<ExplicitPathInfo> explicitPathInfo);
/**
* Builds object of pce path.
*
* @return object of pce path.
......
......@@ -19,6 +19,7 @@ import java.util.List;
import org.onosproject.net.DeviceId;
import org.onosproject.net.intent.Constraint;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.LspType;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelId;
......@@ -42,6 +43,20 @@ public interface PceService {
boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints, LspType lspType);
/**
* Creates new path based on constraints and LSP type.
*
* @param src source device
* @param dst destination device
* @param tunnelName name of the tunnel
* @param constraints list of constraints to be applied on path
* @param lspType type of path to be setup
* @param explicitPathInfo list of explicit path info
* @return false on failure and true on successful path creation
*/
boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints, LspType lspType,
List<ExplicitPathInfo> explicitPathInfo);
/**
* Updates an existing path.
*
* @param tunnelId tunnel identifier
......@@ -72,4 +87,12 @@ public interface PceService {
* @return tunnel if path exists, otherwise null
*/
Tunnel queryPath(TunnelId tunnelId);
/**
* Returns list of explicit path info.
*
* @param tunnelName tunnel name
* @return list of explicit path info
*/
List<ExplicitPathInfo> explicitPathInfoList(String tunnelName);
}
\ No newline at end of file
......
......@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
......@@ -33,6 +34,7 @@ import org.onlab.util.KryoNamespace;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.resource.ResourceConsumer;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
import org.onosproject.pce.pceservice.constraint.CostConstraint;
import org.onosproject.pce.pceservice.TunnelConsumerId;
......@@ -69,6 +71,9 @@ public class DistributedPceStore implements PceStore {
// List of Failed path info
private DistributedSet<PcePathInfo> failedPathSet;
// Maintains tunnel name mapped to explicit path info
private ConsistentMap<String, List<ExplicitPathInfo>> tunnelNameExplicitPathInfoMap;
private static final Serializer SERIALIZER = Serializer
.using(new KryoNamespace.Builder().register(KryoNamespaces.API)
.register(PcePathInfo.class)
......@@ -99,6 +104,16 @@ public class DistributedPceStore implements PceStore {
.build()
.asDistributedSet();
tunnelNameExplicitPathInfoMap = storageService.<String, List<ExplicitPathInfo>>consistentMapBuilder()
.withName("onos-pce-explicitpathinfo")
.withSerializer(Serializer.using(
new KryoNamespace.Builder()
.register(KryoNamespaces.API)
.register(ExplicitPathInfo.class)
.register(ExplicitPathInfo.Type.class)
.build()))
.build();
log.info("Started");
}
......@@ -181,4 +196,18 @@ public class DistributedPceStore implements PceStore {
}
return true;
}
@Override
public boolean tunnelNameExplicitPathInfoMap(String tunnelName, List<ExplicitPathInfo> explicitPathInfo) {
checkNotNull(tunnelName);
checkNotNull(explicitPathInfo);
return tunnelNameExplicitPathInfoMap.put(tunnelName, explicitPathInfo) != null ? true : false;
}
@Override
public List<ExplicitPathInfo> getTunnelNameExplicitPathInfoMap(String tunnelName) {
checkNotNull(tunnelName);
return tunnelNameExplicitPathInfoMap.get(tunnelName).value();
}
}
......
......@@ -22,6 +22,7 @@ import java.util.Objects;
import org.onosproject.net.DeviceId;
import org.onosproject.net.intent.Constraint;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.LspType;
/**
......@@ -40,6 +41,8 @@ public final class PcePathInfo {
private LspType lspType; // lsp type
private List<ExplicitPathInfo> explicitPathInfo; //Explicit path info to compute explicit path
/**
* Initialization of member variables.
*
......@@ -48,17 +51,20 @@ public final class PcePathInfo {
* @param name tunnel name
* @param constraints list of constraints
* @param lspType lsp type
* @param explicitPathInfo explicit path info
*/
public PcePathInfo(DeviceId src,
DeviceId dst,
String name,
List<Constraint> constraints,
LspType lspType) {
LspType lspType,
List<ExplicitPathInfo> explicitPathInfo) {
this.src = src;
this.dst = dst;
this.name = name;
this.constraints = constraints;
this.lspType = lspType;
this.explicitPathInfo = explicitPathInfo;
}
/**
......@@ -70,6 +76,7 @@ public final class PcePathInfo {
this.name = null;
this.constraints = null;
this.lspType = null;
this.explicitPathInfo = null;
}
/**
......@@ -162,9 +169,27 @@ public final class PcePathInfo {
this.lspType = lspType;
}
/**
* Returns list of explicit path info.
*
* @return list of explicit path info
*/
public List<ExplicitPathInfo> explicitPathInfo() {
return explicitPathInfo;
}
/**
* Sets list of explicit path info.
*
* @param explicitPathInfo list of explicit path info
*/
public void explicitPathInfo(List<ExplicitPathInfo> explicitPathInfo) {
this.explicitPathInfo = explicitPathInfo;
}
@Override
public int hashCode() {
return Objects.hash(src, dst, name, constraints, lspType);
return Objects.hash(src, dst, name, constraints, lspType, explicitPathInfo);
}
@Override
......@@ -178,7 +203,8 @@ public final class PcePathInfo {
Objects.equals(this.dst, other.dst) &&
Objects.equals(this.name, other.name) &&
Objects.equals(this.constraints, other.constraints) &&
Objects.equals(this.lspType, other.lspType);
Objects.equals(this.lspType, other.lspType) &&
Objects.equals(this.explicitPathInfo, other.explicitPathInfo);
}
return false;
}
......@@ -187,11 +213,12 @@ public final class PcePathInfo {
public String toString() {
return MoreObjects.toStringHelper(getClass())
.omitNullValues()
.add("Source", src.toString())
.add("Destination", dst.toString())
.add("Name", name.toString())
.add("Constraints", constraints.toString())
.add("LspType", lspType.toString())
.add("Source", src)
.add("Destination", dst)
.add("Name", name)
.add("Constraints", constraints)
.add("explicitPathInfo", explicitPathInfo)
.add("LspType", lspType)
.toString();
}
}
......
......@@ -15,8 +15,11 @@
*/
package org.onosproject.pce.pcestore.api;
import java.util.List;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.net.resource.ResourceConsumer;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pcestore.PcePathInfo;
import java.util.Map;
......@@ -107,4 +110,21 @@ public interface PceStore {
* @return success or failure
*/
boolean removeFailedPathInfo(PcePathInfo failedPathInfo);
/**
* Adds explicit path info to the map with corresponding tunnel name.
*
* @param tunnelName tunnel name as key
* @param explicitPathInfo list of explicit path objects
* @return whether it is added to map
*/
boolean tunnelNameExplicitPathInfoMap(String tunnelName, List<ExplicitPathInfo> explicitPathInfo);
/**
* Gets explicit path info based on tunnel name.
*
* @param tunnelName tunnel name as key
* @return list of explicit path info
*/
List<ExplicitPathInfo> getTunnelNameExplicitPathInfoMap(String tunnelName);
}
......
......@@ -16,21 +16,47 @@
package org.onosproject.pce.pceservice;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.onosproject.pce.pceservice.PathComputationTest.D2;
import static org.easymock.EasyMock.createMock;
import com.google.common.testing.EqualsTester;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.rest.BaseResource;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.pce.pceservice.constraint.CostConstraint;
import org.onosproject.pce.pcestore.api.PceStore;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import java.util.List;
/**
* Unit tests for DefaultPcePath class.
*/
public class DefaultPcePathTest {
private PceStore pceStore = createMock(PceStore.class);
@Before
public void setup() {
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(PceStore.class, pceStore);
BaseResource.setServiceDirectory(testDirectory);
}
@After
public void tearDownTest() {
}
/**
* Checks the operation of equals() methods.
*/
......@@ -43,7 +69,9 @@ public class DefaultPcePathTest {
final String dst1 = "bee";
final String type1 = "1";
final String name1 = "pcc";
final List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
explicitPathInfoList.add(obj);
PcePath path1 = DefaultPcePath.builder()
.source(src1)
.destination(dst1)
......@@ -51,6 +79,7 @@ public class DefaultPcePathTest {
.name(name1)
.costConstraint(cost1)
.bandwidthConstraint(bandwidth1)
.explicitPathInfo(explicitPathInfoList)
.build();
path1.id(TunnelId.valueOf("1"));
......@@ -62,6 +91,7 @@ public class DefaultPcePathTest {
.name(name1)
.costConstraint(cost1)
.bandwidthConstraint(bandwidth1)
.explicitPathInfo(explicitPathInfoList)
.build();
samePath1.id(TunnelId.valueOf("1"));
......@@ -80,6 +110,7 @@ public class DefaultPcePathTest {
.name(name2)
.costConstraint(cost2)
.bandwidthConstraint(bandwidth2)
.explicitPathInfo(explicitPathInfoList)
.build();
path2.id(TunnelId.valueOf("2"));
......@@ -97,7 +128,9 @@ public class DefaultPcePathTest {
final String dst = "deccan";
final String type = "2";
final String name = "pcc4";
final List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
explicitPathInfoList.add(obj);
PcePath path = DefaultPcePath.builder()
.source(src)
.destination(dst)
......@@ -105,6 +138,7 @@ public class DefaultPcePathTest {
.name(name)
.costConstraint(cost)
.bandwidthConstraint(bandwidth)
.explicitPathInfo(explicitPathInfoList)
.build();
assertThat(path.source(), is(src));
......
......@@ -14,10 +14,12 @@ import static org.onosproject.pce.pceservice.PathComputationTest.D1;
import static org.onosproject.pce.pceservice.PathComputationTest.D2;
import static org.onosproject.pce.pceservice.PathComputationTest.D3;
import static org.onosproject.pce.pceservice.PathComputationTest.D4;
import static org.onosproject.pce.pceservice.PathComputationTest.D5;
import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE1;
import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE2;
import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE3;
import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE4;
import static org.onosproject.pce.pceservice.PathComputationTest.DEVICE5;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LOCAL_LSP_ID;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PLSP_ID;
import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.COST;
......@@ -32,6 +34,8 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
......@@ -120,9 +124,9 @@ public class PceManagerTest {
private static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
private TopologyGraph graph = null;
private Device deviceD1, deviceD2, deviceD3, deviceD4;
private Device deviceD1, deviceD2, deviceD3, deviceD4, deviceD5;
private Device pcepDeviceD1, pcepDeviceD2, pcepDeviceD3, pcepDeviceD4;
private Link link1, link2, link3, link4;
private Link link1, link2, link3, link4, link5, link6;
protected static int flowsDownloaded;
private TunnelListener tunnelListener;
private TopologyListener listener;
......@@ -164,12 +168,15 @@ public class PceManagerTest {
link2 = PathComputationTest.addLink(DEVICE2, 30, DEVICE4, 40, setCost, 20);
link3 = PathComputationTest.addLink(DEVICE1, 80, DEVICE3, 70, setCost, 100);
link4 = PathComputationTest.addLink(DEVICE3, 60, DEVICE4, 50, setCost, 80);
link5 = PathComputationTest.addLink(DEVICE2, 60, DEVICE5, 50, setCost, 80);
link6 = PathComputationTest.addLink(DEVICE4, 60, DEVICE5, 50, setCost, 80);
Set<TopologyVertex> vertexes = new HashSet<TopologyVertex>();
vertexes.add(D1);
vertexes.add(D2);
vertexes.add(D3);
vertexes.add(D4);
vertexes.add(D5);
this.vertexes = vertexes;
......@@ -186,6 +193,12 @@ public class PceManagerTest {
TopologyEdge edge4 = new DefaultTopologyEdge(D3, D4, link4);
edges.add(edge4);
TopologyEdge edge5 = new DefaultTopologyEdge(D2, D5, link5);
edges.add(edge5);
TopologyEdge edge6 = new DefaultTopologyEdge(D4, D5, link6);
edges.add(edge6);
this.edges = edges;
graph = new DefaultTopologyGraph(vertexes, edges);
......@@ -194,6 +207,7 @@ public class PceManagerTest {
DefaultAnnotations.Builder builderDev2 = DefaultAnnotations.builder();
DefaultAnnotations.Builder builderDev3 = DefaultAnnotations.builder();
DefaultAnnotations.Builder builderDev4 = DefaultAnnotations.builder();
DefaultAnnotations.Builder builderDev5 = DefaultAnnotations.builder();
// Making L3 devices
builderDev1.set(AnnotationKeys.TYPE, L3);
......@@ -208,15 +222,20 @@ public class PceManagerTest {
builderDev4.set(AnnotationKeys.TYPE, L3);
builderDev4.set(LSRID, "4.4.4.4");
builderDev5.set(AnnotationKeys.TYPE, L3);
builderDev5.set(LSRID, "5.5.5.5");
deviceD1 = new MockDevice(D1.deviceId(), builderDev1.build());
deviceD2 = new MockDevice(D2.deviceId(), builderDev2.build());
deviceD3 = new MockDevice(D3.deviceId(), builderDev3.build());
deviceD4 = new MockDevice(D4.deviceId(), builderDev4.build());
deviceD5 = new MockDevice(D5.deviceId(), builderDev5.build());
deviceService.addDevice(deviceD1);
deviceService.addDevice(deviceD2);
deviceService.addDevice(deviceD3);
deviceService.addDevice(deviceD4);
deviceService.addDevice(deviceD5);
DeviceCapability device1Cap = netConfigRegistry.addConfig(DeviceId.deviceId("1.1.1.1"), DeviceCapability.class);
device1Cap.setLabelStackCap(setLabelStackCap)
......@@ -242,17 +261,25 @@ public class PceManagerTest {
.setSrCap(setSrCap)
.apply();
DeviceCapability device5Cap = netConfigRegistry.addConfig(DeviceId.deviceId("5.5.5.5"), DeviceCapability.class);
device4Cap.setLabelStackCap(setLabelStackCap)
.setLocalLabelCap(setPceccCap)
.setSrCap(setSrCap)
.apply();
if (bandwidth != 0) {
List<Resource> resources = new LinkedList<>();
resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(bandwidth));
resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(bandwidth));
resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(bandwidth));
resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(bandwidth));
resources.add(continuous(link5.src().deviceId(), link5.src().port(), Bandwidth.class).resource(bandwidth));
resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(bandwidth));
resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(bandwidth));
resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(bandwidth));
resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(bandwidth));
resources.add(continuous(link5.dst().deviceId(), link5.dst().port(), Bandwidth.class).resource(bandwidth));
resourceService.allocate(IntentId.valueOf(bandwidth), resources);
}
......@@ -268,7 +295,7 @@ public class PceManagerTest {
CostConstraint costConstraint = new CostConstraint(COST);
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
}
......@@ -282,7 +309,7 @@ public class PceManagerTest {
CostConstraint costConstraint = new CostConstraint(COST);
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
assertThat(result, is(false));
}
......@@ -297,7 +324,7 @@ public class PceManagerTest {
CostConstraint costConstraint = new CostConstraint(TE_COST);
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
}
......@@ -312,7 +339,7 @@ public class PceManagerTest {
CostConstraint costConstraint = new CostConstraint(TE_COST);
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
assertThat(result, is(false));
}
......@@ -328,7 +355,7 @@ public class PceManagerTest {
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
WITHOUT_SIGNALLING_AND_WITHOUT_SR);
WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
assertThat(result, is(true));
}
......@@ -344,7 +371,7 @@ public class PceManagerTest {
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
WITHOUT_SIGNALLING_AND_WITHOUT_SR);
WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
assertThat(result, is(true));
}
......@@ -360,7 +387,7 @@ public class PceManagerTest {
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
WITHOUT_SIGNALLING_AND_WITHOUT_SR);
WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
assertThat(result, is(false));
}
......@@ -377,7 +404,8 @@ public class PceManagerTest {
constraints.add(costConstraint);
constraints.add(bwConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
WITH_SIGNALLING, null);
assertThat(result, is(false));
}
......@@ -394,7 +422,8 @@ public class PceManagerTest {
constraints.add(costConstraint);
constraints.add(bwConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(false));
}
......@@ -408,7 +437,8 @@ public class PceManagerTest {
CostConstraint costConstraint = new CostConstraint(TE_COST);
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
SR_WITHOUT_SIGNALLING, null);
assertThat(result, is(false));
}
......@@ -425,7 +455,8 @@ public class PceManagerTest {
constraints.add(costConstraint);
constraints.add(bwConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
constraints, SR_WITHOUT_SIGNALLING, null);
assertThat(result, is(true));
}
......@@ -436,11 +467,144 @@ public class PceManagerTest {
public void setupPathTest13() {
build4RouterTopo(false, false, false, false, 0);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", null, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", null, WITH_SIGNALLING, null);
assertThat(result, is(true));
}
/**
* Tests path setup with explicit path with loose node D2.
*/
@Test
public void setupPathTest14() {
build4RouterTopo(false, false, false, false, 0);
List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
explicitPathInfoList.add(obj);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", null, WITH_SIGNALLING,
explicitPathInfoList);
Tunnel tunnel = pceManager.queryAllPath().iterator().next();
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link2);
assertThat(result, is(true));
assertThat(tunnel.path().links().equals(links), is(true));
}
/**
* Tests path setup with explicit path with loose node D3.
*/
@Test
public void setupPathTest15() {
build4RouterTopo(false, false, false, false, 0);
List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D3.deviceId());
explicitPathInfoList.add(obj);
boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
explicitPathInfoList);
Tunnel tunnel = pceManager.queryAllPath().iterator().next();
List<Link> links = new LinkedList<>();
links.add(link3);
links.add(link4);
links.add(link6);
assertThat(result, is(true));
assertThat(tunnel.path().links().equals(links), is(true));
}
/**
* Tests path setup with explicit path with loose node D4 , D3 - path fails.
*/
@Test
public void setupPathTest16() {
build4RouterTopo(false, false, false, false, 0);
List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D4.deviceId());
explicitPathInfoList.add(obj);
obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D3.deviceId());
explicitPathInfoList.add(obj);
boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
explicitPathInfoList);
assertThat(result, is(false));
}
/**
* Tests path setup with explicit path with strict node D2 - without reacble to src - path fails.
*/
@Test
public void setupPathTest17() {
build4RouterTopo(false, false, false, false, 0);
List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
explicitPathInfoList.add(obj);
boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
explicitPathInfoList);
assertThat(result, is(false));
}
/**
* Tests path setup with explicit path with loose node D2, strict D2.
*/
@Test
public void setupPathTest18() {
build4RouterTopo(false, false, false, false, 0);
List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
explicitPathInfoList.add(obj);
obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
explicitPathInfoList.add(obj);
boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
explicitPathInfoList);
Tunnel tunnel = pceManager.queryAllPath().iterator().next();
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link5);
assertThat(result, is(true));
assertThat(tunnel.path().links().equals(links), is(true));
}
/**
* Tests path setup with explicit path with loose D1-D2, strict D2.
*/
@Test
public void setupPathTest19() {
build4RouterTopo(false, false, false, false, 0);
List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
explicitPathInfoList.add(obj);
obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
explicitPathInfoList.add(obj);
boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
explicitPathInfoList);
Tunnel tunnel = pceManager.queryAllPath().iterator().next();
List<Link> links = new LinkedList<>();
links.add(link1);
links.add(link5);
assertThat(result, is(true));
assertThat(tunnel.path().links().equals(links), is(true));
}
/**
* Tests path update with increase in bandwidth.
*/
@Test
......@@ -454,7 +618,8 @@ public class PceManagerTest {
CostConstraint costConstraint = new CostConstraint(TE_COST);
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
// Change constraint and update it.
......@@ -492,7 +657,8 @@ public class PceManagerTest {
CostConstraint costConstraint = new CostConstraint(TE_COST);
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, SR_WITHOUT_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
constraints, SR_WITHOUT_SIGNALLING, null);
assertThat(result, is(true));
// Change constraint and update it.
......@@ -523,7 +689,8 @@ public class PceManagerTest {
List<Constraint> constraints = new LinkedList<Constraint>();
CostConstraint costConstraint = new CostConstraint(TE_COST);
constraints.add(costConstraint);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
......@@ -539,6 +706,51 @@ public class PceManagerTest {
}
/**
* Tests path update without cost/bandwidth constraints and with explicit path object.
*/
@Test
public void updatePathTest4() {
build4RouterTopo(false, true, true, true, 100);
// Setup tunnel.
List<Constraint> constraints = new LinkedList<>();
BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(60.0));
constraints.add(bwConstraint);
CostConstraint costConstraint = new CostConstraint(TE_COST);
constraints.add(costConstraint);
List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
explicitPathInfoList.add(obj);
obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
explicitPathInfoList.add(obj);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, explicitPathInfoList);
assertThat(result, is(true));
// Change constraint and update it.
constraints = new LinkedList<>();
bwConstraint = new BandwidthConstraint(Bandwidth.bps(50.0));
constraints.add(bwConstraint);
constraints.add(costConstraint);
Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
assertThat(tunnels.size(), is(1));
Tunnel tunnel = tunnels.iterator().next();
// Stimulate the effect of LSP ids from protocol msg.
tunnelService.updateTunnelWithLspIds(tunnel, "123", "1", State.ACTIVE);
result = pceManager.updatePath(tunnel.tunnelId(), constraints);
assertThat(result, is(true));
tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
assertThat(tunnels.size(), is(2));
}
/**
* Tests path release.
*/
@Test
......@@ -550,7 +762,13 @@ public class PceManagerTest {
constraints.add(bwConst);
constraints.add(costConstraint);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
explicitPathInfoList.add(obj);
obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
explicitPathInfoList.add(obj);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, explicitPathInfoList);
Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
assertThat(tunnels.size(), is(1));
......@@ -573,7 +791,7 @@ public class PceManagerTest {
CostConstraint costConstraint = new CostConstraint(TE_COST);
constraints.add(costConstraint);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
assertThat(tunnels.size(), is(1));
......@@ -587,6 +805,31 @@ public class PceManagerTest {
}
/**
* Tests path release failure.
*/
@Test
public void releasePathTest3() {
build4RouterTopo(false, false, false, false, 5);
List<Constraint> constraints = new LinkedList<Constraint>();
CostConstraint costConstraint = new CostConstraint(TE_COST);
BandwidthConstraint bwConst = new BandwidthConstraint(Bandwidth.bps(3));
constraints.add(bwConst);
constraints.add(costConstraint);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
assertThat(tunnels.size(), is(1));
boolean result;
for (Tunnel tunnel : tunnels) {
result = pceManager.releasePath(tunnel.tunnelId());
assertThat(result, is(true));
}
tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
assertThat(tunnels.size(), is(0));
}
/**
* Tests tunnel events added and removed.
*/
@Test
......@@ -599,7 +842,7 @@ public class PceManagerTest {
constraints.add(costConstraint);
constraints.add(bwConstraint);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T1", constraints, SR_WITHOUT_SIGNALLING);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T1", constraints, SR_WITHOUT_SIGNALLING, null);
assertThat(pceStore.getTunnelInfoCount(), is(1));
Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
......@@ -630,7 +873,8 @@ public class PceManagerTest {
constraints.add(costConstraint);
constraints.add(bwConstraint);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints,
WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
assertThat(pceStore.getTunnelInfoCount(), is(1));
TunnelEvent event;
......@@ -670,7 +914,8 @@ public class PceManagerTest {
constraints.add(costConstraint);
constraints.add(bwConstraint);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR);
pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T2", constraints,
WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
assertThat(pceStore.getTunnelInfoCount(), is(1));
assertThat(pceStore.getFailedPathInfoCount(), is(0));
......@@ -708,7 +953,8 @@ public class PceManagerTest {
constraints.add(localBwConst);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
assertThat(pceStore.getTunnelInfoCount(), is(1));
assertThat(pceStore.getFailedPathInfoCount(), is(0));
......@@ -750,7 +996,8 @@ public class PceManagerTest {
constraints.add(localBwConst);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
List<Event> reasons = new LinkedList<>();
......@@ -788,7 +1035,8 @@ public class PceManagerTest {
constraints.add(localBwConst);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
List<Event> reasons = new LinkedList<>();
......@@ -831,7 +1079,8 @@ public class PceManagerTest {
constraints.add(localBwConst);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
List<Event> reasons = new LinkedList<>();
......@@ -869,7 +1118,8 @@ public class PceManagerTest {
constraints.add(localBwConst);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
List<Event> reasons = new LinkedList<>();
......@@ -917,7 +1167,8 @@ public class PceManagerTest {
constraints.add(localBwConst);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
List<Event> reasons = new LinkedList<>();
......@@ -958,7 +1209,8 @@ public class PceManagerTest {
constraints.add(localBwConst);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
List<Event> reasons = new LinkedList<>();
......@@ -999,7 +1251,8 @@ public class PceManagerTest {
constraints.add(localBwConst);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
List<Event> reasons = new LinkedList<>();
......@@ -1045,7 +1298,8 @@ public class PceManagerTest {
constraints.add(localBwConst);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", constraints, WITH_SIGNALLING);
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, null);
assertThat(result, is(true));
List<Event> reasons = new LinkedList<>();
......@@ -1077,6 +1331,54 @@ public class PceManagerTest {
assertThat(pathService.paths().iterator().next().cost(), is((double) 180));
}
/**
* Tests resilency when link2 availability is changed.
*/
@Test
public void resilencyTest12() {
build4RouterTopo(true, false, false, false, 10);
List<Constraint> constraints = new LinkedList<Constraint>();
CostConstraint costConstraint = new CostConstraint(COST);
constraints.add(costConstraint);
BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
constraints.add(localBwConst);
List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
explicitPathInfoList.add(obj);
obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
explicitPathInfoList.add(obj);
//Setup the path , tunnel created
boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
constraints, WITH_SIGNALLING, explicitPathInfoList);
assertThat(result, is(true));
assertThat(pceStore.getTunnelInfoCount(), is(1));
assertThat(pceStore.getFailedPathInfoCount(), is(0));
List<Event> reasons = new LinkedList<>();
final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link2);
reasons.add(linkEvent);
final TopologyEvent event = new TopologyEvent(
TopologyEvent.Type.TOPOLOGY_CHANGED,
topology,
reasons);
//Change Topology : remove link2
Set<TopologyEdge> tempEdges = new HashSet<>();
tempEdges.add(new DefaultTopologyEdge(D2, D4, link2));
topologyService.changeInTopology(getGraph(null, tempEdges));
listener.event(event);
List<Link> links = new LinkedList<>();
links.add(link3);
links.add(link4);
//Path fails - no alternate path
assertThat(pathService.paths().iterator().hasNext(), is(false));
}
@After
public void tearDown() {
pceManager.deactivate();
......
......@@ -120,7 +120,7 @@ public class DistributedPceStoreTest {
Constraint bandwidth1 = BandwidthConstraint.of(200, DataRateUnit.BPS);
constraints1.add(bandwidth1);
failedPathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1);
failedPathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1, null);
// Creates failedPathInfo2
DeviceId src2 = DeviceId.deviceId("foo2");
......@@ -131,7 +131,7 @@ public class DistributedPceStoreTest {
Constraint bandwidth2 = BandwidthConstraint.of(400, DataRateUnit.BPS);
constraints2.add(bandwidth2);
failedPathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2);
failedPathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2, null);
// Creates failedPathInfo3
DeviceId src3 = DeviceId.deviceId("foo3");
......@@ -142,7 +142,7 @@ public class DistributedPceStoreTest {
Constraint bandwidth3 = BandwidthConstraint.of(500, DataRateUnit.BPS);
constraints3.add(bandwidth3);
failedPathInfo3 = new PcePathInfo(src3, dst3, name3, constraints3, lspType3);
failedPathInfo3 = new PcePathInfo(src3, dst3, name3, constraints3, lspType3, null);
// Creates failedPathInfo4
DeviceId src4 = DeviceId.deviceId("foo4");
......@@ -153,7 +153,7 @@ public class DistributedPceStoreTest {
Constraint bandwidth4 = BandwidthConstraint.of(600, DataRateUnit.BPS);
constraints4.add(bandwidth4);
failedPathInfo4 = new PcePathInfo(src4, dst4, name4, constraints4, lspType4);
failedPathInfo4 = new PcePathInfo(src4, dst4, name4, constraints4, lspType4, null);
}
@After
......
......@@ -53,10 +53,10 @@ public class PcePathInfoTest {
Constraint bandwidth13 = BandwidthConstraint.of(300, DataRateUnit.BPS);
constraints1.add(bandwidth13);
PcePathInfo pathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1);
PcePathInfo pathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1, null);
// create same object as above object
PcePathInfo samePathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1);
PcePathInfo samePathInfo1 = new PcePathInfo(src1, dst1, name1, constraints1, lspType1, null);
// Create different object.
DeviceId src2 = DeviceId.deviceId("foo2");
......@@ -69,7 +69,7 @@ public class PcePathInfoTest {
Constraint bandwidth22 = BandwidthConstraint.of(800, DataRateUnit.BPS);
constraints2.add(bandwidth22);
PcePathInfo pathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2);
PcePathInfo pathInfo2 = new PcePathInfo(src2, dst2, name2, constraints2, lspType2, null);
new EqualsTester().addEqualityGroup(pathInfo1, samePathInfo1)
.addEqualityGroup(pathInfo2)
......@@ -93,7 +93,7 @@ public class PcePathInfoTest {
Constraint bandwidth3 = BandwidthConstraint.of(300, DataRateUnit.BPS);
constraints.add(bandwidth3);
PcePathInfo pathInfo = new PcePathInfo(src, dst, name, constraints, lspType);
PcePathInfo pathInfo = new PcePathInfo(src, dst, name, constraints, lspType, null);
assertThat(src, is(pathInfo.src()));
assertThat(dst, is(pathInfo.dst()));
......
......@@ -22,13 +22,14 @@ import java.util.concurrent.ConcurrentMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.resource.ResourceConsumer;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pcestore.PcePathInfo;
import org.onosproject.pce.pcestore.api.PceStore;
......@@ -43,8 +44,8 @@ public class PceStoreAdapter implements PceStore {
// Set of Path info
private Set<PcePathInfo> failedPathInfoSet = new HashSet<>();
// Locally maintain LSRID to device id mapping for better performance.
private Map<String, DeviceId> lsrIdDeviceIdMap = new HashMap<>();
// Locally maintain with tunnel name as key and corresponding list of explicit path object
private Map<String, List<ExplicitPathInfo>> tunnelNameExplicitPathInfoMap = new HashMap<>();
@Override
public boolean existsTunnelInfo(TunnelId tunnelId) {
......@@ -108,4 +109,15 @@ public class PceStoreAdapter implements PceStore {
}
return true;
}
@Override
public boolean tunnelNameExplicitPathInfoMap(String tunnelName, List<ExplicitPathInfo> explicitPathInfo) {
tunnelNameExplicitPathInfoMap.put(tunnelName, explicitPathInfo);
return false;
}
@Override
public List<ExplicitPathInfo> getTunnelNameExplicitPathInfoMap(String tunnelName) {
return tunnelNameExplicitPathInfoMap.get(tunnelName);
}
}
......
......@@ -16,9 +16,22 @@
package org.onosproject.pcerest;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.Link.State.ACTIVE;
import static org.onosproject.net.Link.Type.DIRECT;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.PortNumber;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.PcePath;
import org.onosproject.pce.pceservice.DefaultPcePath;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
......@@ -29,6 +42,11 @@ import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* PCE path json codec.
*/
......@@ -42,7 +60,13 @@ public final class PcePathCodec extends JsonCodec<PcePath> {
private static final String COST = "cost";
private static final String BANDWIDTH = "bandwidth";
private static final String PATH_ID = "pathId";
private static final String EXPLICIT_PATH_INFO = "explicitPathInfo";
private static final String MISSING_MEMBER_MESSAGE = " member is required in pce-path";
public static final String JSON_NOT_NULL = "JsonNode can not be null";
public static final byte SOURCE_DEVICEID_INDEX = 0;
public static final byte SOURCE_PORTNO_INDEX = 1;
public static final byte DESTINATION_DEVICEID_INDEX = 2;
public static final byte DESTINATION_PORTNO_INDEX = 3;
@Override
public PcePath decode(ObjectNode json, CodecContext context) {
......@@ -114,9 +138,87 @@ public final class PcePathCodec extends JsonCodec<PcePath> {
}
}
// Retrieve explicit path info
JsonNode explicitPathInfo = json.get(EXPLICIT_PATH_INFO);
if (explicitPathInfo != null) {
List<ExplicitPathInfo> explicitPathInfoList =
ImmutableList.copyOf(jsonNodeToExplicitPathInfo(explicitPathInfo));
if (explicitPathInfoList != null) {
resultBuilder.explicitPathInfo(explicitPathInfoList);
}
}
return resultBuilder.build();
}
private ExplicitPathInfo createListOfExplicitPathObj(JsonNode node) {
int explicitPathType = Integer.parseInt(node.get("type").asText());
DeviceId deviceId;
PortNumber portNo;
NetworkResource res;
LinkedList<ExplicitPathInfo> list = Lists.newLinkedList();
if ((explicitPathType < 0) || (explicitPathType > 1)) {
return null;
}
ExplicitPathInfo.Type type = ExplicitPathInfo.Type.values()[explicitPathType];
String subType = node.get("subtype").asText();
if (Integer.parseInt(subType) == 0) {
res = DeviceId.deviceId(node.get("value").asText());
} else if (Integer.parseInt(subType) == 1) {
String[] splitted = node.get("value").asText().split("/");
if (splitted[SOURCE_DEVICEID_INDEX] != null
&& splitted[SOURCE_PORTNO_INDEX] != null
&& splitted[DESTINATION_DEVICEID_INDEX] != null
&& splitted[DESTINATION_PORTNO_INDEX] != null) {
return null;
}
deviceId = DeviceId.deviceId(splitted[SOURCE_DEVICEID_INDEX]);
portNo = PortNumber.portNumber(splitted[SOURCE_PORTNO_INDEX]);
ConnectPoint cpSrc = new ConnectPoint(deviceId, portNo);
deviceId = DeviceId.deviceId(splitted[DESTINATION_DEVICEID_INDEX]);
portNo = PortNumber.portNumber(splitted[DESTINATION_PORTNO_INDEX]);
ConnectPoint cpDst = new ConnectPoint(deviceId, portNo);
res = DefaultLink.builder()
.providerId(ProviderId.NONE)
.src(cpSrc)
.dst(cpDst)
.type(DIRECT)
.state(ACTIVE)
.build();
} else {
return null;
}
return new ExplicitPathInfo(type, res);
}
private Collection<ExplicitPathInfo> jsonNodeToExplicitPathInfo(JsonNode explicitPathInfo) {
checkNotNull(explicitPathInfo, JSON_NOT_NULL);
Integer i = 0;
NetworkResource res;
LinkedList<ExplicitPathInfo> list = Lists.newLinkedList();
if (explicitPathInfo.isArray()) {
for (JsonNode node : explicitPathInfo) {
ExplicitPathInfo obj = createListOfExplicitPathObj(node);
if (obj == null) {
return null;
}
list.add(obj);
}
} else {
ExplicitPathInfo obj = createListOfExplicitPathObj(explicitPathInfo);
if (obj == null) {
return null;
}
list.add(obj);
}
return Collections.unmodifiableCollection(list);
}
@Override
public ObjectNode encode(PcePath path, CodecContext context) {
checkNotNull(path, "path output cannot be null");
......@@ -133,6 +235,18 @@ public final class PcePathCodec extends JsonCodec<PcePath> {
.put(COST, ((CostConstraint) path.costConstraint()).type().type())
.put(BANDWIDTH, ((BandwidthConstraint) path.bandwidthConstraint()).bandwidth().bps());
if (path.explicitPathInfo() != null && !path.explicitPathInfo().isEmpty()) {
ArrayNode arrayNode = context.mapper().createArrayNode();
for (ExplicitPathInfo e : path.explicitPathInfo()) {
ObjectNode node = context.mapper()
.createObjectNode()
.put("type", e.type().toString())
.put("value", e.value().toString());
arrayNode.add(node);
}
result.set(EXPLICIT_PATH_INFO, arrayNode);
}
result.set(CONSTRAINT, constraintNode);
return result;
}
......
......@@ -35,11 +35,13 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.google.common.collect.ImmutableList;
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.intent.Constraint;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.api.PceService;
import org.onosproject.pce.pceservice.PcePath;
import org.onosproject.pce.pceservice.DefaultPcePath;
......@@ -150,8 +152,14 @@ public class PcePathWebResource extends AbstractWebResource {
// Add cost
listConstrnt.add(path.costConstraint());
List<ExplicitPathInfo> explicitPathInfoList = null;
if (explicitPathInfoList != null) {
explicitPathInfoList = ImmutableList.copyOf(path.explicitPathInfo());
}
Boolean issuccess = nullIsNotFound(get(PceService.class)
.setupPath(srcDevice, dstDevice, path.name(), listConstrnt, lspType),
.setupPath(srcDevice, dstDevice, path.name(), listConstrnt,
lspType, explicitPathInfoList),
PCE_SETUP_PATH_FAILED);
return Response.status(OK).entity(issuccess.toString()).build();
} catch (IOException e) {
......
......@@ -64,6 +64,7 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.pce.pceservice.api.PceService;
import org.onosproject.pce.pceservice.PcepAnnotationKeys;
import org.onosproject.pce.pcestore.api.PceStore;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
import org.onosproject.net.provider.ProviderId;
......@@ -73,6 +74,7 @@ import org.onosproject.net.provider.ProviderId;
*/
public class PcePathResourceTest extends PceResourceTest {
private final PceService pceService = createMock(PceService.class);
private final PceStore pceStore = createMock(PceStore.class);
private final TunnelService tunnelService = createMock(TunnelService.class);
private final TunnelEndPoint src = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(23423));
private final TunnelEndPoint dst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(32421));
......@@ -102,6 +104,7 @@ public class PcePathResourceTest extends PceResourceTest {
MockPceCodecContext context = new MockPceCodecContext();
ServiceDirectory testDirectory = new TestServiceDirectory().add(PceService.class, pceService)
.add(TunnelService.class, tunnelService)
.add(PceStore.class, pceStore)
.add(CodecService.class, context.codecManager());
BaseResource.setServiceDirectory(testDirectory);
......@@ -233,7 +236,7 @@ public class PcePathResourceTest extends PceResourceTest {
*/
@Test
public void testPost() {
expect(pceService.setupPath(anyObject(), anyObject(), anyObject(), anyObject(), anyObject()))
expect(pceService.setupPath(anyObject(), anyObject(), anyObject(), anyObject(), anyObject(), anyObject()))
.andReturn(true)
.anyTimes();
replay(pceService);
......
......@@ -7,5 +7,10 @@
"constraint":
{ "cost":2,
"bandwidth":200.0
}
},
"explicitPathInfo" :
{"type":1,
"subtype":0,
"value":"11.0.0.2"
}
}
......
{"path": {"source":"11.0.0.1",
"destination":"11.0.0.2",
"pathType":"2",
"name":"pcc2",
"description":"path-create",
"pathType":"0",
"name":"rsvp11",
"constraint":
{"cost":2,
"bandwidth":200.0
{"cost":1,
"bandwidth":300
},
"explicitPathInfo" :
{"type":1,
"subtype":0,
"value":"11.0.0.2"
}
}
}
......
......@@ -507,7 +507,9 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
break;
}
path = pceService.setupPath((DeviceId) src, (DeviceId) dst, tunnelName, listConstrnt, lspTypeVal);
//TODO: need to get explicit paths [temporarily using null as the value]
path = pceService.setupPath((DeviceId) src, (DeviceId) dst, tunnelName, listConstrnt, lspTypeVal,
null);
if (!path) {
log.error("setup path is failed");
return;
......