2 * Copyright © 2017 AT&T, Inc. 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.networkanalyzer;
11 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 import java.io.Serializable;
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
18 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev220630.OtnLinkType;
19 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Link1;
20 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
21 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
22 import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev211210.span.attributes.LinkConcatenation1;
23 import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev211210.span.attributes.LinkConcatenation1.FiberType;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.link.oms.attributes.Span;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.OpenroadmLinkType;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.link.concatenation.LinkConcatenation;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.link.concatenation.LinkConcatenationKey;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 @SuppressWarnings("serial")
37 value = "SE_NO_SERIALVERSIONID",
38 justification = "https://github.com/rzwitserloot/lombok/wiki/WHY-NOT:-serialVersionUID")
39 public class PceLink implements Serializable {
42 private static final Logger LOG = LoggerFactory.getLogger(PceLink.class);
43 ///////////////////////// LINKS ////////////////////
45 * extension of Link to include constraints and Graph weight
48 private boolean isValid = true;
50 // this member is for XPONDER INPUT/OUTPUT links.
51 // it keeps name of client corresponding to NETWORK TP
52 private String client = "";
53 private final LinkId linkId;
54 private final OpenroadmLinkType linkType;
55 private final NodeId sourceId;
56 private final NodeId destId;
57 private final TpId sourceTP;
58 private final TpId destTP;
59 private final String sourceNetworkSupNodeId;
60 private final String destNetworkSupNodeId;
61 private final String sourceCLLI;
62 private final String destCLLI;
63 private final LinkId oppositeLink;
64 private final AdminStates adminStates;
65 private final State state;
66 private final Long latency;
67 private final Long availableBandwidth;
68 private final Long usedBandwidth;
69 private final List<Long> srlgList;
70 // private final double osnr;
71 private final Double length;
72 private final Double cd;
73 private final Double pmd2;
74 private final Double spanLoss;
75 private final Double powerCorrection;
76 private final transient Span omsAttributesSpan;
78 private static final double GLASSCELERITY = 2.99792458 * 1e5 / 1.5;
79 private static final double PMD_CONSTANT = 0.04;
81 public PceLink(Link link, PceNode source, PceNode dest) {
82 LOG.debug("PceLink: : PceLink start ");
84 this.linkId = link.getLinkId();
86 this.sourceId = link.getSource().getSourceNode();
87 this.destId = link.getDestination().getDestNode();
89 this.sourceTP = link.getSource().getSourceTp();
90 this.destTP = link.getDestination().getDestTp();
92 this.sourceNetworkSupNodeId = source.getSupNetworkNodeId();
93 this.destNetworkSupNodeId = dest.getSupNetworkNodeId();
95 this.sourceCLLI = source.getSupClliNodeId();
96 this.destCLLI = dest.getSupClliNodeId();
98 this.linkType = MapUtils.calcType(link);
100 this.oppositeLink = calcOpposite(link);
102 this.adminStates = link.augmentation(Link1.class).getAdministrativeState();
103 this.state = link.augmentation(Link1.class).getOperationalState();
104 switch (this.linkType) {
106 this.omsAttributesSpan = MapUtils.getOmsAttributesSpan(link);
107 this.length = calcLength(link);
108 this.srlgList = MapUtils.getSRLG(link);
109 this.latency = calcLatency(link);
110 this.availableBandwidth = 0L;
111 this.usedBandwidth = 0L;
112 Map<String, Double> spanLossMap = calcSpanLoss(link);
113 this.spanLoss = spanLossMap.get("SpanLoss");
114 this.powerCorrection = spanLossMap.get("PoutCorrection");
115 Map<String, Double> cdAndPmdMap = calcCDandPMD(link);
116 this.cd = cdAndPmdMap.get("CD");
117 this.pmd2 = cdAndPmdMap.get("PMD2");
120 this.availableBandwidth = MapUtils.getAvailableBandwidth(link);
121 this.usedBandwidth = MapUtils.getUsedBandwidth(link);
122 this.srlgList = MapUtils.getSRLGfromLink(link);
125 this.omsAttributesSpan = null;
127 this.powerCorrection = 0.0;
132 this.omsAttributesSpan = null;
133 this.srlgList = null;
136 this.availableBandwidth = 0L;
137 this.usedBandwidth = 0L;
139 this.powerCorrection = 0.0;
144 LOG.debug("PceLink: created PceLink {}", linkId);
147 //Retrieve the opposite link
148 private LinkId calcOpposite(Link link) {
149 LinkId tmpoppositeLink = MapUtils.extractOppositeLink(link);
150 if (tmpoppositeLink == null) {
151 LOG.error("PceLink: Error calcOpposite. Link is ignored {}", link.getLinkId().getValue());
154 return tmpoppositeLink;
157 //Compute the link latency : if the latency is not defined, the latency is computed from the length
158 private Long calcLatency(Link link) {
159 var augLinkLatency = link.augmentation(Link1.class).getLinkLatency();
160 if (augLinkLatency != null) {
161 return augLinkLatency.toJava();
163 Double linkLength = calcLength(link);
164 if (linkLength == null) {
165 LOG.debug("In PceLink: cannot compute the latency for the link {}", link.getLinkId().getValue());
168 LOG.debug("In PceLink: The latency of link {} is extrapolated from link length and == {}",
169 link.getLinkId(), linkLength / GLASSCELERITY);
170 return (long) Math.ceil(linkLength / GLASSCELERITY);
173 private Double calcLength(Link link) {
174 var augLinkLength = link.augmentation(Link1.class).getLinkLength();
175 if (augLinkLength != null) {
176 return augLinkLength.doubleValue();
178 if (this.omsAttributesSpan == null) {
179 LOG.debug("In PceLink: cannot compute the length for the link {}", link.getLinkId().getValue());
182 double linkLength = 0;
183 Map<LinkConcatenationKey, LinkConcatenation> linkConcatenationMap =
184 this.omsAttributesSpan.nonnullLinkConcatenation();
185 for (Map.Entry<LinkConcatenationKey, LinkConcatenation> entry : linkConcatenationMap.entrySet()) {
186 // Length is expressed in meter according to OpenROADM MSA
187 if (entry == null || entry.getValue() == null || entry.getValue().getSRLGLength() == null) {
188 LOG.debug("In PceLink: cannot compute the length for the link {}", link.getLinkId().getValue());
191 linkLength += entry.getValue().getSRLGLength().doubleValue();
192 LOG.debug("In PceLink: The length of the link {} == {}", link.getLinkId(), linkLength / 1000.0);
194 return linkLength / 1000.0;
197 //Calculate CD and PMD of the link from link length
198 private Map<String, Double> calcCDandPMDfromLength() {
199 return this.length == null
203 "CD", 16.5 * this.length,
204 "PMD2", Math.pow(this.length * PMD_CONSTANT, 2)));
207 //Calculate CD and PMD of the link
208 private Map<String, Double> calcCDandPMD(Link link) {
210 double linkPmd2 = 0.0;
211 if (this.omsAttributesSpan == null) {
212 LOG.debug("In PceLink {} no OMS present, assume G.652 fiber, calculation based on fiber length of {} km",
213 link.getLinkId(), this.length);
214 return calcCDandPMDfromLength();
216 Map<LinkConcatenationKey, LinkConcatenation> linkConcatenationMap =
217 this.omsAttributesSpan.nonnullLinkConcatenation();
218 for (Map.Entry<LinkConcatenationKey, LinkConcatenation> entry : linkConcatenationMap.entrySet()) {
219 // If the link-concatenation list is not populated or partially populated CD &
220 // PMD shall be derived from link-length (expressed in km in OR topology)
221 if (entry == null || entry.getValue() == null || entry.getValue().getSRLGLength() == null
222 || entry.getValue().augmentation(LinkConcatenation1.class).getFiberType() == null) {
223 if (this.length > 0.0) {
224 LOG.debug("In PceLink: no OMS present; cd and PMD for the link {} extrapolated from link length {}"
225 + "assuming SMF fiber type", link.getLinkId().getValue(), this.length);
226 return calcCDandPMDfromLength();
228 // If Link-length upper attributes not present or incorrectly populated, no way
229 // to calculate CD & PMD
230 LOG.error("In PceLink: no Link length declared and no OMS present for the link {}."
231 + " No Way to compute CD and PMD", link.getLinkId().getValue());
234 // SRLG length is expressed in OR topology in meter
235 var entryAug = entry.getValue().augmentation(LinkConcatenation1.class);
236 linkCd += entry.getValue().getSRLGLength().doubleValue() / 1000.0
237 * retrieveCdFromFiberType(entryAug.getFiberType());
238 if (entryAug.getPmd() == null
239 || entryAug.getPmd().getValue().doubleValue() == 0.0
240 || entryAug.getPmd().getValue().toString().isEmpty()) {
241 linkPmd2 += Math.pow(
242 entry.getValue().getSRLGLength().doubleValue() / 1000.0
243 * retrievePmdFromFiberType(entryAug.getFiberType()),
246 linkPmd2 += Math.pow(entryAug.getPmd().getValue().doubleValue(), 2);
249 LOG.debug("In PceLink: The CD and PMD2 of link {} are respectively {} ps and {} ps",
250 link.getLinkId(), linkCd, linkPmd2);
251 return Map.of("CD", linkCd, "PMD2", linkPmd2);
254 // compute default spanLoss and power correction from fiber length
255 // when no OMS attribute defined
256 private Map<String, Double> calcDefaultSpanLoss(Link link) {
257 var augLinkLength = link.augmentation(Link1.class).getLinkLength();
258 if (augLinkLength == null || augLinkLength.doubleValue() == 0) {
259 LOG.error("In PceLink, no link length present or length declared = 0,"
260 + " unable to calculate default span Loss ");
261 return new HashMap<>();
263 long linkLength = augLinkLength.longValue();
264 LOG.warn("In PceLink {}, assume G.652 fiber, calculation "
265 + "based on fiber length of {} km and typical loss of 0.25dB per Km ",
266 link.getLinkId(), linkLength);
267 return new HashMap<>(
269 "SpanLoss", linkLength * 0.25,
270 "PoutCorrection", retrievePower(FiberType.Smf)
274 // Compute the attenuation of a span from OMS attribute
275 private Map<String, Double> calcSpanLoss(Link link) {
276 if (this.omsAttributesSpan == null) {
277 return calcDefaultSpanLoss(link);
279 Collection<LinkConcatenation> linkConcatenationList =
280 this.omsAttributesSpan.nonnullLinkConcatenation().values();
281 if (linkConcatenationList == null) {
282 LOG.error("in PceLink : Null field in the OmsAttrubtesSpan");
283 return calcDefaultSpanLoss(link);
285 Iterator<LinkConcatenation> linkConcatenationiterator = linkConcatenationList.iterator();
286 if (!linkConcatenationiterator.hasNext()) {
287 return calcDefaultSpanLoss(link);
289 // Reference of power to be launched at input of ROADM (dBm)
290 return new HashMap<>(Map.of(
291 "PoutCorrection", retrievePower(
292 linkConcatenationiterator.next().augmentation(LinkConcatenation1.class).getFiberType()) - 2.0,
293 "SpanLoss", this.omsAttributesSpan.getSpanlossCurrent().getValue().doubleValue()));
296 private double retrievePower(FiberType fiberType) {
314 private double retrievePmdFromFiberType(FiberType fiberType) {
315 return fiberType.toString().equalsIgnoreCase("Dsf")
320 private double retrieveCdFromFiberType(FiberType fiberType) {
339 public LinkId getOppositeLink() {
343 public AdminStates getAdminStates() {
347 public State getState() {
351 public TpId getSourceTP() {
355 public TpId getDestTP() {
359 public OpenroadmLinkType getlinkType() {
363 public LinkId getLinkId() {
367 public NodeId getSourceId() {
371 public NodeId getDestId() {
375 public String getClient() {
379 public Double getLength() {
383 public void setClient(String client) {
384 this.client = client;
387 // Double for transformer of JUNG graph
388 public Double getLatency() {
389 return latency.doubleValue();
392 public Long getAvailableBandwidth() {
393 return availableBandwidth;
396 public Long getUsedBandwidth() {
397 return usedBandwidth;
400 public String getsourceNetworkSupNodeId() {
401 return sourceNetworkSupNodeId;
404 public String getdestNetworkSupNodeId() {
405 return destNetworkSupNodeId;
408 public List<Long> getsrlgList() {
412 public String getsourceCLLI() {
416 public String getdestCLLI() {
420 public Double getspanLoss() {
424 public Double getcd() {
428 public Double getpmd2() {
432 public Double getpowerCorrection() {
433 return powerCorrection;
436 public boolean isValid() {
437 if (this.linkId == null || this.linkType == null || this.oppositeLink == null) {
439 LOG.error("PceLink: No Link type or opposite link is available. Link is ignored {}", linkId);
441 isValid = checkParams();
442 if (this.linkType == OpenroadmLinkType.ROADMTOROADM && (this.length == null || this.length == 0.0)) {
443 if (this.omsAttributesSpan == null) {
445 LOG.error("PceLink: Error reading Span for OMS link, and no available generic link information."
446 + " Link is ignored {}", linkId);
447 } else if (this.omsAttributesSpan.getSpanlossCurrent() == null) {
449 LOG.error("PceLink: Error reading Span for OMS link, and no available generic link information."
450 + " Link is ignored {}", linkId);
453 if (this.srlgList != null && this.srlgList.isEmpty()) {
455 LOG.error("PceLink: Empty srlgList for OMS link. Link is ignored {}", linkId);
460 public boolean isOtnValid(Link link, String serviceType) {
462 if (this.linkType != OpenroadmLinkType.OTNLINK) {
463 LOG.error("PceLink: Not an OTN link. Link is ignored {}", linkId);
467 if (this.availableBandwidth == 0L) {
468 LOG.error("PceLink: No bandwidth available for OTN Link, link {} is ignored ", linkId);
473 OtnLinkType neededType = null;
474 switch (serviceType) {
476 if (this.usedBandwidth != 0L) {
480 // Add intermediate rate otn-link-type
481 neededType = OtnLinkType.OTUC2;
484 if (this.usedBandwidth != 0L) {
488 // change otn-link-type
489 neededType = OtnLinkType.OTUC3;
492 if (this.usedBandwidth != 0L) {
496 neededType = OtnLinkType.OTUC4;
500 if (this.usedBandwidth != 0L) {
504 neededType = OtnLinkType.OTU4;
518 // TODO: Here link type needs to be changed, based on the line-rate
519 neededType = OtnLinkType.ODUC4;
523 neededType = OtnLinkType.ODTU4;
527 neededType = OtnLinkType.ODTU4;
530 LOG.error("PceLink: isOtnValid Link {} unsupported serviceType {} ", linkId, serviceType);
533 if (this.availableBandwidth >= neededBW
534 && (neededType == null
535 || neededType.equals(
537 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev220630
539 .getOtnLinkType()))) {
540 LOG.debug("PceLink: Selected Link {} has available bandwidth and is eligible for {} creation ",
541 linkId, serviceType);
543 return checkParams();
546 private boolean checkParams() {
547 if (this.linkId == null || this.linkType == null || this.oppositeLink == null) {
548 LOG.error("PceLink: No Link type or opposite link is available. Link is ignored {}", linkId);
551 if (this.adminStates == null || this.state == null) {
552 LOG.error("PceLink: Link is not available. Link is ignored {}", linkId);
555 if (this.sourceId == null || this.destId == null || this.sourceTP == null || this.destTP == null) {
556 LOG.error("PceLink: No Link source or destination is available. Link is ignored {}", linkId);
559 if (this.sourceNetworkSupNodeId.equals("") || this.destNetworkSupNodeId.equals("")) {
560 LOG.error("PceLink: No Link source SuppNodeID or destination SuppNodeID is available. Link is ignored {}",
564 if (this.sourceCLLI.equals("") || this.destCLLI.equals("")) {
565 LOG.error("PceLink: No Link source CLLI or destination CLLI is available. Link is ignored {}", linkId);
573 public String toString() {
574 return "PceLink type=" + linkType + " ID=" + linkId.getValue() + " latency=" + latency;