626895fd181b71486e0241f5569870f955e58a23
[transportpce.git] / pce / src / main / java / org / opendaylight / transportpce / pce / graph / PostAlgoPathValidator.java
1 /*
2  * Copyright © 2017 AT&T, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.transportpce.pce.graph;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Map;
14
15 import org.jgrapht.GraphPath;
16 import org.opendaylight.transportpce.common.ResponseCodes;
17 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
18 import org.opendaylight.transportpce.pce.constraints.PceConstraints.ResourcePair;
19 import org.opendaylight.transportpce.pce.networkanalyzer.PceNode;
20 import org.opendaylight.transportpce.pce.networkanalyzer.PceResult;
21 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 public class PostAlgoPathValidator {
27     /* Logging. */
28     private static final Logger LOG = LoggerFactory.getLogger(PceGraph.class);
29
30     // TODO hard-coded 96
31     private static final int MAX_WAWELENGTH = 96;
32     private static final double MIN_OSNR_W100G = 17;
33     private static final double TRX_OSNR = 33;
34     private static final double ADD_OSNR = 30;
35     public static final Long CONST_OSNR = 1L;
36     public static final double SYS_MARGIN = 0;
37
38     public PceResult checkPath(GraphPath<String, PceGraphEdge> path,
39             Map<NodeId, PceNode> allPceNodes, PceResult pceResult, PceConstraints pceHardConstraints) {
40
41         //check if the path is empty
42         if (path.getEdgeList().size() == 0) {
43             pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
44             return pceResult;
45         }
46
47         //Choose wavelength available in all nodes of the path
48         Long waveL = chooseWavelength(path, allPceNodes);
49         if (waveL < 0) {
50             pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
51             pceResult.setLocalCause(PceResult.LocalCause.NO_PATH_EXISTS);
52             return pceResult;
53         }
54         pceResult.setResultWavelength(waveL);
55         LOG.info("In PostAlgoPathValidator: chooseWavelength WL found {} {}", waveL, path.toString());
56
57         // TODO here other post algo validations can be added
58         // more data can be sent to PceGraph module via PceResult structure if required
59
60         //Check the OSNR
61         if (!checkOSNR(path)) {
62             pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
63             pceResult.setLocalCause(PceResult.LocalCause.OUT_OF_SPEC_OSNR);
64             return pceResult;
65         }
66
67         //Check if MaxLatency is defined in the hard constraints
68         if (pceHardConstraints.getMaxLatency() != -1) {
69             if (!checkLatency(pceHardConstraints.getMaxLatency(), path)) {
70                 pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
71                 pceResult.setLocalCause(PceResult.LocalCause.TOO_HIGH_LATENCY);
72                 return pceResult;
73             }
74         }
75
76         //Check if nodes are included in the hard constraints
77         if (!checkInclude(path, pceHardConstraints)) {
78             pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
79             pceResult.setLocalCause(PceResult.LocalCause.HD_NODE_INCLUDE);
80             return pceResult;
81         }
82
83         pceResult.setRC(ResponseCodes.RESPONSE_OK);
84         return pceResult;
85     }
86
87     //Choose the first available wavelength from the source to the destination
88     private Long chooseWavelength(GraphPath<String, PceGraphEdge> path, Map<NodeId, PceNode> allPceNodes) {
89         Long wavelength = -1L;
90
91         for (long i = 1; i <= MAX_WAWELENGTH; i++) {
92             boolean completed = true;
93             LOG.debug("In chooseWavelength: {} {}", path.getLength(), path.toString());
94             for (PceGraphEdge edge : path.getEdgeList()) {
95                 LOG.debug("In chooseWavelength: source {} ", edge.link().getSourceId().toString());
96                 PceNode pceNode = allPceNodes.get(edge.link().getSourceId());
97                 if (!pceNode.checkWL(i)) {
98                     completed = false;
99                     break;
100                 }
101             }
102             if (completed) {
103                 wavelength = i;
104                 break;
105             }
106         }
107         return wavelength;
108     }
109
110     //Check the latency
111     private boolean checkLatency(Long maxLatency, GraphPath<String, PceGraphEdge> path) {
112         double latency = 0;
113
114         for (PceGraphEdge edge : path.getEdgeList()) {
115             try {
116                 latency += edge.link().getLatency();
117                 LOG.debug("- In checkLatency: latency of {} = {} units", edge.link().getLinkId().getValue(),latency);
118             } catch (NullPointerException e) {
119                 LOG.warn("- In checkLatency: the link {} does not contain latency field",
120                     edge.link().getLinkId().getValue());
121             }
122         }
123         if (latency > maxLatency) {
124             return false;
125         }
126         return true;
127     }
128
129     //Check the inclusion if it is defined in the hard constraints
130     private boolean checkInclude(GraphPath<String, PceGraphEdge> path, PceConstraints pceHardConstraintsInput) {
131         List<ResourcePair> listToInclude = pceHardConstraintsInput.getListToInclude();
132         if (listToInclude.isEmpty()) {
133             return true;
134         }
135
136         List<PceGraphEdge> pathEdges = path.getEdgeList();
137         LOG.debug(" in checkInclude vertex list: [{}]", path.getVertexList());
138
139         List<String> listOfElementsSubNode = new ArrayList<String>();
140         listOfElementsSubNode.add(pathEdges.get(0).link().getsourceSupNodeId());
141         listOfElementsSubNode.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.NODE,
142             pceHardConstraintsInput));
143
144         List<String> listOfElementsCLLI = new ArrayList<String>();
145         listOfElementsCLLI.add(pathEdges.get(0).link().getsourceCLLI());
146         listOfElementsCLLI.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.CLLI,
147             pceHardConstraintsInput));
148
149         List<String> listOfElementsSRLG = new ArrayList<String>();
150         // first link is XPONDEROUTPUT, no SRLG for it
151         listOfElementsSRLG.add("NONE");
152         listOfElementsSRLG.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.SRLG,
153             pceHardConstraintsInput));
154
155         // validation: check each type for each element
156         for (ResourcePair next : listToInclude) {
157             int indx = -1;
158             switch (next.getType()) {
159                 case NODE:
160                     if (listOfElementsSubNode.contains(next.getName())) {
161                         indx = listOfElementsSubNode.indexOf(next.getName());
162                     }
163                     break;
164                 case SRLG:
165                     if (listOfElementsSRLG.contains(next.getName())) {
166                         indx = listOfElementsSRLG.indexOf(next.getName());
167                     }
168                     break;
169                 case CLLI:
170                     if (listOfElementsCLLI.contains(next.getName())) {
171                         indx = listOfElementsCLLI.indexOf(next.getName());
172                     }
173                     break;
174                 default:
175                     LOG.warn(" in checkInclude vertex list unsupported resource type: [{}]", next.getType());
176             }
177
178             if (indx < 0) {
179                 LOG.debug(" in checkInclude stopped : {} ", next.getName());
180                 return false;
181             }
182
183             LOG.debug(" in checkInclude next found {} in {}", next.getName(), path.getVertexList());
184
185             listOfElementsSubNode.subList(0, indx).clear();
186             listOfElementsCLLI.subList(0, indx).clear();
187             listOfElementsSRLG.subList(0, indx).clear();
188         }
189
190         LOG.info(" in checkInclude passed : {} ", path.getVertexList());
191         return true;
192     }
193
194     private List<String> listOfElementsBuild(List<PceGraphEdge> pathEdges, PceConstraints.ResourceType type,
195         PceConstraints pceHardConstraints) {
196
197         List<String> listOfElements = new ArrayList<String>();
198         for (PceGraphEdge link: pathEdges) {
199             switch (type) {
200                 case NODE:
201                     listOfElements.add(link.link().getdestSupNodeId());
202                     break;
203                 case CLLI:
204                     listOfElements.add(link.link().getdestCLLI());
205                     break;
206                 case SRLG:
207                     if (link.link().getlinkType() != OpenroadmLinkType.ROADMTOROADM) {
208                         listOfElements.add("NONE");
209                         break;
210                     }
211
212                     // srlg of link is List<Long>. But in this algo we need string representation of one SRLG
213                     // this should be any SRLG mentioned in include constraints if any of them if mentioned
214                     boolean found = false;
215                     for (Long srlg : link.link().getsrlgList()) {
216                         String srlgStr = String.valueOf(srlg);
217                         if (pceHardConstraints.getSRLGnames().contains(srlgStr)) {
218                             listOfElements.add(srlgStr);
219                             LOG.info("listOfElementsBuild. FOUND SRLG {} in link {}", srlgStr, link.link().toString());
220                             found = true;
221                             continue;
222                         }
223                     }
224                     if (!found) {
225                         // there is no specific srlg to include. thus add to list just the first one
226                         listOfElements.add("NONE");
227                     }
228                     break;
229                 default:
230                     LOG.debug("listOfElementsBuild unsupported resource type");
231             }
232         }
233         return listOfElements;
234     }
235
236     //Check the path OSNR
237     private boolean checkOSNR(GraphPath<String, PceGraphEdge> path) {
238         double linkOsnrDb;
239         double osnrDb = 0;
240         LOG.info("- In checkOSNR: OSNR of the transmitter = {} dB", TRX_OSNR);
241         LOG.info("- In checkOSNR: add-path incremental OSNR = {} dB", ADD_OSNR);
242         double inverseLocalOsnr = getInverseOsnrLinkLu(TRX_OSNR) + getInverseOsnrLinkLu(ADD_OSNR);
243         for (PceGraphEdge edge : path.getEdgeList()) {
244             if (edge.link().getlinkType() == OpenroadmLinkType.ROADMTOROADM) {
245                 // link OSNR in dB
246                 linkOsnrDb = edge.link().getosnr();
247                 LOG.info("- In checkOSNR: OSNR of {} = {} dB", edge.link().getLinkId().getValue(), linkOsnrDb);
248                 // 1 over the local OSNR, in linear units
249                 inverseLocalOsnr += getInverseOsnrLinkLu(linkOsnrDb);
250             }
251         }
252         try {
253             osnrDb = getOsnrDb(1 / inverseLocalOsnr);
254         }
255         catch (ArithmeticException e) {
256             LOG.debug("In checkOSNR: OSNR is equal to 0 and the number of links is: {}", path.getEdgeList().size());
257             return false;
258         }
259         LOG.info("In checkOSNR: OSNR of the path is {} dB", osnrDb);
260         if ((osnrDb + SYS_MARGIN) < MIN_OSNR_W100G) {
261             return false;
262         }
263         return true;
264     }
265
266     private double getOsnrDb(double osnrLu) {
267         double osnrDb;
268         osnrDb = 10 * Math.log10(osnrLu);
269         return osnrDb;
270     }
271
272     private double getInverseOsnrLinkLu(double linkOsnrDb) {
273         // 1 over the link OSNR, in linear units
274         double linkOsnrLu;
275         linkOsnrLu = Math.pow(10, (linkOsnrDb / 10.0));
276         LOG.debug("In retrieveosnr: the inverse of link osnr is {} (Linear Unit)", linkOsnrLu);
277         return (CONST_OSNR / linkOsnrLu);
278     }
279
280 }