9da697f99961a5a519c6d9f137c79b55989c6d1f
[transportpce.git] / pce / src / main / java / org / opendaylight / transportpce / pce / networkanalyzer / PceOtnNode.java
1 /*
2  * Copyright © 2019 Orange, 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.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 //import java.util.Optional;
16 import java.util.TreeMap;
17
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;
42
43 public class PceOtnNode extends PceNode {
44     /* Logging. */
45     private static final Logger LOG = LoggerFactory.getLogger(PceCalculation.class);
46     ////////////////////////// OTN NODES ///////////////////////////
47     /*
48      * For This Class the node passed shall be at the otn-openroadm Layer
49      */
50
51     private boolean valid = true;
52
53     private final String supNetworkNodeId;
54     private final String supTopoNodeId;
55     private final String clli;
56     private final String otnServiceType;
57
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>();
67
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();
80
81         if ((node == null) || (nodeId == null) || (nodeType == null)) {
82             LOG.error("PceOtnNode: one of parameters is not populated : nodeId, node type");
83             this.valid = false;
84         }
85     }
86
87     public void initXndrTps(String mode) {
88         LOG.info("initXndrTps for node : {}", this.nodeId);
89         int availableNetworkTpNumber = 0;
90         int availableClientTpNumber = 0;
91
92         this.availableXponderTp.clear();
93
94         if (!isValid()) {
95             return;
96         }
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();
102         this.valid = false;
103         if (allTps == null) {
104             LOG.error("initXndrTps: XPONDER TerminationPoint list is empty for node {}", this.toString());
105             return;
106         }
107
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());
115                 } else {
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());
120                     } else {
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
124                             // interface
125                             List<OdtuTpnPool> presenceOdtu =
126                                 otnTp1.getXpdrTpPortConnectionAttributes().getOdtuTpnPool();
127                             if (presenceOdtu == null) {
128                                 this.unusableXpdrNWTps.add(tp.getTpId().getValue());
129                             } else {
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++;
137                                 }
138                                 /*
139                                  * Add the retrieval of outgoing ingoing links
140                                  * through an external function
141                                  */
142                             }
143                         } else {
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++;
150                                 /*
151                                  * Add the retrieval of outgoing ingoing links
152                                  * through an external function
153                                  */
154                             } else {
155                                 this.unusableXpdrNWTps.add(tp.getTpId().getValue());
156
157                             }
158
159                         }
160
161                     }
162
163                 }
164
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
169                 // in use?
170                 List<SupportedInterfaceCapability> sic =
171                     otnTp1.getTpSupportedInterfaces().getSupportedInterfaceCapability();
172                 if (findClientCompliantInterface(sic)) {
173                     this.availableXponderTp.put(tp.getTpId().getValue(), OpenroadmTpType.XPONDERCLIENT);
174                     availableClientTpNumber++;
175                 }
176             }
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());
180         }
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
185                 this.valid = true;
186             }
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
191                 this.valid = true;
192             }
193         }
194
195         if (!isValid()) {
196             LOG.debug("initXndrTps: XPONDER doesn't have the required ports available  {}", this.toString());
197             return;
198         } else {
199             LOG.debug("initXndrTps: XPONDER {} is elligible", this.toString());
200         }
201     }
202
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) {
208                 case "If1GEODU0":
209                 case "If1GE":
210                     if ("1GE".equals(this.otnServiceType)) {
211                         compliant = true;
212                     }
213                     break;
214                 case "If10GEODU2e":
215                 case "If10GE":
216                     if ("10GE".equals(this.otnServiceType)) {
217                         compliant = true;
218                     }
219                     break;
220                 case "If100GEODU4":
221                 case "If100GE":
222                     if ("100GE".equals(this.otnServiceType)) {
223                         compliant = true;
224                     }
225                     break;
226                 case "IfOTU4ODU4":
227                 case "IfOCHOTU4ODU4":
228                     if (("OTU4".equals(this.otnServiceType)) || ("ODU4".equals(this.otnServiceType))) {
229                         compliant = true;
230                     }
231                     break;
232                 default:
233                     compliant = false;
234                     break;
235             }
236
237         }
238         return compliant;
239     }
240
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) {
246                 case "IfOTU4ODU4":
247                 case "IfOCHOTU4ODU4":
248                     compliant = true;
249                     break;
250                 case "IfOTU2ODU2":
251                 case "IfOCHOTU2ODU2":
252                     if (("1GE".equals(this.otnServiceType)) || ("10GE".equals(this.otnServiceType))) {
253                         compliant = true;
254                     }
255                     break;
256                 // add all use case with higher rate interfaces when it shows up
257                 default:
258                     compliant = false;
259                     break;
260             }
261
262         }
263         return compliant;
264     }
265
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());
272         } else {
273             tempNetworkSupNodeId = allSupNodes.get(NetworkUtils.CLLI_NETWORK_ID);
274         }
275         return tempNetworkSupNodeId;
276     }
277
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) {
283             LOG.error(
284                 "getNetworkSupNodeId: No Supporting node at NETWORK layer for node: [{}].", inputNode.getNodeId());
285         } else {
286             tempNetworkSupNodeId = allSupNodes.get(NetworkUtils.UNDERLAY_NETWORK_ID);
287         }
288         return tempNetworkSupNodeId;
289     }
290
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) {
296             LOG.error(
297                 "getTopologySupNodeId: No Supporting node at TOPOLOGY layer for node: [{}].", inputNode.getNodeId());
298         } else {
299             tempTopoSupNodeId = allSupNodes.get(NetworkUtils.OVERLAY_NETWORK_ID);
300         }
301         return tempTopoSupNodeId;
302     }
303
304     public void validateAZxponder(String anodeId, String znodeId) {
305         if (!isValid()) {
306             return;
307         }
308         if ((this.nodeType != OpenroadmNodeType.MUXPDR) & (this.nodeType != OpenroadmNodeType.SWITCH)
309             & (this.nodeType != OpenroadmNodeType.TPDR)) {
310             return;
311         }
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))) {
315             initXndrTps("AZ");
316             if (!this.valid) {
317                 LOG.debug("validateAZxponder: XPONDER unusable for A or Z == {}", nodeId.getValue());
318             } else {
319                 LOG.info("validateAZxponder: A or Z node detected and validated == {}", nodeId.getValue());
320             }
321             return;
322         } else {
323             LOG.debug("validateAZxponder: XPONDER is ignored == {}", nodeId.getValue());
324             valid = false;
325         }
326
327     }
328
329     public boolean validateSwitchingPoolBandwidth(
330             Node node,
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,
335             Long neededBW) {
336         Long availableBW = 0L;
337         if (this.nodeType != OpenroadmNodeType.TPDR) {
338             return true;
339         } else {
340             org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.Node1 node1 =
341                 node.augmentation(
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());
354                             return true;
355                         }
356                     }
357                 }
358
359             }
360             LOG.debug("validateSwitchingPoolBandwidth: No valid Switching pool for crossconnecting tp {} and {}",
361                 tp1.getTpId().toString(), tp2.getTpId().toString());
362             return false;
363         }
364
365     }
366
367     public void validateIntermediateSwitch() {
368         if (!isValid()) {
369             return;
370         }
371         if (this.nodeType != OpenroadmNodeType.SWITCH) {
372             return;
373         }
374         // Validate switch for use as an intermediate XPONDER on the path
375         initXndrTps("intermediate");
376         if (!this.valid) {
377             LOG.debug("validateIntermediateSwitch: Switch unusable for transit == {}", nodeId.getValue());
378         } else {
379             LOG.info("validateIntermediateSwitch: Switch usable for transit == {}", nodeId.getValue());
380         }
381         return;
382
383     }
384
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) {
391             try {
392                 List<OdtuTpnPool> otpp = otnTp1.getXpdrTpPortConnectionAttributes().getOdtuTpnPool();
393
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;
400
401                     }
402                 }
403             } catch (NullPointerException e) {
404                 LOG.debug("checkAvailableTribPort: OdtuTpnPool not present for tp {} ", tp.getTpId().toString());
405             }
406
407         } else {
408             LOG.debug("checkAvailableTribPort: tp {} has no odtu tpn Pool", tp.getTpId().getValue());
409         }
410         return compatibleSupInt;
411     }
412
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;
420             try {
421                 otpp = otnTp1.getXpdrTpPortConnectionAttributes().getOdtuTpnPool();
422
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());
428                         LOG.debug(
429                             "checkAvailableTribPort: tp {} and its trib Slots were added to tpAvailableTribSlotMap",
430                             tp.getTpId().getValue());
431                         compatibleSupInt = true;
432
433                     }
434                 }
435
436             } catch (NullPointerException e) {
437                 LOG.debug("checkAvailableTribSlot: OdtuTpnPool not present for tp {} ", tp.getTpId().toString());
438             }
439         } else {
440             LOG.debug("checkAvailableTribPort: tp {} is not a network Port", tp.getTpId().getValue());
441         }
442         return compatibleSupInt;
443     }
444
445     public String getXpdrClient(String tp) {
446         return this.clientPerNwTp.get(tp);
447     }
448
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)));
452     }
453
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");
457             valid = false;
458         }
459         return valid;
460     }
461
462     public Map<String, OpenroadmTpType> getAvailableTps() {
463         return availableXponderTp;
464     }
465
466     public void addOutgoingLink(PceLink outLink) {
467         this.outgoingLinks.add(outLink);
468     }
469
470     public List<PceLink> getOutgoingLinks() {
471         return outgoingLinks;
472     }
473
474     public String getClient(String tp) {
475         return clientPerNwTp.get(tp);
476     }
477
478     public String getTopoSupNodeIdPceNode() {
479         return supTopoNodeId;
480     }
481
482     public String getNetworkSupNodeIdPceNode() {
483         return supNetworkNodeId;
484     }
485
486     public String getCLLI() {
487         return clli;
488     }
489
490     public String toString() {
491         return "PceNode type=" + nodeType + " ID=" + nodeId.getValue() + " CLLI=" + clli;
492     }
493
494     public void printLinksOfNode() {
495         LOG.info(" outgoing links of node {} : {} ", nodeId.getValue(), this.getOutgoingLinks().toString());
496     }
497
498     public Map<String, List<Integer>> getAvailableTribPorts() {
499         return tpAvailableTribPort;
500     }
501
502     public Map<String, List<Integer>> getAvailableTribSlots() {
503         return tpAvailableTribSlot;
504     }
505
506 }