2 * Copyright © 2019 Orange, 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.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
15 //import java.util.Optional;
16 import java.util.TreeMap;
18 //import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.transportpce.common.NetworkUtils;
20 //import org.opendaylight.transportpce.pce.SortPortsByName;
21 //import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.Node1;
22 //import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.TerminationPoint1;
23 //import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.networks
24 //.network.node.termination.point.pp.attributes.UsedWavelength;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev181130.xpdr.odu.switching.pools.OduSwitchingPools;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev181130.xpdr.odu.switching.pools.odu.switching.pools.NonBlockingList;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmNodeType;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmTpType;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.xpdr.tp.supported.interfaces.SupportedInterfaceCapability;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev181130.ODTU4TsAllocated;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.TerminationPoint1;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.networks.network.node.SwitchingPools;
33 //import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev181130.If100GEODU4;
34 //import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev181130.If10GEODU2e;
35 //import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev181130.If1GEODU0;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.xponder.rev181130.xpdr.otn.tp.attributes.OdtuTpnPool;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 public class PceOtnNode extends PceNode {
45 private static final Logger LOG = LoggerFactory.getLogger(PceCalculation.class);
46 ////////////////////////// OTN NODES ///////////////////////////
48 * For This Class the node passed shall be at the otn-openroadm Layer
51 private boolean valid = true;
53 private final String supNetworkNodeId;
54 private final String supTopoNodeId;
55 private final String clli;
56 private final String otnServiceType;
58 private Map<String, List<Integer>> tpAvailableTribPort = new TreeMap<String, List<Integer>>();
59 private Map<String, List<Integer>> tpAvailableTribSlot = new TreeMap<String, List<Integer>>();
60 private Map<String, OpenroadmTpType> availableXponderTp = new TreeMap<String, OpenroadmTpType>();
61 private List<String> usedXpdrNWTps = new ArrayList<String>();
62 private List<String> unusableXpdrNWTps = new ArrayList<String>();
63 private List<String> usedXpdrClientTps = new ArrayList<String>();
64 private List<String> unusableXpdrClientTps = new ArrayList<String>();
65 private List<PceLink> outgoingLinks = new ArrayList<PceLink>();
66 private Map<String, String> clientPerNwTp = new HashMap<String, String>();
68 public PceOtnNode(Node node, OpenroadmNodeType nodeType, NodeId nodeId, String serviceType) {
69 super(node, nodeType, nodeId);
70 this.supNetworkNodeId = getNetworkSupNodeId(node);
71 this.supTopoNodeId = getTopoSupNodeId(node);
72 this.clli = getClliSupNodeId(node);
73 this.otnServiceType = serviceType;
74 this.tpAvailableTribPort.clear();
75 this.tpAvailableTribSlot.clear();
76 this.usedXpdrNWTps.clear();
77 this.unusableXpdrNWTps.clear();
78 this.usedXpdrClientTps.clear();
79 this.unusableXpdrClientTps.clear();
81 if ((node == null) || (nodeId == null) || (nodeType == null)) {
82 LOG.error("PceOtnNode: one of parameters is not populated : nodeId, node type");
87 public void initXndrTps(String mode) {
88 LOG.info("initXndrTps for node : {}", this.nodeId);
89 int availableNetworkTpNumber = 0;
90 int availableClientTpNumber = 0;
92 this.availableXponderTp.clear();
97 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1 nodeTp =
98 this.node.augmentation(
99 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1.class);
100 List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
101 .network.node.TerminationPoint> allTps = nodeTp.getTerminationPoint();
103 if (allTps == null) {
104 LOG.error("initXndrTps: XPONDER TerminationPoint list is empty for node {}", this.toString());
108 for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
109 .network.node.TerminationPoint tp : allTps) {
110 TerminationPoint1 otnTp1 = tp.augmentation(TerminationPoint1.class);
111 //TODO many nested if-structures below, this needs to be reworked
112 if (otnTp1.getTpType() == OpenroadmTpType.XPONDERNETWORK) {
113 if (otnTp1.getXpdrTpPortConnectionAttributes().getWavelength() != null) {
114 this.usedXpdrNWTps.add(tp.getTpId().getValue());
116 // find server of this network TP
117 String server = otnTp1.getXpdrTpPortConnectionAttributes().getTailEquipmentId();
118 if ((server.equals("")) || (server == null)) {
119 this.unusableXpdrNWTps.add(tp.getTpId().getValue());
121 // tp is not used and as a tail to server WDM layer
122 if (("10GE".equals(this.otnServiceType)) || ("1GE".equals(this.otnServiceType))) {
123 // LO-ODU needs to be created on a parent HO-ODU
125 List<OdtuTpnPool> presenceOdtu =
126 otnTp1.getXpdrTpPortConnectionAttributes().getOdtuTpnPool();
127 if (presenceOdtu == null) {
128 this.unusableXpdrNWTps.add(tp.getTpId().getValue());
130 List<SupportedInterfaceCapability> sic =
131 otnTp1.getTpSupportedInterfaces().getSupportedInterfaceCapability();
132 if ((findNetworkCompliantInterface(sic)) & (checkAvailableTribPort(tp))
133 & (checkAvailableTribSlot(tp))) {
134 this.availableXponderTp.put(tp.getTpId().getValue(),
135 OpenroadmTpType.XPONDERNETWORK);
136 availableNetworkTpNumber++;
139 * Add the retrieval of outgoing ingoing links
140 * through an external function
144 // service is HO service
145 List<SupportedInterfaceCapability> sic =
146 otnTp1.getTpSupportedInterfaces().getSupportedInterfaceCapability();
147 if (findNetworkCompliantInterface(sic)) {
148 this.availableXponderTp.put(tp.getTpId().getValue(), OpenroadmTpType.XPONDERNETWORK);
149 availableNetworkTpNumber++;
151 * Add the retrieval of outgoing ingoing links
152 * through an external function
155 this.unusableXpdrNWTps.add(tp.getTpId().getValue());
165 // The port is not a network port
166 } else if (otnTp1.getTpType() == OpenroadmTpType.XPONDERCLIENT) {
167 // For Client port we verify that it supports needed interfaces
168 // TBD : How shall we check a client port is available and not
170 List<SupportedInterfaceCapability> sic =
171 otnTp1.getTpSupportedInterfaces().getSupportedInterfaceCapability();
172 if (findClientCompliantInterface(sic)) {
173 this.availableXponderTp.put(tp.getTpId().getValue(), OpenroadmTpType.XPONDERCLIENT);
174 availableClientTpNumber++;
177 LOG.debug("initXndrTps: XPONDER tp = {} is used", tp.getTpId().getValue());
178 LOG.error("initXndrTps: XPONDER {} NW TP doesn't have defined server ROADM SRG {}", this.toString(), tp
179 .getTpId().getValue());
181 if ("AZ".equals(mode)) {
182 if ((availableClientTpNumber >= 1) || (availableNetworkTpNumber >= 1)) {
183 // for A and Z node we need to have one valid client port & one
184 // valid network port
187 } else if ("intermediate".equals(mode)) {
188 if ((availableNetworkTpNumber >= 2)) {
189 // for OTN switching node used in transit we need to have two
190 // valid network ports
196 LOG.debug("initXndrTps: XPONDER doesn't have the required ports available {}", this.toString());
199 LOG.debug("initXndrTps: XPONDER {} is elligible", this.toString());
203 private Boolean findClientCompliantInterface(List<SupportedInterfaceCapability> sic) {
204 boolean compliant = false;
205 for (SupportedInterfaceCapability sit : sic) {
206 String interfacetype = sit.getIfCapType().toString();
207 switch (interfacetype) {
210 if ("1GE".equals(this.otnServiceType)) {
216 if ("10GE".equals(this.otnServiceType)) {
222 if ("100GE".equals(this.otnServiceType)) {
227 case "IfOCHOTU4ODU4":
228 if (("OTU4".equals(this.otnServiceType)) || ("ODU4".equals(this.otnServiceType))) {
241 private Boolean findNetworkCompliantInterface(List<SupportedInterfaceCapability> sic) {
242 boolean compliant = false;
243 for (SupportedInterfaceCapability sit : sic) {
244 String interfacetype = sit.getIfCapType().toString();
245 switch (interfacetype) {
247 case "IfOCHOTU4ODU4":
251 case "IfOCHOTU2ODU2":
252 if (("1GE".equals(this.otnServiceType)) || ("10GE".equals(this.otnServiceType))) {
256 // add all use case with higher rate interfaces when it shows up
266 private String getClliSupNodeId(Node inputNode) {
267 TreeMap<String, String> allSupNodes = new TreeMap<String, String>();
268 String tempNetworkSupNodeId = "";
269 allSupNodes = MapUtils.getAllSupNode(inputNode);
270 if (allSupNodes.get(NetworkUtils.CLLI_NETWORK_ID) == null) {
271 LOG.error("getClliSupNodeId: No Supporting node at CLLI layer for node: [{}].", inputNode.getNodeId());
273 tempNetworkSupNodeId = allSupNodes.get(NetworkUtils.CLLI_NETWORK_ID);
275 return tempNetworkSupNodeId;
278 private String getNetworkSupNodeId(Node inputNode) {
279 TreeMap<String, String> allSupNodes = new TreeMap<String, String>();
280 String tempNetworkSupNodeId = "";
281 allSupNodes = MapUtils.getAllSupNode(inputNode);
282 if (allSupNodes.get(NetworkUtils.UNDERLAY_NETWORK_ID) == null) {
284 "getNetworkSupNodeId: No Supporting node at NETWORK layer for node: [{}].", inputNode.getNodeId());
286 tempNetworkSupNodeId = allSupNodes.get(NetworkUtils.UNDERLAY_NETWORK_ID);
288 return tempNetworkSupNodeId;
291 private String getTopoSupNodeId(Node inputNode) {
292 TreeMap<String, String> allSupNodes = new TreeMap<String, String>();
293 String tempTopoSupNodeId = "";
294 allSupNodes = MapUtils.getAllSupNode(inputNode);
295 if (allSupNodes.get(NetworkUtils.OVERLAY_NETWORK_ID) == null) {
297 "getTopologySupNodeId: No Supporting node at TOPOLOGY layer for node: [{}].", inputNode.getNodeId());
299 tempTopoSupNodeId = allSupNodes.get(NetworkUtils.OVERLAY_NETWORK_ID);
301 return tempTopoSupNodeId;
304 public void validateAZxponder(String anodeId, String znodeId) {
308 if ((this.nodeType != OpenroadmNodeType.MUXPDR) & (this.nodeType != OpenroadmNodeType.SWITCH)
309 & (this.nodeType != OpenroadmNodeType.TPDR)) {
312 // Detect A and Z, a/znodeId correspond to otn layer, supporting node
313 // might be of Network or Topology layer
314 if (this.nodeId.equals(anodeId) || (this.nodeId.equals(znodeId))) {
317 LOG.debug("validateAZxponder: XPONDER unusable for A or Z == {}", nodeId.getValue());
319 LOG.info("validateAZxponder: A or Z node detected and validated == {}", nodeId.getValue());
323 LOG.debug("validateAZxponder: XPONDER is ignored == {}", nodeId.getValue());
329 public boolean validateSwitchingPoolBandwidth(
331 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
332 .network.node.TerminationPoint tp1,
333 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
334 .network.node.TerminationPoint tp2,
336 Long availableBW = 0L;
337 if (this.nodeType != OpenroadmNodeType.TPDR) {
340 org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.Node1 node1 =
342 org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.Node1.class);
343 SwitchingPools sp = node1.getSwitchingPools();
344 List<OduSwitchingPools> osp = new ArrayList<OduSwitchingPools>();
345 osp = sp.getOduSwitchingPools();
346 for (OduSwitchingPools ospx : osp) {
347 List<NonBlockingList> nbl = ospx.getNonBlockingList();
348 for (NonBlockingList nbll : nbl) {
349 if (nbll.getAvailableInterconnectBandwidth() >= neededBW) {
350 List<TpId> tplist = new ArrayList<TpId>(nbll.getTpList());
351 if ((tplist.contains(tp1.getTpId())) & (tplist.contains(tp2.getTpId()))) {
352 LOG.debug("validateSwitchingPoolBandwidth: couple of tp {} x {} valid for crossconnection",
353 tp1.getTpId().toString(), tp2.getTpId().toString());
360 LOG.debug("validateSwitchingPoolBandwidth: No valid Switching pool for crossconnecting tp {} and {}",
361 tp1.getTpId().toString(), tp2.getTpId().toString());
367 public void validateIntermediateSwitch() {
371 if (this.nodeType != OpenroadmNodeType.SWITCH) {
374 // Validate switch for use as an intermediate XPONDER on the path
375 initXndrTps("intermediate");
377 LOG.debug("validateIntermediateSwitch: Switch unusable for transit == {}", nodeId.getValue());
379 LOG.info("validateIntermediateSwitch: Switch usable for transit == {}", nodeId.getValue());
385 public boolean checkAvailableTribPort(
386 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
387 .network.node.TerminationPoint tp) {
388 boolean compatibleSupInt = false;
389 TerminationPoint1 otnTp1 = tp.augmentation(TerminationPoint1.class);
390 if (otnTp1.getTpType() == OpenroadmTpType.XPONDERNETWORK) {
392 List<OdtuTpnPool> otpp = otnTp1.getXpdrTpPortConnectionAttributes().getOdtuTpnPool();
394 for (OdtuTpnPool otppi : otpp) {
395 if (otppi.getOdtuType().getClass().equals(ODTU4TsAllocated.class)) {
396 this.tpAvailableTribPort.put(tp.getTpId().getValue(), otppi.getTpnPool());
397 LOG.debug("checkAvailableTribPort: tp {} and his trib Ports have been added to "
398 + "tpAvailableTribPortMap", tp.getTpId().getValue());
399 compatibleSupInt = true;
403 } catch (NullPointerException e) {
404 LOG.debug("checkAvailableTribPort: OdtuTpnPool not present for tp {} ", tp.getTpId().toString());
408 LOG.debug("checkAvailableTribPort: tp {} has no odtu tpn Pool", tp.getTpId().getValue());
410 return compatibleSupInt;
413 public boolean checkAvailableTribSlot(
414 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
415 .network.node.TerminationPoint tp) {
416 boolean compatibleSupInt = false;
417 TerminationPoint1 otnTp1 = tp.augmentation(TerminationPoint1.class);
418 if (otnTp1.getTpType() == OpenroadmTpType.XPONDERNETWORK) {
419 List<OdtuTpnPool> otpp;
421 otpp = otnTp1.getXpdrTpPortConnectionAttributes().getOdtuTpnPool();
423 for (OdtuTpnPool otppi : otpp) {
424 if (otppi.getOdtuType().getClass().equals(ODTU4TsAllocated.class)) {
425 this.tpAvailableTribSlot.put(
426 tp.getTpId().getValue(),
427 otnTp1.getXpdrTpPortConnectionAttributes().getTsPool());
429 "checkAvailableTribPort: tp {} and its trib Slots were added to tpAvailableTribSlotMap",
430 tp.getTpId().getValue());
431 compatibleSupInt = true;
436 } catch (NullPointerException e) {
437 LOG.debug("checkAvailableTribSlot: OdtuTpnPool not present for tp {} ", tp.getTpId().toString());
440 LOG.debug("checkAvailableTribPort: tp {} is not a network Port", tp.getTpId().getValue());
442 return compatibleSupInt;
445 public String getXpdrClient(String tp) {
446 return this.clientPerNwTp.get(tp);
449 public boolean checkTP(String tp) {
450 return !((this.usedXpdrNWTps.contains(tp)) || (this.usedXpdrClientTps.contains(tp))
451 || (this.unusableXpdrNWTps.contains(tp)) || (this.unusableXpdrClientTps.contains(tp)));
454 public boolean isValid() {
455 if ((node == null) || (nodeId == null) || (nodeType == null) || (supNetworkNodeId == null) || (clli == null)) {
456 LOG.error("PceNode: one of parameters is not populated : nodeId, node type, supporting nodeId");
462 public Map<String, OpenroadmTpType> getAvailableTps() {
463 return availableXponderTp;
466 public void addOutgoingLink(PceLink outLink) {
467 this.outgoingLinks.add(outLink);
470 public List<PceLink> getOutgoingLinks() {
471 return outgoingLinks;
474 public String getClient(String tp) {
475 return clientPerNwTp.get(tp);
478 public String getTopoSupNodeIdPceNode() {
479 return supTopoNodeId;
482 public String getNetworkSupNodeIdPceNode() {
483 return supNetworkNodeId;
486 public String getCLLI() {
490 public String toString() {
491 return "PceNode type=" + nodeType + " ID=" + nodeId.getValue() + " CLLI=" + clli;
494 public void printLinksOfNode() {
495 LOG.info(" outgoing links of node {} : {} ", nodeId.getValue(), this.getOutgoingLinks().toString());
498 public Map<String, List<Integer>> getAvailableTribPorts() {
499 return tpAvailableTribPort;
502 public Map<String, List<Integer>> getAvailableTribSlots() {
503 return tpAvailableTribSlot;