Determine preferred node/port from PCRI
[transportpce.git] / pce / src / main / java / org / opendaylight / transportpce / pce / networkanalyzer / port / PreferenceFactory.java
1 /*
2  * Copyright (c) 2024 Smartoptics 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.port;
10
11 import java.util.Arrays;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Map;
15 import java.util.Set;
16 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInput;
17 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.request.input.ServiceAEnd;
18 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.request.input.ServiceZEnd;
19 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.port.Port;
20 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.endpoint.sp.RxDirection;
21 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.endpoint.sp.TxDirection;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 public class PreferenceFactory implements Factory {
26
27     private static final Logger LOG = LoggerFactory.getLogger(PreferenceFactory.class);
28
29     private final String portNamePattern = "(?i)SRG\\d+-PP\\d+-(TXRX|TX|RX)";
30
31     @Override
32     public Preference portPreference(PathComputationRequestInput pathComputationRequestInput) {
33
34         Map<String, Set<String>> map = nodePortMap(pathComputationRequestInput);
35
36         if (map.isEmpty()) {
37             LOG.debug("No port preference found in path computation request.");
38             return new NoPreference();
39         }
40
41         LOG.debug("Port preference in path computation request: {}." , map);
42         return new ClientPreference(map);
43     }
44
45     /**
46      * Create a key value mapper from PCRI where key is the node and the value is
47      * a unique list of port names.
48      *
49      * @return Client port preference map
50      */
51     Map<String, Set<String>> nodePortMap(PathComputationRequestInput pathComputationRequestInput) {
52
53         Map<String, Set<String>> mapper = new HashMap<>();
54
55         ServiceAEnd serviceAEnd = pathComputationRequestInput.getServiceAEnd();
56         if (serviceAEnd != null) {
57
58             RxDirection rxAzDirection = serviceAEnd.getRxDirection();
59             if (rxAzDirection != null) {
60
61                 Port rxAZport = rxAzDirection.getPort();
62                 if (rxAZport != null) {
63                     add(rxAZport.getPortDeviceName(), rxAZport.getPortName(), mapper);
64                 }
65             }
66
67             TxDirection txAzDirection = serviceAEnd.getTxDirection();
68             if (txAzDirection != null) {
69
70                 Port txAZport = txAzDirection.getPort();
71                 if (txAZport != null) {
72                     add(txAZport.getPortDeviceName(), txAZport.getPortName(), mapper);
73                 }
74             }
75         }
76
77         ServiceZEnd serviceZEnd = pathComputationRequestInput.getServiceZEnd();
78         if (serviceZEnd != null) {
79
80             RxDirection rxZaDirection = serviceZEnd.getRxDirection();
81             if (rxZaDirection != null) {
82
83                 Port rxZAport = rxZaDirection.getPort();
84                 if (rxZAport != null) {
85                     add(rxZAport.getPortDeviceName(), rxZAport.getPortName(), mapper);
86                 }
87             }
88
89             TxDirection txZaDirection = serviceZEnd.getTxDirection();
90             if (txZaDirection != null) {
91
92                 Port txZAport = txZaDirection.getPort();
93                 if (txZAport != null) {
94                     add(txZAport.getPortDeviceName(), txZAport.getPortName(), mapper);
95                 }
96             }
97         }
98
99         return mapper;
100     }
101
102     /**
103      * Add node/port name to key value map. Mutable method, modifies the argument nodePortMap.
104      */
105     boolean add(String node, String port, Map<String, Set<String>> nodePortMap) {
106
107         if (node == null || port == null) {
108             return false;
109         }
110
111         String nodeTrimmed = node.trim();
112         String portTrimmed = port.trim();
113
114         if (nodeTrimmed.isEmpty() || portTrimmed.isEmpty()) {
115             return false;
116         }
117
118         if (!portTrimmed.matches(portNamePattern)) {
119             LOG.warn("Preferred port name '{}' on node {} doesn't match pattern '{}'",
120                 portTrimmed,
121                 nodeTrimmed,
122                 portNamePattern
123             );
124         }
125
126         if (nodePortMap.containsKey(nodeTrimmed)) {
127             boolean added = nodePortMap.get(nodeTrimmed).add(portTrimmed);
128             if (added) {
129                 LOG.debug("Preferred port '{}' for node '{}' registered.", portTrimmed, nodeTrimmed);
130             } else {
131                 LOG.debug("Failed registering port '{}' for node '{}'.", portTrimmed, nodeTrimmed);
132             }
133             return added;
134         }
135
136         nodePortMap.put(nodeTrimmed, new HashSet<>(Arrays.asList(portTrimmed)));
137
138         return true;
139     }
140 }