Merge "Fix spotbugs issues in common module"
[transportpce.git] / pce / src / main / java / org / opendaylight / transportpce / pce / networkanalyzer / PceLink.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.networkanalyzer;
10
11 import java.io.IOException;
12 import java.io.ObjectInputStream;
13 import java.io.ObjectOutputStream;
14 import java.io.Serializable;
15 import java.util.List;
16
17 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Link1;
18 import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.span.attributes.LinkConcatenation.FiberType;
19 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.networks.network.link.oms.attributes.Span;
20 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType;
21 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev200129.OtnLinkType;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 public class PceLink implements Serializable {
29
30     private static final long serialVersionUID = 1L;
31     /* Logging. */
32     private static final Logger LOG = LoggerFactory.getLogger(PceLink.class);
33     ///////////////////////// LINKS ////////////////////
34     /*
35      * extension of Link to include constraints and Graph weight
36      */
37     double weight = 0;
38     private boolean isValid = true;
39     private boolean isOtnValid = true;
40
41     // this member is for XPONDER INPUT/OUTPUT links.
42     // it keeps name of client corresponding to NETWORK TP
43     private String client = "";
44     private final LinkId linkId;
45     private final OpenroadmLinkType linkType;
46     private final NodeId sourceId;
47     private final NodeId destId;
48     private transient Object sourceTP;
49     private transient Object destTP;
50     private final String sourceNetworkSupNodeId;
51     private final String destNetworkSupNodeId;
52     private final String sourceCLLI;
53     private final String destCLLI;
54     private final LinkId oppositeLink;
55     private final Long latency;
56     private final Long availableBandwidth;
57     private final Long usedBandwidth;
58     private final List<Long> srlgList;
59     private final double osnr;
60     private final transient Span omsAttributesSpan;
61     private static final double CELERITY = 2.99792458 * 1e5; //meter per ms
62     private static final double NOISE_MASK_A = 0.571429;
63     private static final double NOISE_MASK_B = 39.285714;
64     private static final double UPPER_BOUND_OSNR = 33;
65     private static final double LOWER_BOUND_OSNR = 0.1;
66
67     public PceLink(Link link, PceNode source, PceNode dest) {
68         LOG.info("PceLink: : PceLink start ");
69
70         this.linkId = link.getLinkId();
71
72         this.sourceId = link.getSource().getSourceNode();
73         this.destId = link.getDestination().getDestNode();
74
75         this.sourceTP = link.getSource().getSourceTp();
76         this.destTP = link.getDestination().getDestTp();
77
78         this.sourceNetworkSupNodeId = source.getSupNetworkNodeId();
79         this.destNetworkSupNodeId = dest.getSupNetworkNodeId();
80
81         this.sourceCLLI = source.getSupClliNodeId();
82         this.destCLLI = dest.getSupClliNodeId();
83
84         this.linkType = MapUtils.calcType(link);
85
86         this.oppositeLink = calcOpposite(link);
87
88         if (this.linkType == OpenroadmLinkType.ROADMTOROADM) {
89             this.omsAttributesSpan = MapUtils.getOmsAttributesSpan(link);
90             this.srlgList = MapUtils.getSRLG(link);
91             this.latency = calcLatency(link);
92             this.osnr = calcSpanOSNR();
93             this.availableBandwidth = 0L;
94             this.usedBandwidth = 0L;
95         } else if (this.linkType == OpenroadmLinkType.OTNLINK) {
96             this.availableBandwidth = MapUtils.getAvailableBandwidth(link);
97             this.usedBandwidth = MapUtils.getUsedBandwidth(link);
98             this.srlgList = MapUtils.getSRLGfromLink(link);
99             this.osnr = 0.0;
100             this.latency = 0L;
101             this.omsAttributesSpan = null;
102         } else {
103             this.omsAttributesSpan = null;
104             this.srlgList = null;
105             this.latency = 0L;
106             this.osnr = 100L; //infinite OSNR in DB
107             this.availableBandwidth = 0L;
108             this.usedBandwidth = 0L;
109         }
110         LOG.debug("PceLink: created PceLink  {}", linkId);
111     }
112
113     //Retrieve the opposite link
114     private LinkId calcOpposite(Link link) {
115         LinkId tmpoppositeLink = MapUtils.extractOppositeLink(link);
116         if (tmpoppositeLink == null) {
117             LOG.error("PceLink: Error calcOpposite. Link is ignored {}", link.getLinkId().getValue());
118             isValid = false;
119         }
120         return tmpoppositeLink;
121     }
122
123     //Compute the link latency : if the latency is not defined, the latency is computed from the omsAttributesSpan
124     private Long calcLatency(Link link) {
125         Link1 link1 = null;
126         Long tmplatency;
127         link1 = link.augmentation(Link1.class);
128         if (link1.getLinkLatency() != null) {
129             tmplatency = link1.getLinkLatency().toJava();
130             return tmplatency;
131         }
132
133         try {
134             double tmp = 0;
135             for (int i = 0; i < this.omsAttributesSpan.getLinkConcatenation().size(); i++) {
136                 //Length is expressed in meter and latency is expressed in ms according to OpenROADM MSA
137                 tmp += this.omsAttributesSpan.getLinkConcatenation().get(i).getSRLGLength().toJava() / CELERITY;
138                 LOG.info("In PceLink: The latency of link {} == {}",link.getLinkId(),tmp);
139             }
140             tmplatency = (long) Math.ceil(tmp);
141         } catch (NullPointerException e) {
142             LOG.debug("In PceLink: cannot compute the latency for the link {}",link.getLinkId().getValue());
143             tmplatency = 1L;
144         }
145         return tmplatency;
146     }
147
148     //Compute the OSNR of a span
149     public double calcSpanOSNR() {
150         try {
151             double pout; //power on the output of the previous ROADM (dBm)
152             pout = retrievePower(this.omsAttributesSpan.getLinkConcatenation().get(0).getFiberType());
153             double spanLoss = this.omsAttributesSpan.getSpanlossCurrent().getValue().doubleValue(); // span loss (dB)
154             double pin = pout - spanLoss; //power on the input of the current ROADM (dBm)
155             double spanOsnrDb;
156             spanOsnrDb = NOISE_MASK_A * pin + NOISE_MASK_B;
157             if (spanOsnrDb > UPPER_BOUND_OSNR) {
158                 spanOsnrDb =  UPPER_BOUND_OSNR;
159             } else if (spanOsnrDb < LOWER_BOUND_OSNR) {
160                 spanOsnrDb = LOWER_BOUND_OSNR;
161             }
162             return spanOsnrDb;
163         } catch (NullPointerException e) {
164             LOG.error("in PceLink : Null field in the OmsAttrubtesSpan");
165             return 0L;
166         }
167     }
168
169     private double retrievePower(FiberType fiberType) {
170         double power;
171         switch (fiberType) {
172             case Smf:
173                 power = 2;
174                 break;
175             case Eleaf:
176                 power = 1;
177                 break;
178             case Truewavec:
179                 power = -1;
180                 break;
181             case Oleaf:
182             case Dsf:
183             case Truewave:
184             case NzDsf:
185             case Ull:
186             default:
187                 power = 0;
188                 break;
189         }
190         return power;
191     }
192
193     public LinkId getOppositeLink() {
194         return oppositeLink;
195     }
196
197     public Object getSourceTP() {
198         return sourceTP;
199     }
200
201     public Object getDestTP() {
202         return destTP;
203     }
204
205     public OpenroadmLinkType getlinkType() {
206         return linkType;
207     }
208
209     public LinkId getLinkId() {
210         return linkId;
211     }
212
213     public NodeId getSourceId() {
214         return sourceId;
215     }
216
217     public NodeId getDestId() {
218         return destId;
219     }
220
221     public String getClient() {
222         return client;
223     }
224
225     public void setClient(String client) {
226         this.client = client;
227     }
228
229     // Double for transformer of JUNG graph
230     public Double getLatency() {
231         return latency.doubleValue();
232     }
233
234     public Long getAvailableBandwidth() {
235         return availableBandwidth;
236     }
237
238     public Long getUsedBandwidth() {
239         return usedBandwidth;
240     }
241
242     public String getsourceNetworkSupNodeId() {
243         return sourceNetworkSupNodeId;
244     }
245
246     public String getdestNetworkSupNodeId() {
247         return destNetworkSupNodeId;
248     }
249
250     public List<Long> getsrlgList() {
251         return srlgList;
252     }
253
254     public double getosnr() {
255         return osnr;
256     }
257
258     public String getsourceCLLI() {
259         return sourceCLLI;
260     }
261
262     public String getdestCLLI() {
263         return destCLLI;
264     }
265
266     public boolean isValid() {
267         if ((this.linkId == null) || (this.linkType == null) || (this.oppositeLink == null)) {
268             isValid = false;
269             LOG.error("PceLink: No Link type or opposite link is available. Link is ignored {}", linkId);
270         }
271         if ((this.sourceId == null) || (this.destId == null) || (this.sourceTP == null) || (this.destTP == null)) {
272             isValid = false;
273             LOG.error("PceLink: No Link source or destination is available. Link is ignored {}", linkId);
274         }
275         if ((this.sourceNetworkSupNodeId.equals("")) || (this.destNetworkSupNodeId.equals(""))) {
276             isValid = false;
277             LOG.error("PceLink: No Link source SuppNodeID or destination SuppNodeID is available. Link is ignored {}",
278                 linkId);
279         }
280         if ((this.sourceCLLI.equals("")) || (this.destCLLI.equals(""))) {
281             isValid = false;
282             LOG.error("PceLink: No Link source CLLI or destination CLLI is available. Link is ignored {}", linkId);
283         }
284         if ((this.omsAttributesSpan == null) && (this.linkType == OpenroadmLinkType.ROADMTOROADM)) {
285             isValid = false;
286             LOG.error("PceLink: Error reading Span for OMS link. Link is ignored {}", linkId);
287         }
288         if ((this.srlgList != null) && (this.srlgList.isEmpty())) {
289             isValid = false;
290             LOG.error("PceLink: Empty srlgList for OMS link. Link is ignored {}", linkId);
291         }
292         return isValid;
293     }
294
295     public boolean isOtnValid(Link link, String serviceType) {
296
297         if (this.linkType != OpenroadmLinkType.OTNLINK) {
298             LOG.error("PceLink: Not an OTN link. Link is ignored {}", linkId);
299             return false;
300         }
301
302         OtnLinkType otnLinkType = link
303             .augmentation(org.opendaylight.yang.gen.v1.http.transportpce.topology.rev200129.Link1.class)
304             .getOtnLinkType();
305         if (this.availableBandwidth == 0L) {
306             LOG.error("PceLink: No bandwidth available for OTN Link, link {}  is ignored ", linkId);
307             return false;
308         }
309
310         long neededBW;
311         OtnLinkType neededType = null;
312         switch (serviceType) {
313
314             case "ODU4":
315                 if (this.usedBandwidth != 0L) {
316                     return false;
317                 }
318                 neededBW = 100000L;
319                 neededType = OtnLinkType.OTU4;
320                 break;
321             case "ODU2":
322             case "ODU2e":
323                 neededBW = 12500L;
324                 break;
325             case "ODU0":
326                 neededBW = 1250L;
327                 break;
328             case "ODU1":
329                 neededBW = 2500L;
330                 break;
331             case "10GE":
332                 neededBW = 10000L;
333                 neededType = OtnLinkType.ODTU4;
334                 break;
335             case "1GE":
336                 neededBW = 1000L;
337                 neededType = OtnLinkType.ODTU4;
338                 break;
339             default:
340                 LOG.error("PceLink: isOtnValid Link {} unsupported serviceType {} ", linkId, serviceType);
341                 return false;
342         }
343
344         if ((this.availableBandwidth >= neededBW)
345             && ((neededType == null) || (neededType.equals(otnLinkType)))) {
346             LOG.info("PceLink: Selected Link {} has available bandwidth and is eligible for {} creation ",
347                 linkId, serviceType);
348         }
349
350         if ((this.linkId == null) || (this.linkType == null) || (this.oppositeLink == null)) {
351             LOG.error("PceLink: No Link type or opposite link is available. Link is ignored {}", linkId);
352             return false;
353         }
354         if ((this.sourceId == null) || (this.destId == null) || (this.sourceTP == null) || (this.destTP == null)) {
355             LOG.error("PceLink: No Link source or destination is available. Link is ignored {}", linkId);
356             return false;
357         }
358         if ((this.sourceNetworkSupNodeId.equals("")) || (this.destNetworkSupNodeId.equals(""))) {
359             LOG.error("PceLink: No Link source SuppNodeID or destination SuppNodeID is available. Link is ignored {}",
360                 linkId);
361             return false;
362         }
363         if ((this.sourceCLLI.equals("")) || (this.destCLLI.equals(""))) {
364             LOG.error("PceLink: No Link source CLLI or destination CLLI is available. Link is ignored {}", linkId);
365             return false;
366         }
367
368         return true;
369     }
370
371     @Override
372     public String toString() {
373         return "PceLink type=" + linkType + " ID=" + linkId.getValue() + " latency=" + latency;
374     }
375
376     private void writeObject(ObjectOutputStream out) throws IOException {
377         out.defaultWriteObject();
378         out.writeObject(this.sourceTP);
379         out.writeObject(this.destTP);
380     }
381
382     private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException {
383         in.defaultReadObject();
384         this.sourceTP = in.readObject();
385         this.destTP = in.readObject();
386     }
387 }