2 * Copyright © 2017 AT&T and others. 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.transportpce.pce;
11 import org.opendaylight.transportpce.common.ResponseCodes;
12 import org.opendaylight.transportpce.common.mapping.PortMapping;
13 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
14 import org.opendaylight.transportpce.pce.constraints.OperatorConstraints;
15 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
16 import org.opendaylight.transportpce.pce.constraints.PceConstraintsCalc;
17 import org.opendaylight.transportpce.pce.gnpy.GnpyException;
18 import org.opendaylight.transportpce.pce.gnpy.GnpyResult;
19 import org.opendaylight.transportpce.pce.gnpy.GnpyUtilitiesImpl;
20 import org.opendaylight.transportpce.pce.gnpy.consumer.GnpyConsumer;
21 import org.opendaylight.transportpce.pce.graph.PceGraph;
22 import org.opendaylight.transportpce.pce.networkanalyzer.PceCalculation;
23 import org.opendaylight.transportpce.pce.networkanalyzer.PceResult;
24 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestInput;
25 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestInputBuilder;
26 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PceConstraintMode;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.path.computation.reroute.request.input.Endpoints;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.service.path.rpc.result.PathDescriptionBuilder;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.HardConstraints;
30 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.path.description.AToZDirection;
31 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.path.description.ZToADirection;
32 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.PceMetric;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
39 * - path-computation-request
40 * - path-computation-reroute
41 * - cancel-resource-reserve.
42 * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
45 public class PceSendingPceRPCs {
48 private static final Logger LOG = LoggerFactory.getLogger(PceSendingPceRPCs.class);
49 /* define procedure success (or not ). */
50 private PceResult rc = new PceResult();
53 * define type of request<br> <code>true</code> pathcomputation <br>
54 * <code>false</code> cancelresourcereserve .
56 private PathDescriptionBuilder pathDescription;
57 private PathComputationRequestInput input;
58 private NetworkTransactionService networkTransaction;
59 private PceConstraints pceHardConstraints = new PceConstraints();
60 private PceConstraints pceSoftConstraints = new PceConstraints();
61 private GnpyResult gnpyAtoZ;
62 private GnpyResult gnpyZtoA;
63 private Boolean success;
64 private String message;
65 private String responseCode;
66 private final GnpyConsumer gnpyConsumer;
67 private PortMapping portMapping;
68 // Define the termination points whose reservation status is not taken into account during the pruning process
69 private Endpoints endpoints;
71 public PceSendingPceRPCs(GnpyConsumer gnpyConsumer) {
72 setPathDescription(null);
74 this.networkTransaction = null;
75 this.gnpyConsumer = gnpyConsumer;
78 public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
79 GnpyConsumer gnpyConsumer, PortMapping portMapping) {
80 this.gnpyConsumer = gnpyConsumer;
81 setPathDescription(null);
82 // TODO compliance check to check that input is not empty
84 this.networkTransaction = networkTransaction;
85 this.portMapping = portMapping;
86 this.endpoints = null;
89 public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
90 GnpyConsumer gnpyConsumer, PortMapping portMapping,
91 Endpoints endpoints) {
92 this.gnpyConsumer = gnpyConsumer;
93 setPathDescription(null);
95 this.networkTransaction = networkTransaction;
96 this.portMapping = portMapping;
97 this.endpoints = endpoints;
100 public void cancelResourceReserve() {
102 LOG.info("Wait for 10s til beginning the PCE cancelResourceReserve request");
106 } catch (InterruptedException e) {
107 LOG.error("in PCESendingPceRPC: ",e);
110 LOG.info("cancelResourceReserve ...");
113 private void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints,
114 PceConstraintMode mode) {
116 PceCalculation nwAnalizer = new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc,
117 portMapping, endpoints);
118 nwAnalizer.retrievePceNetwork();
119 rc = nwAnalizer.getReturnStructure();
120 String serviceType = nwAnalizer.getServiceType();
121 if (!rc.getStatus()) {
122 LOG.error("In pathComputationWithConstraints, nwAnalizer: result = {}", rc);
125 OperatorConstraints opConstraints = new OperatorConstraints(networkTransaction);
126 LOG.info("PceGraph ...");
127 PceGraph graph = new PceGraph(nwAnalizer.getaendPceNode(), nwAnalizer.getzendPceNode(),
128 nwAnalizer.getAllPceNodes(), nwAnalizer.getAllPceLinks(), hardConstraints,
129 rc, serviceType, networkTransaction, mode, opConstraints.getBitMapConstraint(input.getCustomerName()));
131 rc = graph.getReturnStructure();
132 if (!rc.getStatus()) {
133 LOG.warn("In pathComputationWithConstraints : Graph return without Path ");
134 // TODO fix. This is quick workaround for algorithm problem
135 if ((rc.getLocalCause() == PceResult.LocalCause.TOO_HIGH_LATENCY)
136 && (hardConstraints.getPceMetrics() == PceMetric.HopCount)
137 && (hardConstraints.getMaxLatency() != -1)) {
138 hardConstraints.setPceMetrics(PceMetric.PropagationDelay);
139 graph = patchRerunGraph(graph);
142 if (rc.getLocalCause() == PceResult.LocalCause.HD_NODE_INCLUDE) {
143 graph.setKpathsToBring(graph.getKpathsToBring() * 10);
144 graph = patchRerunGraph(graph);
147 if (!rc.getStatus()) {
148 LOG.error("In pathComputationWithConstraints, graph.calcPath: result = {}", rc);
152 LOG.info("PcePathDescription ...");
153 PcePathDescription description = new PcePathDescription(graph.getPathAtoZ(), nwAnalizer.getAllPceLinks(), rc);
154 description.buildDescriptions();
155 rc = description.getReturnStructure();
156 if (!rc.getStatus()) {
157 LOG.error("In pathComputationWithConstraints, description: result = {}", rc);
161 public void pathComputation() throws Exception {
163 PceConstraintsCalc constraints = new PceConstraintsCalc(input, networkTransaction);
164 pceHardConstraints = constraints.getPceHardConstraints();
165 pceSoftConstraints = constraints.getPceSoftConstraints();
166 pathComputationWithConstraints(pceHardConstraints, pceSoftConstraints, PceConstraintMode.Loose);
167 this.success = rc.getStatus();
168 this.message = rc.getMessage();
169 this.responseCode = rc.getResponseCode();
171 AToZDirection atoz = null;
172 ZToADirection ztoa = null;
173 if (rc.getStatus()) {
174 atoz = rc.getAtoZDirection();
175 ztoa = rc.getZtoADirection();
178 //Connect to Gnpy to check path feasibility and recompute another path in case of path non-feasibility
180 if (gnpyConsumer.isAvailable()) {
181 GnpyUtilitiesImpl gnpy = new GnpyUtilitiesImpl(networkTransaction, input,
183 if (rc.getStatus() && gnpyToCheckFeasiblity(atoz,ztoa,gnpy)) {
184 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
187 callGnpyToComputeNewPath(gnpy);
189 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
192 catch (GnpyException e) {
193 LOG.error("Exception raised by GNPy {}",e.getMessage());
194 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
198 private boolean gnpyToCheckFeasiblity(AToZDirection atoz, ZToADirection ztoa, GnpyUtilitiesImpl gnpy)
199 throws GnpyException {
201 //Call GNPy for path verification
202 if (gnpy.verifyComputationByGnpy(atoz, ztoa, pceHardConstraints)) {
203 LOG.info("In pceSendingPceRPC: the path is feasible according to Gnpy");
204 gnpyAtoZ = gnpy.getGnpyAtoZ();
205 gnpyZtoA = gnpy.getGnpyZtoA();
211 private void callGnpyToComputeNewPath(GnpyUtilitiesImpl gnpy) throws GnpyException {
213 //Call GNPy in the case of non feasibility
214 LOG.info("In pceSendingPceRPC: the path is not feasible according to Gnpy");
215 HardConstraints gnpyPathAsHC = null;
216 gnpyPathAsHC = gnpy.askNewPathFromGnpy(pceHardConstraints);
217 if (gnpyPathAsHC == null) {
218 LOG.info("In pceSendingPceRPC: GNPy failed to find another path");
219 this.success = false;
220 this.message = "No path available by PCE and GNPy ";
221 this.responseCode = ResponseCodes.RESPONSE_FAILED;
222 gnpyAtoZ = gnpy.getGnpyAtoZ();
223 gnpyZtoA = gnpy.getGnpyZtoA();
227 LOG.info("In pceSendingPceRPC: GNPy succeed to find another path");
229 PathComputationRequestInput inputFromGnpy = new PathComputationRequestInputBuilder()
230 .setServiceName(input.getServiceName())
231 .setHardConstraints(gnpyPathAsHC)
232 .setSoftConstraints(input.getSoftConstraints())
233 .setPceRoutingMetric(PceMetric.HopCount)
234 .setServiceAEnd(input.getServiceAEnd())
235 .setServiceZEnd(input.getServiceZEnd())
237 PceConstraintsCalc constraintsGnpy = new PceConstraintsCalc(inputFromGnpy, networkTransaction);
238 PceConstraints gnpyHardConstraints = constraintsGnpy.getPceHardConstraints();
239 PceConstraints gnpySoftConstraints = constraintsGnpy.getPceSoftConstraints();
240 pathComputationWithConstraints(gnpyHardConstraints, gnpySoftConstraints, PceConstraintMode.Strict);
241 AToZDirection atoz = rc.getAtoZDirection();
242 ZToADirection ztoa = rc.getZtoADirection();
243 if (gnpyToCheckFeasiblity(atoz, ztoa,gnpy)) {
244 LOG.info("In pceSendingPceRPC: the new path computed by GNPy is valid");
246 this.message = "Path is calculated by GNPy";
247 this.responseCode = ResponseCodes.RESPONSE_OK;
248 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
250 LOG.info("In pceSendingPceRPC: the new path computed by GNPy is not valid");
251 this.success = false;
252 this.message = "No path available";
253 this.responseCode = ResponseCodes.RESPONSE_FAILED;
254 setPathDescription(new PathDescriptionBuilder().setAToZDirection(null).setZToADirection(null));
258 private PceGraph patchRerunGraph(PceGraph graph) {
259 LOG.info("In pathComputation patchRerunGraph : rerun Graph with metric = PROPAGATION-DELAY ");
260 graph.setConstrains(pceHardConstraints);
265 public PathDescriptionBuilder getPathDescription() {
266 return pathDescription;
269 private void setPathDescription(PathDescriptionBuilder pathDescription) {
270 this.pathDescription = pathDescription;
273 public Boolean getSuccess() {
277 public String getMessage() {
281 public String getResponseCode() {
282 return this.responseCode;
285 public GnpyResult getGnpyAtoZ() {
289 public GnpyResult getGnpyZtoA() {