2 * Copyright (c) 2020 Orange. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.bgpcep.pcep.server.provider;
11 import com.google.common.base.Preconditions;
12 import java.math.BigDecimal;
13 import java.nio.ByteBuffer;
14 import java.util.List;
15 import org.opendaylight.algo.PathComputationAlgorithm;
16 import org.opendaylight.algo.PathComputationProvider;
17 import org.opendaylight.bgpcep.pcep.server.PathComputation;
18 import org.opendaylight.graph.ConnectedGraph;
19 import org.opendaylight.graph.ConnectedVertex;
20 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
21 import org.opendaylight.protocol.pcep.spi.PSTUtil;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.DecimalBandwidth;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.Delay;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.VertexKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.AlgorithmType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.ComputationStatus;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.ConstrainedPath;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.PathConstraints;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.PathConstraints.AddressFamily;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.get.constrained.path.input.ConstraintsBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.Bandwidth;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.classtype.object.ClassType;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.Ipv4Case;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.Ipv6Case;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.object.EndpointsObj;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.Requests;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2p;
42 import org.opendaylight.yangtools.yang.common.Uint32;
43 import org.opendaylight.yangtools.yang.common.Uint8;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public class PathComputationImpl implements PathComputation {
49 private static final Logger LOG = LoggerFactory.getLogger(PathComputationImpl.class);
51 private final ConnectedGraph tedGraph;
52 private final PathComputationProvider algoProvider;
54 public PathComputationImpl(ConnectedGraph tedGraph, PathComputationProvider algoProvider) {
55 Preconditions.checkArgument(tedGraph != null);
56 this.tedGraph = tedGraph;
57 this.algoProvider = algoProvider;
61 public Message computePath(Requests req) {
62 LOG.info("Received Compute Path request");
64 /* Check that Request Parameter Object is present */
65 if (req == null || req.getRp() == null) {
66 LOG.error("Missing Request Parameter Objects. Abort!");
67 return MessagesUtil.createErrorMsg(PCEPErrors.RP_MISSING, Uint32.ZERO);
70 LOG.debug("Request for path computation {}", req);
73 * Check that mandatory End Point Objects are present and Source /
74 * Destination are know in the TED Graph
76 P2p input = req.getSegmentComputation().getP2p();
77 if (input == null || input.getEndpointsObj() == null) {
78 LOG.error("Missing End Point Objects. Abort!");
79 Uint32 reqID = req.getRp().getRequestId().getValue();
80 return MessagesUtil.createErrorMsg(PCEPErrors.END_POINTS_MISSING, reqID);
82 VertexKey source = getSourceVertexKey(input.getEndpointsObj());
83 VertexKey destination = getDestinationVertexKey(input.getEndpointsObj());
85 return MessagesUtil.createNoPathMessage(req.getRp(), MessagesUtil.UNKNOWN_SOURCE);
87 if (destination == null) {
88 return MessagesUtil.createNoPathMessage(req.getRp(), MessagesUtil.UNKNOWN_DESTINATION);
91 /* Create new Constraints Object from the request */
92 PathConstraints cts = getConstraints(input, !PSTUtil.isDefaultPST(req.getRp().getTlvs().getPathSetupType()));
94 /* Determine Path Computation Algorithm according to Input choice */
95 AlgorithmType algoType;
96 if ((cts.getTeMetric() == null) && (cts.getDelay() == null)) {
97 algoType = AlgorithmType.Spf;
98 } else if (cts.getDelay() == null) {
99 algoType = AlgorithmType.Cspf;
101 algoType = AlgorithmType.Samcra;
103 PathComputationAlgorithm algo = algoProvider.getPathComputationAlgorithm(tedGraph, algoType);
105 return MessagesUtil.createErrorMsg(PCEPErrors.RESOURCE_LIMIT_EXCEEDED, Uint32.ZERO);
108 /* Request Path Computation for given source, destination and constraints */
109 LOG.debug("Call Path Computation {} algorithm for path from {} to {} with contraints {}",
110 algoType, source, destination, cts);
111 final ConstrainedPath cpath = algo.computeP2pPath(source, destination, cts);
113 LOG.info("Computed path: {}", cpath.getPathDescription());
115 /* Check if we got a valid Path and return appropriate message */
116 if (cpath.getStatus() == ComputationStatus.Completed) {
117 return MessagesUtil.createPcRepMessage(req.getRp(), req.getSegmentComputation().getP2p(), cpath);
119 return MessagesUtil.createNoPathMessage(req.getRp(), MessagesUtil.NO_PATH);
124 public Ero computeEro(EndpointsObj endpoints, Bandwidth bandwidth, ClassType classType, List<Metrics> metrics,
125 boolean segmentRouting) {
126 VertexKey source = getSourceVertexKey(endpoints);
127 VertexKey destination = getDestinationVertexKey(endpoints);
128 if (source == null) {
131 if (destination == null) {
134 /* Create new Constraints Object from the request */
135 PathConstraints cts = getConstraints(endpoints, bandwidth, classType, metrics, segmentRouting);
137 /* Determine Path Computation Algorithm according to parameters */
138 AlgorithmType algoType;
139 if ((cts.getTeMetric() == null) && (cts.getDelay() == null) && (cts.getBandwidth() == null)) {
140 algoType = AlgorithmType.Spf;
141 } else if (cts.getDelay() == null) {
142 algoType = AlgorithmType.Cspf;
144 algoType = AlgorithmType.Samcra;
146 PathComputationAlgorithm algo = algoProvider.getPathComputationAlgorithm(tedGraph, algoType);
152 * Request Path Computation for given source, destination and
155 final ConstrainedPath cpath = algo.computeP2pPath(source, destination, cts);
157 LOG.info("Computed ERO: {}", cpath.getPathDescription());
159 /* Check if we got a valid Path and return appropriate ERO */
160 if (cpath.getStatus() == ComputationStatus.Completed) {
161 return MessagesUtil.getEro(cpath.getPathDescription());
167 private VertexKey getSourceVertexKey(EndpointsObj endPoints) {
168 IpAddress address = null;
170 if (endPoints.getAddressFamily() instanceof Ipv4Case) {
171 address = new IpAddress(((Ipv4Case) endPoints.getAddressFamily()).getIpv4().getSourceIpv4Address());
173 if (endPoints.getAddressFamily() instanceof Ipv6Case) {
174 address = new IpAddress(((Ipv6Case) endPoints.getAddressFamily()).getIpv6().getSourceIpv6Address());
176 if (address == null) {
180 ConnectedVertex vertex = tedGraph.getConnectedVertex(address);
181 LOG.debug("Compute path from Source {}", vertex.toString());
182 return (vertex != null) ? vertex.getVertex().key() : null;
185 private VertexKey getDestinationVertexKey(EndpointsObj endPoints) {
186 IpAddress address = null;
188 if (endPoints.getAddressFamily() instanceof Ipv4Case) {
189 address = new IpAddress(((Ipv4Case) endPoints.getAddressFamily()).getIpv4().getDestinationIpv4Address());
191 if (endPoints.getAddressFamily() instanceof Ipv6Case) {
192 address = new IpAddress(((Ipv6Case) endPoints.getAddressFamily()).getIpv6().getDestinationIpv6Address());
194 if (address == null) {
198 ConnectedVertex vertex = tedGraph.getConnectedVertex(address);
199 LOG.debug("Compute path to Destination {}", vertex.toString());
200 return (vertex != null) ? vertex.getVertex().key() : null;
203 private PathConstraints getConstraints(P2p parameters, boolean segmentRouting) {
204 return getConstraints(parameters.getEndpointsObj(), parameters.getBandwidth(), parameters.getClassType(),
205 parameters.getMetrics(), segmentRouting);
208 private PathConstraints getConstraints(EndpointsObj endpoints, Bandwidth bandwidth, ClassType classType,
209 List<Metrics> metrics, boolean segmentRouting) {
210 ConstraintsBuilder ctsBuilder = new ConstraintsBuilder();
213 /* Set Metrics if any */
214 if (metrics != null) {
215 for (Metrics metric : metrics) {
216 convert = ByteBuffer.wrap(metric.getMetric().getValue().getValue()).getFloat();
217 switch (metric.getMetric().getMetricType().intValue()) {
218 case MessagesUtil.IGP_METRIC:
219 ctsBuilder.setMetric(Uint32.valueOf(convert.longValue()));
221 case MessagesUtil.TE_METRIC:
222 ctsBuilder.setTeMetric(Uint32.valueOf(convert.longValue()));
224 case MessagesUtil.PATH_DELAY:
225 ctsBuilder.setDelay(new Delay(Uint32.valueOf(convert.longValue())));
228 LOG.warn("Metric {} is not handle by Path Computation Constraints", metric);
234 /* Set Bandwidth and Class Type */
235 if (bandwidth != null) {
236 convert = ByteBuffer.wrap(bandwidth.getBandwidth().getValue()).getFloat();
237 ctsBuilder.setBandwidth(new DecimalBandwidth(BigDecimal.valueOf(convert.longValue())));
238 if (classType != null) {
239 ctsBuilder.setClassType(classType.getClassType().getValue());
241 ctsBuilder.setClassType(Uint8.ZERO);
245 /* Set Address Family */
246 if (endpoints.getAddressFamily() instanceof Ipv4Case) {
247 if (segmentRouting) {
248 ctsBuilder.setAddressFamily(AddressFamily.SrIpv4);
250 ctsBuilder.setAddressFamily(AddressFamily.Ipv4);
253 if (segmentRouting) {
254 ctsBuilder.setAddressFamily(AddressFamily.SrIpv6);
256 ctsBuilder.setAddressFamily(AddressFamily.Ipv6);
260 return ctsBuilder.build();