use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm in project bgpcep by opendaylight.
the class AbstractPathComputation method pruneEdge.
/**
* Check if Edge need to be prune regarding all constraints including
* address family.
*
* @return True if Edge must be prune, False if Edge must be keep
*/
protected boolean pruneEdge(final ConnectedEdge edge, final CspfPath path) {
/* Check that Constraints are initialized */
if (constraints == null) {
LOG.warn("Constraints not set");
return true;
}
/* Edge could point to an unknown Vertex e.g. with inter-domain link */
if (edge.getDestination() == null || edge.getDestination().getVertex() == null) {
LOG.debug("No Destination");
return true;
}
/* Check that Edge have attributes */
EdgeAttributes attributes = edge.getEdge() != null ? edge.getEdge().getEdgeAttributes() : null;
if (attributes == null) {
LOG.debug("No attributes");
return true;
}
/* Check that Edge belongs to the requested address family */
switch(constraints.getAddressFamily()) {
case Ipv4:
if (attributes.getRemoteAddress() == null || attributes.getRemoteAddress().getIpv4Address() == null) {
LOG.debug("No Ipv4 address");
return true;
}
break;
case Ipv6:
if (attributes.getRemoteAddress() == null || attributes.getRemoteAddress().getIpv6Address() == null) {
LOG.debug("No Ipv6 address");
return true;
}
break;
case SrIpv4:
if (getIpv4NodeSid(edge.getDestination()) == null) {
LOG.debug("No Node-SID for IPv4");
return true;
}
if (attributes.getAdjSid() == null) {
LOG.debug("No Adjacency-SID");
return true;
}
break;
case SrIpv6:
if (getIpv6NodeSid(edge.getDestination()) == null) {
LOG.debug("No Node-SID for IPv6");
return true;
}
if (attributes.getAdjSid() == null) {
LOG.debug("No SR Adjacency-SID");
return true;
}
break;
default:
return true;
}
/* Skip checking other Constraints for simple SPF algorithm */
if (this instanceof ShortestPathFirst) {
LOG.trace("Edge {} is valid for Simple Path Computation", edge);
return false;
}
/*
* If specified, check that total TE Metric up to this edge respects the
* initial constraints
*/
if (constraints.getTeMetric() != null) {
if (attributes.getTeMetric() == null) {
return true;
} else {
int totalCost = attributes.getTeMetric().intValue() + path.getCost();
if (totalCost > constraints.getTeMetric().intValue()) {
LOG.debug("TeMetric {} exceed constraint {}", totalCost, constraints.getTeMetric().intValue());
return true;
}
}
}
/*
* If specified, check that total Delay up to this edge respects the
* initial constraints
*/
if (constraints.getDelay() != null) {
if (attributes.getDelay() == null) {
return true;
} else {
int totalDelay = attributes.getDelay().getValue().intValue() + path.getDelay();
if (totalDelay > constraints.getDelay().getValue().intValue()) {
LOG.debug("Delay {} exceed constraint {}", totalDelay, constraints.getDelay().getValue().intValue());
return true;
}
}
}
/* Check that Edge respect Loss constraint */
if (constraints.getLoss() != null) {
if (attributes.getLoss() == null || attributes.getLoss().getValue().intValue() > constraints.getLoss().getValue().intValue()) {
return true;
}
}
/* Check that Edge meet Bandwidth constraint */
int cos = 0;
if (constraints.getClassType() != null) {
cos = constraints.getClassType().intValue();
}
if (constraints.getBandwidth() != null) {
if (attributes.getMaxLinkBandwidth() == null || attributes.getMaxResvLinkBandwidth() == null || attributes.getUnreservedBandwidth() == null || attributes.getUnreservedBandwidth().get(cos) == null) {
return true;
} else {
Long bandwidth = constraints.getBandwidth().getValue().longValue();
Long unrsv = 0L;
for (UnreservedBandwidth unResBw : attributes.getUnreservedBandwidth()) {
if (unResBw.getClassType().intValue() == cos) {
unrsv = unResBw.getBandwidth().getValue().longValue();
break;
}
}
if (unrsv < bandwidth || attributes.getMaxLinkBandwidth().getValue().longValue() < bandwidth || attributes.getMaxResvLinkBandwidth().getValue().longValue() < bandwidth) {
LOG.debug("Bandwidth constraint is not met");
return true;
}
}
}
/* Check that Edge belongs to admin group */
if (constraints.getAdminGroup() != null && !constraints.getAdminGroup().equals(attributes.getAdminGroup())) {
LOG.debug("Not in the requested admin-group");
return true;
}
/*
* OK. All is fine. We can consider this Edge valid, so not to be prune
*/
LOG.trace("Edge {} is valid for Constrained Path Computation", edge);
return false;
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm in project bgpcep by opendaylight.
the class ConstrainedShortestPathFirst method computeP2pPath.
@Override
public ConstrainedPath computeP2pPath(final VertexKey src, final VertexKey dst, final PathConstraints cts) {
LOG.info("Start CSPF Path Computation from {} to {} with constraints {}", src, dst, cts);
/* Initialize algorithm */
this.constraints = cts;
ConstrainedPathBuilder cpathBuilder = initializePathComputation(src, dst);
if (cpathBuilder.getStatus() == ComputationStatus.Failed) {
return cpathBuilder.build();
}
cpathBuilder.setBandwidth(cts.getBandwidth()).setClassType(cts.getClassType());
visitedVertices.clear();
/* Process all Connected Vertex until priority queue becomes empty. Connected Vertices are added into the
* priority queue when processing the next Connected Vertex: see relaxMC() method */
int currentCost = Integer.MAX_VALUE;
while (priorityQueue.size() != 0) {
CspfPath currentPath = priorityQueue.poll();
visitedVertices.put(currentPath.getVertexKey(), currentPath);
LOG.debug("Got path to Vertex {} from Priority Queue", currentPath.getVertex());
List<ConnectedEdge> edges = currentPath.getVertex().getOutputConnectedEdges();
for (ConnectedEdge edge : edges) {
/* Skip Connected Edges that must be prune i.e. Edges that not satisfy the given constraints,
* in particular the Bandwidth, TE Metric and Delay. */
if (pruneEdge(edge, currentPath)) {
LOG.trace(" Prune Edge {}", edge);
continue;
}
if (relaxMultiConstraints(edge, currentPath) && pathDestination.getCost() < currentCost) {
currentCost = pathDestination.getCost();
cpathBuilder.setPathDescription(getPathDescription(pathDestination.getPath())).setMetric(Uint32.valueOf(pathDestination.getCost())).setStatus(ComputationStatus.Active);
LOG.debug(" Found a valid path up to destination {}", cpathBuilder.getPathDescription());
}
}
}
/* The priority queue is empty => all the possible (vertex, path) elements have been explored
* The "ConstrainedPathBuilder" object contains the optimal path if it exists
* Otherwise an empty path with status failed is returned
*/
if (cpathBuilder.getStatus() == ComputationStatus.InProgress || cpathBuilder.getPathDescription().size() == 0) {
cpathBuilder.setStatus(ComputationStatus.Failed);
} else {
cpathBuilder.setStatus(ComputationStatus.Completed);
}
return cpathBuilder.build();
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm in project bgpcep by opendaylight.
the class PathComputationServer method getConstrainedPath.
@Override
public ListenableFuture<RpcResult<GetConstrainedPathOutput>> getConstrainedPath(final GetConstrainedPathInput input) {
final GetConstrainedPathOutputBuilder output = new GetConstrainedPathOutputBuilder();
LOG.info("Got Path Computation Service request");
/* First, get graph */
final ConnectedGraph cgraph = graphProvider.getConnectedGraph(input.getGraphName());
if (cgraph == null) {
output.setStatus(ComputationStatus.Failed);
return RpcResultBuilder.<GetConstrainedPathOutput>failed().withError(RpcError.ErrorType.RPC, "Unknown Graph Name").buildFuture();
}
/* get a new Path Computation Algorithm according to Input choice */
PathComputationAlgorithm algo = getPathComputationAlgorithm(cgraph, input.getAlgorithm());
if (algo == null) {
output.setStatus(ComputationStatus.Failed);
return RpcResultBuilder.<GetConstrainedPathOutput>failed().withError(RpcError.ErrorType.RPC, "Unknown Path Computation Algorithm").buildFuture();
}
/*
* Request Path Computation for given source, destination and
* constraints
*/
final VertexKey source = new VertexKey(input.getSource());
final VertexKey destination = new VertexKey(input.getDestination());
LOG.info("Call Path Computation {} algorithm for path from {} to {} with contraints {}", input.getAlgorithm().getName(), source, destination, input.getConstraints());
final ConstrainedPath cpath = algo.computeP2pPath(source, destination, input.getConstraints());
/* Send back the Computed Path */
output.setPathDescription(cpath.getPathDescription()).setStatus(cpath.getStatus()).setComputedMetric(cpath.getMetric()).setComputedTeMetric(cpath.getTeMetric()).setComputedDelay(cpath.getDelay());
return RpcResultBuilder.success(output.build()).buildFuture();
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm in project bgpcep by opendaylight.
the class SrNodeAttributesParser method parseSrAlgorithms.
public static SrAlgorithm parseSrAlgorithms(final ByteBuf buffer) {
final SrAlgorithmBuilder builder = new SrAlgorithmBuilder();
final List<Algorithm> algs = new ArrayList<>();
while (buffer.isReadable()) {
algs.add(Algorithm.forValue(buffer.readUnsignedByte()));
}
builder.setAlgorithms(algs);
return builder.build();
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm in project bgpcep by opendaylight.
the class AbstractBestPathSelector method isExistingPathBetter.
/**
* Chooses best route according to BGP best path selection.
*
* @param state attributes of the new route
* @return true if the existing path is better, false if the new path is better
*/
protected boolean isExistingPathBetter(@NonNull final BestPathState state) {
// 0. draft-uttaro-idr-bgp-persistence-04 defines "depreferenced" paths
final boolean stateDepref = state.isDepreferenced();
if (this.bestState.isDepreferenced() != stateDepref) {
return stateDepref;
}
// 1. prefer path with accessible nexthop
// - we assume that all nexthops are accessible
/*
* 2. prefer path with higher LOCAL_PREF
*
* FIXME: for eBGP cases (when the LOCAL_PREF is missing), we should assign a policy-based preference
* before we ever get here.
*/
final Uint32 bestLocal = this.bestState.getLocalPref();
final Uint32 stateLocal = state.getLocalPref();
if (stateLocal != null) {
if (bestLocal == null) {
return true;
}
final int cmp = stateLocal.compareTo(bestLocal);
if (cmp != 0) {
return cmp < 0;
}
} else if (bestLocal != null) {
return false;
}
// 4. prefer the path with the shortest AS_PATH.
if (this.bestState.getAsPathLength() != state.getAsPathLength()) {
return this.bestState.getAsPathLength() < state.getAsPathLength();
}
// - IGP is lower than Exterior Gateway Protocol (EGP), and EGP is lower than INCOMPLETE
if (!this.bestState.getOrigin().equals(state.getOrigin())) {
final BgpOrigin bo = this.bestState.getOrigin();
final BgpOrigin no = state.getOrigin();
// This trick relies on the order in which the values are declared in the model.
return no.ordinal() > bo.ordinal();
}
// FIXME: we should be able to cache the best AS
final long bestAs = this.bestState.getPeerAs();
final long newAs = state.getPeerAs();
/*
* Checks 6 and 7 are mutually-exclusive, as MEDs are comparable
* only when the routes originated from the same AS. On the other
* hand, when they are from the same AS, they are in the same iBGP/eBGP
* relationship.
*
*/
if (bestAs == newAs) {
// 6. prefer the path with the lowest multi-exit discriminator (MED)
final Boolean cmp = firstLower(this.bestState.getMultiExitDisc(), state.getMultiExitDisc());
if (cmp != null) {
return cmp;
}
} else {
/*
* 7. prefer eBGP over iBGP paths
*
* EBGP is peering between two different AS, whereas IBGP is between same AS (Autonomous System),
* so we just compare the AS numbers to our AS.
*
* FIXME: we should know this information from the peer directly.
*/
if (this.ourAs != bestAs && this.ourAs == newAs) {
return true;
}
}
/*
* 10. Prefer the route that comes from the BGP router with the lowest router ID.
*
* This is normally guaranteed by the iteration order of our caller, which runs selection
* in the order of increasing router ID, but RFC-4456 Route Reflection throws a wrench into that.
*
* With RFC-5004, this gets a bit easier, because it completely eliminates step f) and later :-)
*
* RFC-5004 states that this algorithm should end here and select existing path over new path in the
* best path selection process. Benefits are listed in the RFC: @see http://tools.ietf.org/html/rfc500
* - This algorithm SHOULD NOT be applied when either path is from a BGP Confederation peer.
* - not applicable, we don't deal with confederation peers
* - The algorithm SHOULD NOT be applied when both paths are from peers with an identical BGP identifier
* (i.e., there exist parallel BGP sessions between two BGP speakers).
* - not applicable, BUG-2631 prevents parallel sessions to be created.
*/
return true;
}
Aggregations