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