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.PceConstraints;
15 import org.opendaylight.transportpce.pce.constraints.PceConstraintsCalc;
16 import org.opendaylight.transportpce.pce.gnpy.GnpyException;
17 import org.opendaylight.transportpce.pce.gnpy.GnpyResult;
18 import org.opendaylight.transportpce.pce.gnpy.GnpyUtilitiesImpl;
19 import org.opendaylight.transportpce.pce.gnpy.consumer.GnpyConsumer;
20 import org.opendaylight.transportpce.pce.graph.PceGraph;
21 import org.opendaylight.transportpce.pce.networkanalyzer.PceCalculation;
22 import org.opendaylight.transportpce.pce.networkanalyzer.PceResult;
23 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestInput;
24 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.PathComputationRequestInputBuilder;
25 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.path.computation.reroute.request.input.Endpoints;
26 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.service.path.rpc.result.PathDescriptionBuilder;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev211210.routing.constraints.HardConstraints;
28 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirection;
29 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ZToADirection;
30 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.PceMetric;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
37 * - path-computation-request
38 * - path-computation-reroute
39 * - cancel-resource-reserve.
40 * @author Martial Coulibaly ( martial.coulibaly@gfi.com ) on behalf of Orange
43 public class PceSendingPceRPCs {
46 private static final Logger LOG = LoggerFactory.getLogger(PceSendingPceRPCs.class);
47 /* define procedure success (or not ). */
48 private PceResult rc = new PceResult();
51 * define type of request<br> <code>true</code> pathcomputation <br>
52 * <code>false</code> cancelresourcereserve .
54 private PathDescriptionBuilder pathDescription;
55 private PathComputationRequestInput input;
56 private NetworkTransactionService networkTransaction;
57 private PceConstraints pceHardConstraints = new PceConstraints();
58 private PceConstraints pceSoftConstraints = new PceConstraints();
59 private GnpyResult gnpyAtoZ;
60 private GnpyResult gnpyZtoA;
61 private Boolean success;
62 private String message;
63 private String responseCode;
64 private final GnpyConsumer gnpyConsumer;
65 private PortMapping portMapping;
66 // Define the termination points whose reservation status is not taken into account during the pruning process
67 private Endpoints endpoints;
69 public PceSendingPceRPCs(GnpyConsumer gnpyConsumer) {
70 setPathDescription(null);
72 this.networkTransaction = null;
73 this.gnpyConsumer = gnpyConsumer;
76 public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
77 GnpyConsumer gnpyConsumer, PortMapping portMapping) {
78 this.gnpyConsumer = gnpyConsumer;
79 setPathDescription(null);
80 // TODO compliance check to check that input is not empty
82 this.networkTransaction = networkTransaction;
83 this.portMapping = portMapping;
84 this.endpoints = null;
87 public PceSendingPceRPCs(PathComputationRequestInput input, NetworkTransactionService networkTransaction,
88 GnpyConsumer gnpyConsumer, PortMapping portMapping,
89 Endpoints endpoints) {
90 this.gnpyConsumer = gnpyConsumer;
91 setPathDescription(null);
93 this.networkTransaction = networkTransaction;
94 this.portMapping = portMapping;
95 this.endpoints = endpoints;
98 public void cancelResourceReserve() {
100 LOG.info("Wait for 10s til beginning the PCE cancelResourceReserve request");
104 } catch (InterruptedException e) {
105 LOG.error("in PCESendingPceRPC: ",e);
108 LOG.info("cancelResourceReserve ...");
111 public void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints) {
113 PceCalculation nwAnalizer = new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc,
114 portMapping, endpoints);
115 nwAnalizer.retrievePceNetwork();
116 rc = nwAnalizer.getReturnStructure();
117 String serviceType = nwAnalizer.getServiceType();
118 if (!rc.getStatus()) {
119 LOG.error("In pathComputationWithConstraints, nwAnalizer: result = {}", rc);
122 LOG.info("PceGraph ...");
123 PceGraph graph = new PceGraph(nwAnalizer.getaendPceNode(), nwAnalizer.getzendPceNode(),
124 nwAnalizer.getAllPceNodes(), hardConstraints, softConstraints, rc, serviceType);
126 rc = graph.getReturnStructure();
127 if (!rc.getStatus()) {
128 LOG.warn("In pathComputationWithConstraints : Graph return without Path ");
129 // TODO fix. This is quick workaround for algorithm problem
130 if ((rc.getLocalCause() == PceResult.LocalCause.TOO_HIGH_LATENCY)
131 && (hardConstraints.getPceMetrics() == PceMetric.HopCount)
132 && (hardConstraints.getMaxLatency() != -1)) {
133 hardConstraints.setPceMetrics(PceMetric.PropagationDelay);
134 graph = patchRerunGraph(graph);
137 if (rc.getLocalCause() == PceResult.LocalCause.HD_NODE_INCLUDE) {
138 graph.setKpathsToBring(graph.getKpathsToBring() * 10);
139 graph = patchRerunGraph(graph);
142 if (!rc.getStatus()) {
143 LOG.error("In pathComputationWithConstraints, graph.calcPath: result = {}", rc);
147 LOG.info("PcePathDescription ...");
148 PcePathDescription description = new PcePathDescription(graph.getPathAtoZ(), nwAnalizer.getAllPceLinks(), rc);
149 description.buildDescriptions();
150 rc = description.getReturnStructure();
151 if (!rc.getStatus()) {
152 LOG.error("In pathComputationWithConstraints, description: result = {}", rc);
156 public void pathComputation() throws Exception {
158 PceConstraintsCalc constraints = new PceConstraintsCalc(input, networkTransaction);
159 pceHardConstraints = constraints.getPceHardConstraints();
160 pceSoftConstraints = constraints.getPceSoftConstraints();
161 pathComputationWithConstraints(pceHardConstraints, pceSoftConstraints);
162 this.success = rc.getStatus();
163 this.message = rc.getMessage();
164 this.responseCode = rc.getResponseCode();
166 AToZDirection atoz = null;
167 ZToADirection ztoa = null;
168 if (rc.getStatus()) {
169 atoz = rc.getAtoZDirection();
170 ztoa = rc.getZtoADirection();
173 //Connect to Gnpy to check path feasibility and recompute another path in case of path non-feasibility
175 if (gnpyConsumer.isAvailable()) {
176 GnpyUtilitiesImpl gnpy = new GnpyUtilitiesImpl(networkTransaction, input,
178 if (rc.getStatus() && gnpyToCheckFeasiblity(atoz,ztoa,gnpy)) {
179 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
182 callGnpyToComputeNewPath(gnpy);
184 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
187 catch (GnpyException e) {
188 LOG.error("Exception raised by GNPy {}",e.getMessage());
189 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
193 private boolean gnpyToCheckFeasiblity(AToZDirection atoz, ZToADirection ztoa, GnpyUtilitiesImpl gnpy)
194 throws GnpyException {
196 //Call GNPy for path verification
197 if (gnpy.verifyComputationByGnpy(atoz, ztoa, pceHardConstraints)) {
198 LOG.info("In pceSendingPceRPC: the path is feasible according to Gnpy");
199 gnpyAtoZ = gnpy.getGnpyAtoZ();
200 gnpyZtoA = gnpy.getGnpyZtoA();
206 private void callGnpyToComputeNewPath(GnpyUtilitiesImpl gnpy) throws GnpyException {
208 //Call GNPy in the case of non feasibility
209 LOG.info("In pceSendingPceRPC: the path is not feasible according to Gnpy");
210 HardConstraints gnpyPathAsHC = null;
211 gnpyPathAsHC = gnpy.askNewPathFromGnpy(pceHardConstraints);
212 if (gnpyPathAsHC == null) {
213 LOG.info("In pceSendingPceRPC: GNPy failed to find another path");
214 this.success = false;
215 this.message = "No path available by PCE and GNPy ";
216 this.responseCode = ResponseCodes.RESPONSE_FAILED;
217 gnpyAtoZ = gnpy.getGnpyAtoZ();
218 gnpyZtoA = gnpy.getGnpyZtoA();
222 LOG.info("In pceSendingPceRPC: GNPy succeed to find another path");
224 PathComputationRequestInput inputFromGnpy = new PathComputationRequestInputBuilder()
225 .setServiceName(input.getServiceName())
226 .setHardConstraints(gnpyPathAsHC)
227 .setSoftConstraints(input.getSoftConstraints())
228 .setPceRoutingMetric(PceMetric.HopCount)
229 .setServiceAEnd(input.getServiceAEnd())
230 .setServiceZEnd(input.getServiceZEnd())
232 PceConstraintsCalc constraintsGnpy = new PceConstraintsCalc(inputFromGnpy, networkTransaction);
233 PceConstraints gnpyHardConstraints = constraintsGnpy.getPceHardConstraints();
234 PceConstraints gnpySoftConstraints = constraintsGnpy.getPceSoftConstraints();
235 pathComputationWithConstraints(gnpyHardConstraints, gnpySoftConstraints);
236 AToZDirection atoz = rc.getAtoZDirection();
237 ZToADirection ztoa = rc.getZtoADirection();
238 if (gnpyToCheckFeasiblity(atoz, ztoa,gnpy)) {
239 LOG.info("In pceSendingPceRPC: the new path computed by GNPy is valid");
241 this.message = "Path is calculated by GNPy";
242 this.responseCode = ResponseCodes.RESPONSE_OK;
243 setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
245 LOG.info("In pceSendingPceRPC: the new path computed by GNPy is not valid");
246 this.success = false;
247 this.message = "No path available";
248 this.responseCode = ResponseCodes.RESPONSE_FAILED;
249 setPathDescription(new PathDescriptionBuilder().setAToZDirection(null).setZToADirection(null));
253 private PceGraph patchRerunGraph(PceGraph graph) {
254 LOG.info("In pathComputation patchRerunGraph : rerun Graph with metric = PROPAGATION-DELAY ");
255 graph.setConstrains(pceHardConstraints, pceSoftConstraints);
260 public PathDescriptionBuilder getPathDescription() {
261 return pathDescription;
264 private void setPathDescription(PathDescriptionBuilder pathDescription) {
265 this.pathDescription = pathDescription;
268 public Boolean getSuccess() {
272 public String getMessage() {
276 public String getResponseCode() {
277 return this.responseCode;
280 public GnpyResult getGnpyAtoZ() {
284 public GnpyResult getGnpyZtoA() {