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 java.io.Serializable;
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.Iterator;
15 import java.util.List;
17 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev220630.OtnLinkType;
18 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Link1;
19 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
20 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
21 import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev211210.span.attributes.LinkConcatenation1;
22 import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev211210.span.attributes.LinkConcatenation1.FiberType;
23 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.link.oms.attributes.Span;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.OpenroadmLinkType;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.link.concatenation.LinkConcatenation;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.link.concatenation.LinkConcatenationKey;
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.TpId;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 @SuppressWarnings("serial")
35 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
36 value = "SE_NO_SERIALVERSIONID",
37 justification = "https://github.com/rzwitserloot/lombok/wiki/WHY-NOT:-serialVersionUID")
38 public class PceLink implements Serializable {
41 private static final Logger LOG = LoggerFactory.getLogger(PceLink.class);
42 ///////////////////////// LINKS ////////////////////
44 * extension of Link to include constraints and Graph weight
47 private boolean isValid = true;
49 // this member is for XPONDER INPUT/OUTPUT links.
50 // it keeps name of client corresponding to NETWORK TP
51 private String client = "";
52 private final LinkId linkId;
53 private final OpenroadmLinkType linkType;
54 private final NodeId sourceId;
55 private final NodeId destId;
56 private final TpId sourceTP;
57 private final TpId destTP;
58 private final String sourceNetworkSupNodeId;
59 private final String destNetworkSupNodeId;
60 private final String sourceCLLI;
61 private final String destCLLI;
62 private final LinkId oppositeLink;
63 private final AdminStates adminStates;
64 private final State state;
65 private final Long latency;
66 private final Long availableBandwidth;
67 private final Long usedBandwidth;
68 private final List<Long> srlgList;
69 // private final double osnr;
70 private final Double length;
71 private final Double cd;
72 private final Double pmd2;
73 private final Double spanLoss;
74 private final Double powerCorrection;
75 private final transient Span omsAttributesSpan;
77 private static final double GLASSCELERITY = 2.99792458 * 1e5 / 1.5;
78 private static final double PMD_CONSTANT = 0.04;
80 public PceLink(Link link, PceNode source, PceNode dest) {
81 LOG.debug("PceLink: : PceLink start ");
83 this.linkId = link.getLinkId();
85 this.sourceId = link.getSource().getSourceNode();
86 this.destId = link.getDestination().getDestNode();
88 this.sourceTP = link.getSource().getSourceTp();
89 this.destTP = link.getDestination().getDestTp();
91 this.sourceNetworkSupNodeId = source.getSupNetworkNodeId();
92 this.destNetworkSupNodeId = dest.getSupNetworkNodeId();
94 this.sourceCLLI = source.getSupClliNodeId();
95 this.destCLLI = dest.getSupClliNodeId();
97 this.linkType = MapUtils.calcType(link);
99 this.oppositeLink = calcOpposite(link);
101 this.adminStates = link.augmentation(Link1.class).getAdministrativeState();
102 this.state = link.augmentation(Link1.class).getOperationalState();
103 switch (this.linkType) {
105 this.omsAttributesSpan = MapUtils.getOmsAttributesSpan(link);
106 this.length = calcLength(link);
107 this.srlgList = MapUtils.getSRLG(link);
108 this.latency = calcLatency(link);
109 this.availableBandwidth = 0L;
110 this.usedBandwidth = 0L;
111 Map<String, Double> spanLossMap = calcSpanLoss(link);
112 this.spanLoss = spanLossMap.get("SpanLoss");
113 this.powerCorrection = spanLossMap.get("PoutCorrection");
114 Map<String, Double> cdAndPmdMap = calcCDandPMD(link);
115 this.cd = cdAndPmdMap.get("CD");
116 this.pmd2 = cdAndPmdMap.get("PMD2");
119 this.availableBandwidth = MapUtils.getAvailableBandwidth(link);
120 this.usedBandwidth = MapUtils.getUsedBandwidth(link);
121 this.srlgList = MapUtils.getSRLGfromLink(link);
124 this.omsAttributesSpan = null;
126 this.powerCorrection = 0.0;
131 this.omsAttributesSpan = null;
132 this.srlgList = null;
135 this.availableBandwidth = 0L;
136 this.usedBandwidth = 0L;
138 this.powerCorrection = 0.0;
143 LOG.debug("PceLink: created PceLink {}", linkId);
146 //Retrieve the opposite link
147 private LinkId calcOpposite(Link link) {
148 LinkId tmpoppositeLink = MapUtils.extractOppositeLink(link);
149 if (tmpoppositeLink == null) {
150 LOG.error("PceLink: Error calcOpposite. Link is ignored {}", link.getLinkId().getValue());
153 return tmpoppositeLink;
156 //Compute the link latency : if the latency is not defined, the latency is computed from the length
157 private Long calcLatency(Link link) {
158 var augLinkLatency = link.augmentation(Link1.class).getLinkLatency();
159 if (augLinkLatency != null) {
160 return augLinkLatency.toJava();
162 Double linkLength = calcLength(link);
163 if (linkLength == null) {
164 LOG.debug("In PceLink: cannot compute the latency for the link {}", link.getLinkId().getValue());
167 LOG.debug("In PceLink: The latency of link {} is extrapolated from link length and == {}",
168 link.getLinkId(), linkLength / GLASSCELERITY);
169 return (long) Math.ceil(linkLength / GLASSCELERITY);
172 private Double calcLength(Link link) {
173 var augLinkLength = link.augmentation(Link1.class).getLinkLength();
174 if (augLinkLength != null) {
175 return augLinkLength.doubleValue();
177 if (this.omsAttributesSpan == null) {
178 LOG.debug("In PceLink: cannot compute the length for the link {}", link.getLinkId().getValue());
181 double linkLength = 0;
182 Map<LinkConcatenationKey, LinkConcatenation> linkConcatenationMap =
183 this.omsAttributesSpan.nonnullLinkConcatenation();
184 for (Map.Entry<LinkConcatenationKey, LinkConcatenation> entry : linkConcatenationMap.entrySet()) {
185 // Length is expressed in meter according to OpenROADM MSA
186 if (entry == null || entry.getValue() == null || entry.getValue().getSRLGLength() == null) {
187 LOG.debug("In PceLink: cannot compute the length for the link {}", link.getLinkId().getValue());
190 linkLength += entry.getValue().getSRLGLength().doubleValue();
191 LOG.debug("In PceLink: The length of the link {} == {}", link.getLinkId(), linkLength / 1000.0);
193 return linkLength / 1000.0;
196 //Calculate CD and PMD of the link from link length
197 private Map<String, Double> calcCDandPMDfromLength() {
198 return this.length == null
202 "CD", 16.5 * this.length,
203 "PMD2", Math.pow(this.length * PMD_CONSTANT, 2)));
206 //Calculate CD and PMD of the link
207 private Map<String, Double> calcCDandPMD(Link link) {
209 double linkPmd2 = 0.0;
210 if (this.omsAttributesSpan == null) {
211 LOG.debug("In PceLink {} no OMS present, assume G.652 fiber, calculation based on fiber length of {} km",
212 link.getLinkId(), this.length);
213 return calcCDandPMDfromLength();
215 Map<LinkConcatenationKey, LinkConcatenation> linkConcatenationMap =
216 this.omsAttributesSpan.nonnullLinkConcatenation();
217 for (Map.Entry<LinkConcatenationKey, LinkConcatenation> entry : linkConcatenationMap.entrySet()) {
218 // If the link-concatenation list is not populated or partially populated CD &
219 // PMD shall be derived from link-length (expressed in km in OR topology)
220 if (entry == null || entry.getValue() == null || entry.getValue().getSRLGLength() == null
221 || entry.getValue().augmentation(LinkConcatenation1.class).getFiberType() == null) {
222 if (this.length > 0.0) {
223 LOG.debug("In PceLink: no OMS present; cd and PMD for the link {} extrapolated from link length {}"
224 + "assuming SMF fiber type", link.getLinkId().getValue(), this.length);
225 return calcCDandPMDfromLength();
227 // If Link-length upper attributes not present or incorrectly populated, no way
228 // to calculate CD & PMD
229 LOG.error("In PceLink: no Link length declared and no OMS present for the link {}."
230 + " No Way to compute CD and PMD", link.getLinkId().getValue());
233 // SRLG length is expressed in OR topology in meter
234 var entryAug = entry.getValue().augmentation(LinkConcatenation1.class);
235 linkCd += entry.getValue().getSRLGLength().doubleValue() / 1000.0
236 * retrieveCdFromFiberType(entryAug.getFiberType());
237 if (entryAug.getPmd() == null
238 || entryAug.getPmd().getValue().doubleValue() == 0.0
239 || entryAug.getPmd().getValue().toString().isEmpty()) {
240 linkPmd2 += Math.pow(
241 entry.getValue().getSRLGLength().doubleValue() / 1000.0
242 * retrievePmdFromFiberType(entryAug.getFiberType()),
245 linkPmd2 += Math.pow(entryAug.getPmd().getValue().doubleValue(), 2);
248 LOG.debug("In PceLink: The CD and PMD2 of link {} are respectively {} ps and {} ps",
249 link.getLinkId(), linkCd, linkPmd2);
250 return Map.of("CD", linkCd, "PMD2", linkPmd2);
253 // compute default spanLoss and power correction from fiber length
254 // when no OMS attribute defined
255 private Map<String, Double> calcDefaultSpanLoss(Link link) {
256 var augLinkLength = link.augmentation(Link1.class).getLinkLength();
257 if (augLinkLength == null || augLinkLength.doubleValue() == 0) {
258 LOG.error("In PceLink, no link length present or length declared = 0,"
259 + " unable to calculate default span Loss ");
260 return new HashMap<>();
262 long linkLength = augLinkLength.longValue();
263 LOG.warn("In PceLink {}, assume G.652 fiber, calculation "
264 + "based on fiber length of {} km and typical loss of 0.25dB per Km ",
265 link.getLinkId(), linkLength);
266 return new HashMap<>(
268 "SpanLoss", linkLength * 0.25,
269 "PoutCorrection", retrievePower(FiberType.Smf)
273 // Compute the attenuation of a span from OMS attribute
274 private Map<String, Double> calcSpanLoss(Link link) {
275 if (this.omsAttributesSpan == null) {
276 return calcDefaultSpanLoss(link);
278 Collection<LinkConcatenation> linkConcatenationList =
279 this.omsAttributesSpan.nonnullLinkConcatenation().values();
280 if (linkConcatenationList == null) {
281 LOG.error("in PceLink : Null field in the OmsAttrubtesSpan");
282 return calcDefaultSpanLoss(link);
284 Iterator<LinkConcatenation> linkConcatenationiterator = linkConcatenationList.iterator();
285 if (!linkConcatenationiterator.hasNext()) {
286 return calcDefaultSpanLoss(link);
288 // Reference of power to be launched at input of ROADM (dBm)
289 return new HashMap<>(Map.of(
290 "PoutCorrection", retrievePower(
291 linkConcatenationiterator.next().augmentation(LinkConcatenation1.class).getFiberType()) - 2.0,
292 "SpanLoss", this.omsAttributesSpan.getSpanlossCurrent().getValue().doubleValue()));
295 private double retrievePower(FiberType fiberType) {
313 private double retrievePmdFromFiberType(FiberType fiberType) {
314 return fiberType.toString().equalsIgnoreCase("Dsf")
319 private double retrieveCdFromFiberType(FiberType fiberType) {
338 public LinkId getOppositeLink() {
342 public AdminStates getAdminStates() {
346 public State getState() {
350 public TpId getSourceTP() {
354 public TpId getDestTP() {
358 public OpenroadmLinkType getlinkType() {
362 public LinkId getLinkId() {
366 public NodeId getSourceId() {
370 public NodeId getDestId() {
374 public String getClient() {
378 public Double getLength() {
382 public void setClient(String client) {
383 this.client = client;
386 // Double for transformer of JUNG graph
387 public Double getLatency() {
388 return latency.doubleValue();
391 public Long getAvailableBandwidth() {
392 return availableBandwidth;
395 public Long getUsedBandwidth() {
396 return usedBandwidth;
399 public String getsourceNetworkSupNodeId() {
400 return sourceNetworkSupNodeId;
403 public String getdestNetworkSupNodeId() {
404 return destNetworkSupNodeId;
407 public List<Long> getsrlgList() {
411 public String getsourceCLLI() {
415 public String getdestCLLI() {
419 public Double getspanLoss() {
423 public Double getcd() {
427 public Double getpmd2() {
431 public Double getpowerCorrection() {
432 return powerCorrection;
435 public boolean isValid() {
436 if (this.linkId == null || this.linkType == null || this.oppositeLink == null) {
438 LOG.error("PceLink: No Link type or opposite link is available. Link is ignored {}", linkId);
440 isValid = checkParams();
441 if (this.linkType == OpenroadmLinkType.ROADMTOROADM && (this.length == null || this.length == 0.0)) {
442 if (this.omsAttributesSpan == null) {
444 LOG.error("PceLink: Error reading Span for OMS link, and no available generic link information."
445 + " Link is ignored {}", linkId);
446 } else if (this.omsAttributesSpan.getSpanlossCurrent() == null) {
448 LOG.error("PceLink: Error reading Span for OMS link, and no available generic link information."
449 + " Link is ignored {}", linkId);
452 if (this.srlgList != null && this.srlgList.isEmpty()) {
454 LOG.error("PceLink: Empty srlgList for OMS link. Link is ignored {}", linkId);
459 public boolean isOtnValid(Link link, String serviceType) {
461 if (this.linkType != OpenroadmLinkType.OTNLINK) {
462 LOG.error("PceLink: Not an OTN link. Link is ignored {}", linkId);
466 if (this.availableBandwidth == 0L) {
467 LOG.error("PceLink: No bandwidth available for OTN Link, link {} is ignored ", linkId);
472 OtnLinkType neededType = null;
473 switch (serviceType) {
475 if (this.usedBandwidth != 0L) {
479 // Add intermediate rate otn-link-type
480 neededType = OtnLinkType.OTUC2;
483 if (this.usedBandwidth != 0L) {
487 // change otn-link-type
488 neededType = OtnLinkType.OTUC3;
491 if (this.usedBandwidth != 0L) {
495 neededType = OtnLinkType.OTUC4;
499 if (this.usedBandwidth != 0L) {
503 neededType = OtnLinkType.OTU4;
517 // TODO: Here link type needs to be changed, based on the line-rate
518 neededType = OtnLinkType.ODUC4;
522 neededType = OtnLinkType.ODTU4;
526 neededType = OtnLinkType.ODTU4;
529 LOG.error("PceLink: isOtnValid Link {} unsupported serviceType {} ", linkId, serviceType);
532 if (this.availableBandwidth >= neededBW
533 && (neededType == null
534 || neededType.equals(
536 org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkutils.rev220630
538 .getOtnLinkType()))) {
539 LOG.debug("PceLink: Selected Link {} has available bandwidth and is eligible for {} creation ",
540 linkId, serviceType);
542 return checkParams();
545 private boolean checkParams() {
546 if (this.linkId == null || this.linkType == null || this.oppositeLink == null) {
547 LOG.error("PceLink: No Link type or opposite link is available. Link is ignored {}", linkId);
550 if (this.adminStates == null || this.state == null) {
551 LOG.error("PceLink: Link is not available. Link is ignored {}", linkId);
554 if (this.sourceId == null || this.destId == null || this.sourceTP == null || this.destTP == null) {
555 LOG.error("PceLink: No Link source or destination is available. Link is ignored {}", linkId);
558 if (this.sourceNetworkSupNodeId.equals("") || this.destNetworkSupNodeId.equals("")) {
559 LOG.error("PceLink: No Link source SuppNodeID or destination SuppNodeID is available. Link is ignored {}",
563 if (this.sourceCLLI.equals("") || this.destCLLI.equals("")) {
564 LOG.error("PceLink: No Link source CLLI or destination CLLI is available. Link is ignored {}", linkId);
572 public String toString() {
573 return "PceLink type=" + linkType + " ID=" + linkId.getValue() + " latency=" + latency;