PCE OTN layer support init 63/85363/17
authorOlivier Renais <olivier.renais@orange.com>
Wed, 23 Oct 2019 13:29:13 +0000 (15:29 +0200)
committerguillaume.lambert <guillaume.lambert@orange.com>
Sun, 9 Feb 2020 14:32:42 +0000 (15:32 +0100)
-Add PceOtnNode Class and complete PceLinkClass
-Add Algorithm in PceCalculation and PceGraph to handle path
 calculation at the WDM or OTN layer
-Adapt InAlgoPathValidator to work with the OTN layer
-Adapt PostAlgoPathValidator with method to retrieve trib-port/slot in
 place of wavelengths
 CAUTION: at that time, it does not handle trib-slot and trib-port
 pass to Service Handler (still based on old path-computation-request)
-Adapt PCE functional tests
-change topo to include supporting nodes
CAUTION: Expected node in rpc path-computation-request is of OTN type

JIRA: TRNSPRTPCE-162
Signed-off-by: Olivier Renais <olivier.renais@orange.com>
Co-authored-by: Gilles Thouenon <gilles.thouenon@orange.com>
Co-authored-by: Christophe Betoule <christophe.betoule@orange.com>
Change-Id: If5c29cae48b94660f2536f86b2df814b6515969b

12 files changed:
pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java [changed mode: 0755->0644]
pce/src/main/java/org/opendaylight/transportpce/pce/graph/InAlgoPathValidator.java
pce/src/main/java/org/opendaylight/transportpce/pce/graph/PceGraph.java
pce/src/main/java/org/opendaylight/transportpce/pce/graph/PostAlgoPathValidator.java
pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/MapUtils.java
pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceCalculation.java
pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceLink.java
pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceNode.java
pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceOtnNode.java [new file with mode: 0644]
pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceResult.java
tests/sample_configs/honeynode-topo.xml
tests/transportpce_tests/1.2.1/test_pce.py

old mode 100755 (executable)
new mode 100644 (file)
index e8f0f9a..064140c
@@ -93,14 +93,15 @@ public class PceSendingPceRPCs {
             new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc);
         nwAnalizer.retrievePceNetwork();
         rc = nwAnalizer.getReturnStructure();
+        String serviceType = nwAnalizer.getServiceType();
         if (!rc.getStatus()) {
             LOG.error("In pathComputationWithConstraints, nwAnalizer: result = {}", rc.toString());
             return;
         }
         LOG.info("PceGraph ...");
         PceGraph graph = new PceGraph(nwAnalizer.getaendPceNode(),
-            nwAnalizer.getzendPceNode(), nwAnalizer.getAllPceNodes(),
-            hardConstraints, softConstraints, rc);
+                nwAnalizer.getzendPceNode(), nwAnalizer.getAllPceNodes(),
+                pceHardConstraints, pceSoftConstraints, rc, serviceType);
         graph.calcPath();
         rc = graph.getReturnStructure();
         if (!rc.getStatus()) {
index 963ce456413e58fa0ec5b49bd7c8acf222ec61f1..92ffaea23da8a9e5fe3cbe6f8a818ce1fadefea5 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.transportpce.pce.graph;
 import org.jgrapht.GraphPath;
 import org.jgrapht.alg.shortestpath.PathValidator;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType;
+//import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,5 +73,5 @@ public class InAlgoPathValidator implements PathValidator<String, PceGraphEdge>
 
         return true;
     }
+}
 
-}
\ No newline at end of file
index 3f2210b530a8b0c9874a29f4049d7c892f4a796d..c7733ddd5726f903a79cb8d54cc2e18916d48c04 100644 (file)
@@ -44,6 +44,7 @@ public class PceGraph {
     private Map<NodeId, PceNode> allPceNodes = new HashMap<NodeId, PceNode>();
     private PceNode apceNode = null;
     private PceNode zpceNode = null;
+    private String serviceType = "";
 
     PceConstraints pceHardConstraints;
     PceConstraints pceSoftConstraints;
@@ -58,7 +59,8 @@ public class PceGraph {
     private List<PceLink> pathAtoZ = new ArrayList<PceLink>();
 
     public PceGraph(PceNode aendNode, PceNode zendNode, Map<NodeId, PceNode> allPceNodes,
-            PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult pceResult) {
+            PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult pceResult,
+            String serviceType) {
         super();
         this.apceNode = aendNode;
         this.zpceNode = zendNode;
@@ -66,6 +68,7 @@ public class PceGraph {
         this.pceResult = pceResult;
         this.pceHardConstraints = pceHardConstraints;
         this.pceSoftConstraints = pceSoftConstraints;
+        this.serviceType = serviceType;
 
         LOG.info("In GraphCalculator: A and Z = {} / {} ", aendNode.toString(), zendNode.toString());
         LOG.debug("In GraphCalculator: allPceNodes size {}, nodes {} ", allPceNodes.size(), allPceNodes.toString());
@@ -89,7 +92,7 @@ public class PceGraph {
         pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
         for (GraphPath<String, PceGraphEdge> path : allWPaths) {
             PostAlgoPathValidator papv = new PostAlgoPathValidator();
-            pceResult = papv.checkPath(path, allPceNodes, pceResult, pceHardConstraints);
+            pceResult = papv.checkPath(path, allPceNodes, pceResult, pceHardConstraints, serviceType);
             LOG.info("In calcPath after PostAlgoPathValidator {} {}",
                     pceResult.getResponseCode(), ResponseCodes.RESPONSE_OK);
 
@@ -105,9 +108,17 @@ public class PceGraph {
             }
 
             shortestPathAtoZ = new ArrayList<>(pathAtoZ);
-            LOG.info("In calcPath Path FOUND path for wl [{}], hops {}, distance per metrics {}, path AtoZ {}",
-                    pceResult.getResultWavelength(), pathAtoZ.size(), path.getWeight(), pathAtoZ.toString());
-            break;
+            if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
+                LOG.info("In calcPath Path FOUND path for wl [{}], hops {}, distance per metrics {}, path AtoZ {}",
+                        pceResult.getResultWavelength(), pathAtoZ.size(), path.getWeight(), pathAtoZ.toString());
+                break;
+            } else {
+                // Service is at OTN layer and is relying on a supporting wavelength service
+                LOG.info("In calcPath Path FOUND path for hops {}, distance per metrics {}, path AtoZ {}",
+                        pathAtoZ.size(), path.getWeight(), pathAtoZ.toString());
+                break;
+            }
+
         }
 
         if (shortestPathAtoZ != null) {
@@ -222,6 +233,11 @@ public class PceGraph {
             case PropagationDelay :
                 weight = link.getLatency();
                 LOG.debug("In PceGraph PropagationDelay is used as a metrics. {}", link.toString());
+                if ((("1GE".equals(serviceType)) || ("10GE".equals(serviceType)) || ("ODU4".equals(serviceType)))
+                        && (weight == 0)) {
+                    LOG.warn("PropagationDelay set as metric, but latency is null: is latency set for OTN link {}?",
+                        link.toString());
+                }
                 break;
 
             default:
index 626895fd181b71486e0241f5569870f955e58a23..1d28a2dd2c1e9a623355eb49a6b314e5bc7451f1 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.transportpce.common.ResponseCodes;
 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
 import org.opendaylight.transportpce.pce.constraints.PceConstraints.ResourcePair;
 import org.opendaylight.transportpce.pce.networkanalyzer.PceNode;
+import org.opendaylight.transportpce.pce.networkanalyzer.PceOtnNode;
 import org.opendaylight.transportpce.pce.networkanalyzer.PceResult;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
@@ -35,56 +36,78 @@ public class PostAlgoPathValidator {
     public static final Long CONST_OSNR = 1L;
     public static final double SYS_MARGIN = 0;
 
-    public PceResult checkPath(GraphPath<String, PceGraphEdge> path,
-            Map<NodeId, PceNode> allPceNodes, PceResult pceResult, PceConstraints pceHardConstraints) {
+    public PceResult checkPath(GraphPath<String, PceGraphEdge> path, Map<NodeId, PceNode> allPceNodes,
+        PceResult pceResult, PceConstraints pceHardConstraints, String serviceType) {
 
-        //check if the path is empty
+        // check if the path is empty
         if (path.getEdgeList().size() == 0) {
             pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
             return pceResult;
         }
+        if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
+            // choose wavelength available in all nodes of the path
+            Long waveL = chooseWavelength(path, allPceNodes);
+            if (waveL < 0) {
+                pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
+                pceResult.setLocalCause(PceResult.LocalCause.NO_PATH_EXISTS);
+                return pceResult;
+            }
+            pceResult.setResultWavelength(waveL);
+            LOG.info("In PostAlgoPathValidator: chooseWavelength WL found {} {}", waveL, path.toString());
 
-        //Choose wavelength available in all nodes of the path
-        Long waveL = chooseWavelength(path, allPceNodes);
-        if (waveL < 0) {
-            pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
-            pceResult.setLocalCause(PceResult.LocalCause.NO_PATH_EXISTS);
-            return pceResult;
-        }
-        pceResult.setResultWavelength(waveL);
-        LOG.info("In PostAlgoPathValidator: chooseWavelength WL found {} {}", waveL, path.toString());
+            // TODO here other post algo validations can be added
+            // more data can be sent to PceGraph module via PceResult structure if required
 
-        // TODO here other post algo validations can be added
-        // more data can be sent to PceGraph module via PceResult structure if required
+            // Check the OSNR
+            if (!checkOSNR(path)) {
+                pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
+                pceResult.setLocalCause(PceResult.LocalCause.OUT_OF_SPEC_OSNR);
+                return pceResult;
+            }
 
-        //Check the OSNR
-        if (!checkOSNR(path)) {
-            pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
-            pceResult.setLocalCause(PceResult.LocalCause.OUT_OF_SPEC_OSNR);
-            return pceResult;
-        }
+            // Check if MaxLatency is defined in the hard constraints
+            if (pceHardConstraints.getMaxLatency() != -1) {
+                if (!checkLatency(pceHardConstraints.getMaxLatency(), path)) {
+                    pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
+                    pceResult.setLocalCause(PceResult.LocalCause.TOO_HIGH_LATENCY);
+                    return pceResult;
+                }
+            }
 
-        //Check if MaxLatency is defined in the hard constraints
-        if (pceHardConstraints.getMaxLatency() != -1) {
-            if (!checkLatency(pceHardConstraints.getMaxLatency(), path)) {
+            // Check if nodes are included in the hard constraints
+            if (!checkInclude(path, pceHardConstraints)) {
                 pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
-                pceResult.setLocalCause(PceResult.LocalCause.TOO_HIGH_LATENCY);
+                pceResult.setLocalCause(PceResult.LocalCause.HD_NODE_INCLUDE);
                 return pceResult;
             }
-        }
+            pceResult.setRC(ResponseCodes.RESPONSE_OK);
 
-        //Check if nodes are included in the hard constraints
-        if (!checkInclude(path, pceHardConstraints)) {
+        } else if (("1GE".equals(serviceType)) || ("10GE".equals(serviceType))) {
+            // Path is at the OTN layer
             pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
-            pceResult.setLocalCause(PceResult.LocalCause.HD_NODE_INCLUDE);
-            return pceResult;
+            // In a first step we select the first tribPort available on the first edge
+            // TODO : after the way to pass trib-ports and trib-slots to the renderer has
+            // been adapted to fit
+            // with multiple OTN Hops, each first available port shall be passed for each
+            // edge to Renderer
+            Integer tribPort = chooseTribPort(path, allPceNodes).get(0).get(0);
+            // TODO : Same comment apply for tribSlot
+            Integer tribSlot = chooseTribSlot(path, allPceNodes).get(0).get(0);
+
+            if (tribPort != null) {
+                // Temporarily we use wavelength-number to provide the TribPort
+                // TODO adapt the path-description
+                // TODO make the adaptation to return the first tribSlot in an intermediate
+                // phase
+                pceResult.setResultWavelength(tribPort);
+                pceResult.setRC(ResponseCodes.RESPONSE_OK);
+                LOG.info("In PostAlgoPathValidator: chooseTribPort TribPort found {} {}", tribPort, path.toString());
+            }
         }
-
-        pceResult.setRC(ResponseCodes.RESPONSE_OK);
         return pceResult;
     }
 
-    //Choose the first available wavelength from the source to the destination
+    // Choose the first available wavelength from the source to the destination
     private Long chooseWavelength(GraphPath<String, PceGraphEdge> path, Map<NodeId, PceNode> allPceNodes) {
         Long wavelength = -1L;
 
@@ -107,14 +130,14 @@ public class PostAlgoPathValidator {
         return wavelength;
     }
 
-    //Check the latency
+    // Check the latency
     private boolean checkLatency(Long maxLatency, GraphPath<String, PceGraphEdge> path) {
         double latency = 0;
 
         for (PceGraphEdge edge : path.getEdgeList()) {
             try {
                 latency += edge.link().getLatency();
-                LOG.debug("- In checkLatency: latency of {} = {} units", edge.link().getLinkId().getValue(),latency);
+                LOG.debug("- In checkLatency: latency of {} = {} units", edge.link().getLinkId().getValue(), latency);
             } catch (NullPointerException e) {
                 LOG.warn("- In checkLatency: the link {} does not contain latency field",
                     edge.link().getLinkId().getValue());
@@ -126,7 +149,7 @@ public class PostAlgoPathValidator {
         return true;
     }
 
-    //Check the inclusion if it is defined in the hard constraints
+    // Check the inclusion if it is defined in the hard constraints
     private boolean checkInclude(GraphPath<String, PceGraphEdge> path, PceConstraints pceHardConstraintsInput) {
         List<ResourcePair> listToInclude = pceHardConstraintsInput.getListToInclude();
         if (listToInclude.isEmpty()) {
@@ -195,7 +218,7 @@ public class PostAlgoPathValidator {
         PceConstraints pceHardConstraints) {
 
         List<String> listOfElements = new ArrayList<String>();
-        for (PceGraphEdge link: pathEdges) {
+        for (PceGraphEdge link : pathEdges) {
             switch (type) {
                 case NODE:
                     listOfElements.add(link.link().getdestSupNodeId());
@@ -209,14 +232,16 @@ public class PostAlgoPathValidator {
                         break;
                     }
 
-                    // srlg of link is List<Long>. But in this algo we need string representation of one SRLG
-                    // this should be any SRLG mentioned in include constraints if any of them if mentioned
+                    // srlg of link is List<Long>. But in this algo we need string representation of
+                    // one SRLG
+                    // this should be any SRLG mentioned in include constraints if any of them if
+                    // mentioned
                     boolean found = false;
                     for (Long srlg : link.link().getsrlgList()) {
                         String srlgStr = String.valueOf(srlg);
                         if (pceHardConstraints.getSRLGnames().contains(srlgStr)) {
                             listOfElements.add(srlgStr);
-                            LOG.info("listOfElementsBuild. FOUND SRLG {} in link {}", srlgStr, link.link().toString());
+                            LOG.info("listOfElementsBuild. FOUND SRLG {} in link {}", srlgStr, link.link());
                             found = true;
                             continue;
                         }
@@ -233,7 +258,120 @@ public class PostAlgoPathValidator {
         return listOfElements;
     }
 
-    //Check the path OSNR
+    private List<List<Integer>> chooseTribPort(GraphPath<String, PceGraphEdge> path, Map<NodeId, PceNode> allPceNodes) {
+        List<List<Integer>> tribPort = new ArrayList<>();
+        boolean statusOK = true;
+        boolean check = false;
+        Object nodeClass = allPceNodes.getClass();
+        if (nodeClass.getClass().isInstance(PceNode.class)) {
+            LOG.debug("In choosetribPort: AllPceNodes contains PceNode instance, no trib port search");
+            return tribPort;
+        } else if (nodeClass.getClass().isInstance(PceOtnNode.class)) {
+            LOG.debug("In choosetribPort: {} {}", path.getLength(), path.toString());
+            for (PceGraphEdge edge : path.getEdgeList()) {
+                LOG.debug("In chooseTribPort: source {} ", edge.link().getSourceId().toString());
+                PceNode pceNode = allPceNodes.get(edge.link().getSourceId());
+                Object tps = allPceNodes.get(edge.link().getSourceTP());
+                Object tpd = allPceNodes.get(edge.link().getDestTP());
+                if ((pceNode.getAvailableTribPorts().containsKey(tps.toString()))
+                    && (pceNode.getAvailableTribPorts().containsKey(tpd.toString()))) {
+
+                    List<Integer> tribPortEdgeSourceN = new ArrayList<>();
+                    List<Integer> tribPortEdgeDestN = new ArrayList<>();
+                    tribPortEdgeSourceN = pceNode.getAvailableTribPorts().get(tps.toString());
+                    tribPortEdgeDestN = pceNode.getAvailableTribPorts().get(tps.toString());
+                    check = false;
+                    for (int i = 0; i <= 9; i++) {
+                        if (tribPortEdgeSourceN.get(i) == null) {
+                            break;
+                        }
+                        if (tribPortEdgeSourceN.get(i) == tribPortEdgeDestN.get(i)) {
+                            check = true;
+                        } else {
+                            check = false;
+                            LOG.debug("In chooseTribPort: Misalignement of trib port between source {}  and dest {}",
+                                edge.link().getSourceId().toString(), edge.link().getDestId().toString());
+                            break;
+                        }
+                    }
+                    if (check) {
+                        tribPort.add(tribPortEdgeSourceN);
+                    }
+                } else {
+                    LOG.debug("In chooseTribPort: source {} does not have provisonned hosting HO interface ",
+                        edge.link().getSourceId().toString());
+                    statusOK = false;
+                }
+            }
+        }
+        if (statusOK && check) {
+            return tribPort;
+        } else {
+            tribPort.clear();
+            return tribPort;
+        }
+
+    }
+
+    private List<List<Integer>> chooseTribSlot(GraphPath<String, PceGraphEdge> path, Map<NodeId, PceNode> allPceNodes) {
+        List<List<Integer>> tribSlot = new ArrayList<>();
+        boolean statusOK = true;
+        boolean check = false;
+        Object nodeClass = allPceNodes.getClass();
+        if (nodeClass.getClass().isInstance(PceNode.class)) {
+            LOG.debug("In choosetribSlot: AllPceNodes contains PceNode instance, no trib port search");
+            return tribSlot;
+        } else if (nodeClass.getClass().isInstance(PceOtnNode.class)) {
+            LOG.debug("In choosetribPort: {} {}", path.getLength(), path.toString());
+            for (PceGraphEdge edge : path.getEdgeList()) {
+                LOG.debug("In chooseTribSlot: source {} ", edge.link().getSourceId().toString());
+                PceNode pceNode = allPceNodes.get(edge.link().getSourceId());
+                Object tps = allPceNodes.get(edge.link().getSourceTP());
+                Object tpd = allPceNodes.get(edge.link().getDestTP());
+                if ((pceNode.getAvailableTribSlots().containsKey(tps.toString()))
+                    && (pceNode.getAvailableTribSlots().containsKey(tpd.toString()))) {
+
+                    List<Integer> tribSlotEdgeSourceN = new ArrayList<>();
+                    List<Integer> tribSlotEdgeDestN = new ArrayList<>();
+                    tribSlotEdgeSourceN = pceNode.getAvailableTribSlots().get(tps.toString());
+                    tribSlotEdgeDestN = pceNode.getAvailableTribSlots().get(tps.toString());
+                    check = false;
+                    for (int i = 0; i <= 79; i++) {
+                        if (tribSlotEdgeSourceN.get(i) == null) {
+                            break;
+                        }
+                        // TODO This will need to be modified as soon as the trib-slots allocation per
+                        // trib-port
+                        // policy applied by the different manufacturer is known
+                        if (tribSlotEdgeSourceN.get(i) == tribSlotEdgeDestN.get(i)) {
+                            check = true;
+                        } else {
+                            check = false;
+                            LOG.debug("In chooseTribSlot: Misalignement of trib slots between source {}  and dest {}",
+                                edge.link().getSourceId().toString(), edge.link().getDestId().toString());
+                            break;
+                        }
+                    }
+                    if (check) {
+                        tribSlot.add(tribSlotEdgeSourceN);
+                    }
+                } else {
+                    LOG.debug("In chooseTribSlot: source {} does not have provisonned hosting HO interface ",
+                        edge.link().getSourceId().toString());
+                    statusOK = false;
+                }
+            }
+        }
+        if (statusOK && check) {
+            return tribSlot;
+        } else {
+            tribSlot.clear();
+            return tribSlot;
+        }
+
+    }
+
+    // Check the path OSNR
     private boolean checkOSNR(GraphPath<String, PceGraphEdge> path) {
         double linkOsnrDb;
         double osnrDb = 0;
@@ -251,8 +389,7 @@ public class PostAlgoPathValidator {
         }
         try {
             osnrDb = getOsnrDb(1 / inverseLocalOsnr);
-        }
-        catch (ArithmeticException e) {
+        } catch (ArithmeticException e) {
             LOG.debug("In checkOSNR: OSNR is equal to 0 and the number of links is: {}", path.getEdgeList().size());
             return false;
         }
@@ -260,6 +397,9 @@ public class PostAlgoPathValidator {
         if ((osnrDb + SYS_MARGIN) < MIN_OSNR_W100G) {
             return false;
         }
+        double localOsnr = 0L;
+        LOG.info("In OSNR Stub: {}", localOsnr);
+        // TODO : change this to return OSNR value and validate or invalidate the path
         return true;
     }
 
@@ -277,4 +417,4 @@ public class PostAlgoPathValidator {
         return (CONST_OSNR / linkOsnrLu);
     }
 
-}
\ No newline at end of file
+}
index e6b9e3a4c06309e63a5f42fd5c2a7bb78e5efd3c..54868a35ecf4d43305a4a91c800f45e1f104587c 100644 (file)
@@ -10,11 +10,11 @@ package org.opendaylight.transportpce.pce.networkanalyzer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.TreeMap;
 import org.opendaylight.transportpce.common.NetworkUtils;
 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Link1;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.span.attributes.LinkConcatenation;
-
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.networks.network.link.oms.attributes.Span;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
@@ -92,6 +92,30 @@ public final class MapUtils {
         return srlgList;
     }
 
+    public static List<Long> getSRLGfromLink(Link link) {
+        List<Long> srlgList = new ArrayList<Long>();
+        org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Link1 linkC =
+            link.augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Link1.class);
+        if (linkC == null) {
+            LOG.error("MapUtils: No Link augmentation available. {}", link.getLinkId().getValue());
+
+        } else {
+            try {
+                List<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.networks.network.link
+                    .LinkConcatenation> linkConcatenation = linkC.getLinkConcatenation();
+
+
+                for (org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.networks.network.link
+                        .LinkConcatenation lc : linkConcatenation) {
+                    srlgList.add(lc.getSRLGId());
+                }
+            } catch (NullPointerException e) {
+                LOG.debug("No concatenation for this link");
+            }
+        }
+        return srlgList;
+    }
+
     public static String getSupNode(Node node) {
         List<SupportingNode> supNodes = node.getSupportingNode();
         for (SupportingNode snode : supNodes) {
@@ -102,6 +126,67 @@ public final class MapUtils {
         return null;
     }
 
+    public static TreeMap<String, String> getAllSupNode(Node node) {
+        TreeMap<String, String> allSupNodes = new TreeMap<String, String>();
+        List<SupportingNode> supNodes = new ArrayList<SupportingNode>();
+        try {
+            supNodes = node.getSupportingNode();
+        } catch (NullPointerException e) {
+            LOG.debug("No Supporting Node for the node {}", node);
+        }
+        for (SupportingNode supnode :supNodes) {
+            allSupNodes.put(supnode.getNetworkRef().getValue(),
+                    supnode.getNodeRef().getValue());
+        }
+        return allSupNodes;
+    }
+
+    public static String getSupLink(Link link) {
+        String supLink = "";
+        try {
+            supLink = link.getSupportingLink().get(0).getLinkRef().toString();
+        } catch (NullPointerException e) {
+            LOG.debug("No Supporting Link for the link {}", link);
+        }
+        return supLink;
+    }
+
+
+    public static Long getAvailableBandwidth(Link link) {
+        Link1 link1 = null;
+        Long availableBW  = 0L;
+        // ID and type
+        link1 = link.augmentation(Link1.class);
+        if (link1 == null) {
+            LOG.error("MapUtils: No Link augmentation available. {}", link.getLinkId().getValue());
+            return availableBW;
+        } else {
+            OpenroadmLinkType tmplType = null;
+            tmplType = link1.getLinkType();
+            if (tmplType == null) {
+                LOG.error("MapUtils: No Link type available. {}", link.getLinkId().getValue());
+                return null;
+            } else if (tmplType == OpenroadmLinkType.OTNLINK) {
+                org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.Link1 link11 =
+                    link.augmentation(
+                        org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.Link1.class);
+                if (link11 == null) {
+                    LOG.error("MapUtils: No Link augmentation available for {}", link.getLinkId().getValue());
+                    return availableBW;
+                } else {
+                    availableBW = link11.getAvailableBandwidth();
+                    return availableBW;
+                }
+
+            } else {
+                LOG.error("MapUtils: Evaluated Link is not of OTN Type");
+            }
+        }
+
+
+        return 0L;
+    }
+
     public static OpenroadmLinkType calcType(Link link) {
         Link1 link1 = null;
         OpenroadmLinkType tmplType = null;
index 7217b0c3a90142b720a281a7c26e431a78bb764a..61f288e00e26e0183d7862808509f82fa2b99f0e 100644 (file)
@@ -38,6 +38,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.top
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Network1;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+//import org.opendaylight.yangtools.yang.common.Decimal64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,6 +51,10 @@ public class PceCalculation {
     private PathComputationRequestInput input;
     private String anodeId = "";
     private String znodeId = "";
+    private String serviceFormatA = "";
+    private String serviceFormatZ = "";
+    private String serviceType = "";
+    private Long serviceRate = 0L;
 
     private PceConstraints pceHardConstraints;
 
@@ -109,16 +114,71 @@ public class PceCalculation {
     private boolean parseInput() {
         anodeId = input.getServiceAEnd().getNodeId();
         znodeId = input.getServiceZEnd().getNodeId();
+        serviceFormatA = input.getServiceAEnd().getServiceFormat().getName();
+        serviceFormatZ = input.getServiceZEnd().getServiceFormat().getName();
+        serviceRate = input.getServiceAEnd().getServiceRate();
+
         LOG.info("parseInput: A and Z :[{}] and [{}]", anodeId, znodeId);
+        if (!(serviceFormatA.equals(serviceFormatZ))) {
+            LOG.info("parseInput: different service format for A and Z not handled, will use service format from Aend");
+        } else if (serviceRate == 100L) {
+            switch (serviceFormatA) {
+                case "Ethernet":
+                case "OC":
+                    serviceType = "100GE";
+                    break;
+                case "OTU":
+                    serviceType = "OTU4";
+                    break;
+                case "ODU":
+                    serviceType = "ODU4";
+                    break;
+                default:
+                    LOG.debug("parseInput: unsupported service type: Format {} Rate 100L", serviceFormatA);
+                    break;
+            }
+            //switch(serviceRate) may seem a better option at first glance.
+            //But switching on Long or long is not directly possible in Java.
+            //And casting to int bumps the limit here.
+            //Passing by ENUM or String are possible alternatives.
+            //Maybe HashMap and similar options should also be considered here.
+        } else if (serviceFormatA == "Ethernet") {
+        //only rate 100L is currently supported except in Ethernet
+            if (serviceRate == 10L) {
+                serviceType = "10GE";
+            } else if (serviceRate == 1L) {
+                serviceType = "1GE";
+            } else {
+                LOG.debug("parseInput: unsupported service type: Format Ethernet Rate {}", String.valueOf(serviceRate));
+            }
+        } else {
+            LOG.debug("parseInput: unsupported service type: Format {} Rate {}",
+                serviceFormatA, String.valueOf(serviceRate));
+        }
+
         returnStructure.setRate(input.getServiceAEnd().getServiceRate());
+        returnStructure.setServiceFormat(input.getServiceAEnd().getServiceFormat());
         return true;
     }
 
     private boolean readMdSal() {
-        LOG.info("readMdSal: network {}", NetworkUtils.OVERLAY_NETWORK_ID);
-        InstanceIdentifier<Network> nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
-            .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build();
+        InstanceIdentifier<Network> nwInstanceIdentifier = null;
         Network nw = null;
+        if (("OC".equals(serviceFormatA)) || ("OTU".equals(serviceFormatA)) || (("Ethernet".equals(serviceFormatA))
+            && (serviceRate == 100L))) {
+
+            LOG.info("readMdSal: network {}", NetworkUtils.OVERLAY_NETWORK_ID);
+            nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build();
+        } else if ("ODU".equals(serviceFormatA)) {
+            LOG.info("readMdSal: network {}", NetworkUtils.OTN_NETWORK_ID);
+            nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID))).build();
+        } else {
+            LOG.info("readMdSal: service-rate {} / service-format not handled {}", serviceRate, serviceFormatA);
+            return false;
+        }
+
         try {
             Optional<Network> nwOptional =
                 networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, nwInstanceIdentifier).get();
@@ -131,7 +191,7 @@ public class PceCalculation {
             networkTransactionService.close();
             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
             throw new RuntimeException(
-                    "readMdSal: Error reading from operational store, topology : " + nwInstanceIdentifier + " :" + e);
+                "readMdSal: Error reading from operational store, topology : " + nwInstanceIdentifier + " :" + e);
         }
         networkTransactionService.close();
 
@@ -166,34 +226,66 @@ public class PceCalculation {
 
         LOG.debug("analyzeNw: allNodes size {}, allLinks size {}", allNodes.size(), allLinks.size());
 
-        for (Node node : allNodes) {
-            validateNode(node);
-        }
-        LOG.debug("analyzeNw: allPceNodes size {}", allPceNodes.size());
-
-        if (aendPceNode == null || zendPceNode == null) {
-            LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
-            return false;
-        }
+        if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
+            // 100GE service and OTU4 service are handled at the openroadm-topology layer
+            for (Node node : allNodes) {
+                validateNode(node);
+            }
 
-        for (Link link : allLinks) {
-            validateLink(link);
-        }
+            LOG.debug("analyzeNw: allPceNodes size {}", allPceNodes.size());
 
-        LOG.debug("analyzeNw: addLinks size {}, dropLinks size {}", addLinks.size(), dropLinks.size());
+            if (aendPceNode == null || zendPceNode == null) {
+                LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
+                return false;
+            }
+            for (Link link : allLinks) {
+                validateLink(link);
+            }
+            // debug prints
+            LOG.debug("analyzeNw: addLinks size {}, dropLinks size {}", addLinks.size(), dropLinks.size());
+            // debug prints
+            LOG.debug("analyzeNw: azSrgs size = {}", azSrgs.size());
+            for (NodeId srg : azSrgs) {
+                LOG.debug("analyzeNw: A/Z Srgs SRG = {}", srg.getValue());
+            }
+            // debug prints
+            for (PceLink link : addLinks) {
+                filteraddLinks(link);
+            }
+            for (PceLink link : dropLinks) {
+                filterdropLinks(link);
+            }
 
-        // debug prints
-        LOG.debug("analyzeNw: azSrgs size = {}", azSrgs.size());
-        for (NodeId srg : azSrgs) {
-            LOG.debug("analyzeNw: A/Z Srgs SRG = {}", srg.getValue());
-        }
-        // debug prints
+        } else {
+            // ODU4, 10GE/ODU2e or 1GE/ODU0 services are handled at openroadm-otn layer
+            OpenroadmNodeType typeOfNode = null;
+            for (Node node : allNodes) {
+                String nodeId = node.getNodeId().getValue();
+                if (this.anodeId.equals(nodeId) || (this.znodeId.equals(nodeId))) {
+                    typeOfNode = validateOtnNode(node, "AZ");
+                }
+            }
+            if (typeOfNode == null) {
+                LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
+            } else if (typeOfNode == OpenroadmNodeType.MUXPDR) {
+                LOG.debug("analyzeNw: A/Z end node are of muxponder type, no intermediate switch allowed on the path");
+            } else {
+                LOG.debug("analyzeNw: A/Z end node are of switch type, searching for potential intermediate switch");
+                for (Node node : allNodes) {
+                    String nodeId = node.getNodeId().getValue();
+                    if (!(this.anodeId.equals(nodeId) || (this.znodeId.equals(nodeId)))) {
+                        // A and Z node have been validated, then if A and Z end nodes are not muxponders
+                        // we allow intermediate switch on the path
+                        typeOfNode = validateOtnNode(node, "intermediate");
+                    }
+                    // else : typeOfNode is MUXPDR and we do not authorize any intermediate switch on the path
+                    // TODO : handle regens and authorize them on the path if needed
+                }
+            }
 
-        for (PceLink link : addLinks) {
-            filteraddLinks(link);
-        }
-        for (PceLink link : dropLinks) {
-            filterdropLinks(link);
+            for (Link link : allLinks) {
+                validateLink(link);
+            }
         }
 
         LOG.info("analyzeNw: allPceNodes size {}, allPceLinks size {}", allPceNodes.size(), allPceLinks.size());
@@ -260,87 +352,119 @@ public class PceCalculation {
 
         if (source == null) {
             LOG.debug("validateLink: Link is ignored due source node is rejected by node validation - {}",
-                    link.getSource().getSourceNode().getValue());
+                link.getSource().getSourceNode().getValue());
             return false;
         }
         if (dest == null) {
             LOG.debug("validateLink: Link is ignored due dest node is rejected by node validation - {}",
-                    link.getDestination().getDestNode().getValue());
+                link.getDestination().getDestNode().getValue());
             return false;
         }
 
-        PceLink pcelink = new PceLink(link, source, dest);
-        if (!pcelink.isValid()) {
-            dropOppositeLink(link);
-            LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
-            return false;
-        }
+        if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
+            // 100GE or OTU4 services are handled at WDM Layer
+            PceLink pcelink = new PceLink(link, source, dest);
+            if (!pcelink.isValid()) {
+                dropOppositeLink(link);
+                LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
+                return false;
+            }
+            LinkId linkId = pcelink.getLinkId();
+            switch (validateLinkConstraints(pcelink)) {
+                case HARD_EXCLUDE:
+                    dropOppositeLink(link);
+                    LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
+                    return false;
+                default:
+                    break;
+            }
+            switch (pcelink.getlinkType()) {
+                case ROADMTOROADM:
+                case EXPRESSLINK:
+                    allPceLinks.put(linkId, pcelink);
+                    source.addOutgoingLink(pcelink);
+                    LOG.debug("validateLink: {}-LINK added to allPceLinks {}",
+                        pcelink.getlinkType(), pcelink.toString());
+                    break;
+                case ADDLINK:
+                    pcelink.setClient(source.getRdmSrgClient(pcelink.getSourceTP().toString(), true));
+                    addLinks.add(pcelink);
+                    LOG.debug("validateLink: ADD-LINK saved  {}", pcelink.toString());
+                    break;
+                case DROPLINK:
+                    pcelink.setClient(dest.getRdmSrgClient(pcelink.getDestTP().toString(), false));
+                    dropLinks.add(pcelink);
+                    LOG.debug("validateLink: DROP-LINK saved  {}", pcelink.toString());
+                    break;
+                case XPONDERINPUT:
+                    // store separately all SRG links directly
+                    azSrgs.add(sourceId);
+                    // connected to A/Z
+                    if (!dest.checkTP(pcelink.getDestTP().toString())) {
+                        LOG.debug(
+                            "validateLink: XPONDER-INPUT is rejected as NW port is busy - {} ", pcelink.toString());
+                        return false;
+                    }
+                    pcelink.setClient(dest.getClient(pcelink.getDestTP().toString()));
+                    allPceLinks.put(linkId, pcelink);
+                    source.addOutgoingLink(pcelink);
+                    LOG.debug("validateLink: XPONDER-INPUT link added to allPceLinks {}", pcelink.toString());
+                    break;
+                // does it mean XPONDER==>>SRG ?
+                case XPONDEROUTPUT:
+                    // store separately all SRG links directly
+                    azSrgs.add(destId);
+                    // connected to A/Z
+                    if (!source.checkTP(pcelink.getSourceTP().toString())) {
+                        LOG.debug(
+                            "validateLink: XPONDER-OUTPUT is rejected as NW port is busy - {} ", pcelink.toString());
+                        return false;
+                    }
+                    pcelink.setClient(source.getClient(pcelink.getSourceTP().toString()));
+                    allPceLinks.put(linkId, pcelink);
+                    source.addOutgoingLink(pcelink);
+                    LOG.debug("validateLink: XPONDER-OUTPUT link added to allPceLinks {}", pcelink.toString());
+                    break;
+                default:
+                    LOG.warn("validateLink: link type is not supported {}", pcelink.toString());
+            }
+            return true;
 
-        LinkId linkId = pcelink.getLinkId();
+        } else if (("ODU4".equals(serviceType)) || ("10GE".equals(serviceType)) || ("1GE".equals(serviceType))) {
+            // ODU4, 1GE and 10GE services relying on ODU2, ODU2e or ODU0 services are handled at OTN layer
+            PceLink pceOtnLink = new PceLink(link, source, dest);
 
-        switch (validateLinkConstraints(pcelink)) {
-            case HARD_EXCLUDE :
+            if (!pceOtnLink.isOtnValid(link, serviceType)) {
                 dropOppositeLink(link);
-                LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
+                LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
                 return false;
-            default:
-                break;
-        }
+            }
 
-        switch (pcelink.getlinkType()) {
-            case ROADMTOROADM :
-                allPceLinks.put(linkId, pcelink);
-                source.addOutgoingLink(pcelink);
-                LOG.debug("validateLink: ROADMTOROADM-LINK added to allPceLinks {}", pcelink.toString());
-                break;
-            case EXPRESSLINK :
-                allPceLinks.put(linkId, pcelink);
-                source.addOutgoingLink(pcelink);
-                LOG.debug("validateLink: EXPRESS-LINK added to allPceLinks {}", pcelink.toString());
-                break;
-            case ADDLINK :
-                pcelink.setClient(source.getRdmSrgClient(pcelink.getSourceTP().toString(), true));
-                addLinks.add(pcelink);
-                LOG.debug("validateLink: ADD-LINK saved  {}", pcelink.toString());
-                break;
-            case DROPLINK :
-                pcelink.setClient(dest.getRdmSrgClient(pcelink.getDestTP().toString(), false));
-                dropLinks.add(pcelink);
-                LOG.debug("validateLink: DROP-LINK saved  {}", pcelink.toString());
-                break;
-            case XPONDERINPUT :
-                // store separately all SRG links directly
-                azSrgs.add(sourceId);
-                // connected to A/Z
-                if (!dest.checkTP(pcelink.getDestTP().toString())) {
-                    LOG.debug("validateLink: XPONDER-INPUT is rejected as NW port is busy - {} ", pcelink.toString());
-                    return false;
-                }
-                pcelink.setClient(dest.getClient(pcelink.getDestTP().toString()));
-                allPceLinks.put(linkId, pcelink);
-                source.addOutgoingLink(pcelink);
-                LOG.debug("validateLink: XPONDER-INPUT link added to allPceLinks {}", pcelink.toString());
-                break;
-            // does it mean XPONDER==>>SRG ?
-            case XPONDEROUTPUT :
-                // store separately all SRG links directly
-                azSrgs.add(destId);
-                // connected to A/Z
-                if (!source.checkTP(pcelink.getSourceTP().toString())) {
-                    LOG.debug("validateLink: XPONDER-OUTPUT is rejected as NW port is busy - {} ", pcelink.toString());
+            LinkId linkId = pceOtnLink.getLinkId();
+            switch (validateLinkConstraints(pceOtnLink)) {
+                case HARD_EXCLUDE:
+                    dropOppositeLink(link);
+                    LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
                     return false;
-                }
-                pcelink.setClient(source.getClient(pcelink.getSourceTP().toString()));
-                allPceLinks.put(linkId, pcelink);
-                source.addOutgoingLink(pcelink);
-                LOG.debug("validateLink: XPONDER-OUTPUT link added to allPceLinks {}", pcelink.toString());
-                break;
-            default:
-                LOG.warn("validateLink: link type is not supported {}", pcelink.toString());
+                default:
+                    break;
+            }
+            switch (pceOtnLink.getlinkType()) {
+                case OTNLINK:
+                    allPceLinks.put(linkId, pceOtnLink);
+                    source.addOutgoingLink(pceOtnLink);
+                    LOG.debug("validateLink: OTN-LINK added to allPceLinks {}", pceOtnLink.toString());
+                    break;
+                default:
+                    LOG.warn("validateLink: link type is not supported {}", pceOtnLink.toString());
+            }
+            return true;
 
+        } else {
+            LOG.error(" validateLink: Unmanaged service type {}", serviceType);
+            return false;
         }
 
-        return true;
     }
 
     private boolean validateNode(Node node) {
@@ -353,7 +477,7 @@ public class PceCalculation {
         }
         OpenroadmNodeType nodeType = node1.getNodeType();
 
-        PceNode pceNode = new PceNode(node,nodeType,node.getNodeId());
+        PceNode pceNode = new PceNode(node, nodeType, node.getNodeId());
         pceNode.validateAZxponder(anodeId, znodeId);
         pceNode.initWLlist();
 
@@ -363,28 +487,19 @@ public class PceCalculation {
         }
 
         switch (validateNodeConstraints(pceNode)) {
-            case HARD_EXCLUDE :
+            case HARD_EXCLUDE:
                 return false;
 
-            default :
+            default:
                 break;
         }
-
-        if (pceNode.getSupNodeIdPceNode().equals(this.anodeId)) {
-            if (this.aendPceNode != null) {
-                LOG.debug("aendPceNode already gets: {}", this.aendPceNode);
-            } else if (endPceNode(nodeType,pceNode.getNodeId(), pceNode)) {
-                this.aendPceNode = pceNode;
-            }
-            // returning false otherwise would break E2E test
+        if ((pceNode.getSupNetworkNodeIdPceNode().equals(anodeId) && (this.aendPceNode == null))
+            && (endPceNode(nodeType, pceNode.getNodeId(), pceNode))) {
+            this.aendPceNode = pceNode;
         }
-        if (pceNode.getSupNodeIdPceNode().equals(this.znodeId)) {
-            if (this.zendPceNode != null) {
-                LOG.debug("zendPceNode already gets: {}", this.zendPceNode);
-            } else if (endPceNode(nodeType,pceNode.getNodeId(), pceNode)) {
-                this.zendPceNode = pceNode;
-            }
-            // returning false otherwise would break E2E test
+        if ((pceNode.getSupNetworkNodeIdPceNode().equals(znodeId) && (this.zendPceNode == null))
+            && (endPceNode(nodeType, pceNode.getNodeId(), pceNode))) {
+            this.zendPceNode = pceNode;
         }
 
         allPceNodes.put(pceNode.getNodeId(), pceNode);
@@ -392,13 +507,58 @@ public class PceCalculation {
         return true;
     }
 
+    private OpenroadmNodeType validateOtnNode(Node node, String mode) {
+
+        LOG.debug("validateNode: node {} ", node.toString());
+        // PceOtnNode will be used in Graph algorithm
+        Node1 node1 = node.augmentation(Node1.class);
+        if (node1 == null) {
+            LOG.error("getNodeType: no Node1 (type) Augmentation for node: [{}]. Node is ignored", node.getNodeId());
+        }
+        OpenroadmNodeType nodeType = node1.getNodeType();
+
+        PceOtnNode pceOtnNode = new PceOtnNode(node, nodeType, node.getNodeId(), serviceType);
+        if (mode == "AZ") {
+            pceOtnNode.validateAZxponder(anodeId, znodeId);
+        } else if (mode == "intermediate") {
+            pceOtnNode.validateIntermediateSwitch();
+        } else {
+            LOG.error("validateOtnNode: unproper mode passed to the method : {} not supported", mode);
+            return null;
+        }
+
+        if (!pceOtnNode.isValid()) {
+            LOG.warn(" validateNode: Node is ignored");
+            return null;
+        }
+
+        switch (validateNodeConstraints(pceOtnNode)) {
+            case HARD_EXCLUDE:
+                return null;
+
+            default:
+                break;
+        }
+
+        if ((pceOtnNode.getNodeId().equals(anodeId))) {
+            this.aendPceNode = pceOtnNode;
+        }
+        if ((pceOtnNode.getNodeId().equals(znodeId))) {
+            this.zendPceNode = pceOtnNode;
+        }
+
+        allPceNodes.put(pceOtnNode.getNodeId(), pceOtnNode);
+        LOG.debug("validateNode: node is saved {}", pceOtnNode.getNodeId().getValue());
+        return nodeType;
+    }
+
     private ConstraintTypes validateNodeConstraints(PceNode pcenode) {
 
         if (pceHardConstraints.getExcludeSupNodes().isEmpty() && pceHardConstraints.getExcludeCLLI().isEmpty()) {
             return ConstraintTypes.NONE;
         }
 
-        if (pceHardConstraints.getExcludeSupNodes().contains(pcenode.getSupNodeIdPceNode())) {
+        if (pceHardConstraints.getExcludeSupNodes().contains(pcenode.getSupNetworkNodeIdPceNode())) {
             LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue());
             return ConstraintTypes.HARD_EXCLUDE;
         }
@@ -443,11 +603,11 @@ public class PceCalculation {
 
     private Boolean endPceNode(OpenroadmNodeType openroadmNodeType, NodeId nodeId, PceNode pceNode) {
         switch (openroadmNodeType) {
-            case SRG :
+            case SRG:
                 pceNode.initSrgTps();
                 this.azSrgs.add(nodeId);
                 break;
-            case XPONDER :
+            case XPONDER:
                 pceNode.initXndrTps();
                 break;
             default:
@@ -478,6 +638,10 @@ public class PceCalculation {
         return this.allPceLinks;
     }
 
+    public String getServiceType() {
+        return serviceType;
+    }
+
     public PceResult getReturnStructure() {
         return returnStructure;
     }
@@ -491,11 +655,4 @@ public class PceCalculation {
         }
     }
 
-    /*private static void printLinksInfo(Map<LinkId, PceLink> allpcelinks) {
-        Iterator<Map.Entry<LinkId, PceLink>> links = allpcelinks.entrySet().iterator();
-        while (links.hasNext()) {
-            LOG.info("In printLinksInfo link {} : ", links.next().getValue().toString());
-        }
-    }*/
-
 }
index 58215e8f29513d170fe34ed6c1ef8c934869ef8d..9929b4dc02ba90e0e6052372056dc41b2ca33c8e 100644 (file)
@@ -30,6 +30,8 @@ public class PceLink {
      */
     double weight = 0;
     private boolean isValid = true;
+    private boolean isOtnValid = true;
+
     // this member is for XPONDER INPUT/OUTPUT links.
     // it keeps name of client corresponding to NETWORK TP
     private String client = "";
@@ -41,10 +43,13 @@ public class PceLink {
     private final Object destTP;
     private final String sourceSupNodeId;
     private final String destSupNodeId;
+    private final String sourceNetworkSupNodeId;
+    private final String destNetworkSupNodeId;
     private final String sourceCLLI;
     private final String destCLLI;
     private final LinkId oppositeLink;
     private final Long latency;
+    private final Long availableBandwidth;
     private final List<Long> srlgList;
     private final double osnr;
     private final Span omsAttributesSpan;
@@ -67,9 +72,11 @@ public class PceLink {
 
         this.sourceSupNodeId = source.getSupNodeIdPceNode();
         this.destSupNodeId = dest.getSupNodeIdPceNode();
+        this.sourceNetworkSupNodeId = source.getSupNetworkNodeIdPceNode();
+        this.destNetworkSupNodeId = dest.getSupNetworkNodeIdPceNode();
 
-        this.sourceCLLI = source.getCLLI();
-        this.destCLLI = dest.getCLLI();
+        this.sourceCLLI = source.getClliSupNodeId();
+        this.destCLLI = dest.getClliSupNodeId();
 
         this.linkType = MapUtils.calcType(link);
 
@@ -80,13 +87,20 @@ public class PceLink {
             this.srlgList = MapUtils.getSRLG(link);
             this.latency = calcLatency(link);
             this.osnr = calcSpanOSNR();
+            this.availableBandwidth = 0L;
+        } else if (this.linkType == OpenroadmLinkType.OTNLINK) {
+            this.availableBandwidth = MapUtils.getAvailableBandwidth(link);
+            this.srlgList = MapUtils.getSRLGfromLink(link);
+            this.osnr = 0.0;
+            this.latency = 0L;
+            this.omsAttributesSpan = null;
         } else {
             this.omsAttributesSpan = null;
             this.srlgList = null;
             this.latency = 0L;
             this.osnr = 100L; //infinite OSNR in DB
+            this.availableBandwidth = 0L;
         }
-
         LOG.debug("PceLink: created PceLink  {}", toString());
     }
 
@@ -210,14 +224,27 @@ public class PceLink {
         return latency.doubleValue();
     }
 
+    public Long getAvailableBandwidth() {
+        return availableBandwidth;
+    }
+
+
     public String getsourceSupNodeId() {
         return sourceSupNodeId;
     }
 
+    public String getsourceNetworkSupNodeId() {
+        return sourceNetworkSupNodeId;
+    }
+
     public String getdestSupNodeId() {
         return destSupNodeId;
     }
 
+    public String getdestNetworkSupNodeId() {
+        return destNetworkSupNodeId;
+    }
+
     public List<Long> getsrlgList() {
         return srlgList;
     }
@@ -265,6 +292,62 @@ public class PceLink {
         return isValid;
     }
 
+    public boolean isOtnValid(Link link, String oduType) {
+        if (this.linkType == OpenroadmLinkType.OTNLINK) {
+            isOtnValid = false;
+            Long availableBW = MapUtils.getAvailableBandwidth(link);
+            if ((availableBW == 0L) || (availableBW == null)) {
+                LOG.error("PceLink: No bandwidth available or not valid OTN Link, Link {}  is ignored ", linkId);
+            } else if (("ODU4".equals(oduType)) && (availableBW == 100000L)) {
+                isOtnValid = true;
+                LOG.debug("PceLink: Selected OTU4 Link {} is eligible for ODU creation OTN Link", linkId);
+            } else if (("ODU2".equals(oduType)) || ("ODU2e".equals(oduType)) && (availableBW >= 12500L)) {
+                isOtnValid = true;
+                LOG.debug("PceLink: Selected ODU4 Link {} has available bandwidth and is eligible for {} creation ",
+                    linkId, oduType);
+            } else if (("ODU0".equals(oduType)) && (availableBW >= 1250L)) {
+                isOtnValid = true;
+                LOG.debug("PceLink: Selected ODU4 Link {} has available bandwidth and is eligible for {} creation ",
+                    linkId, oduType);
+            } else if (("ODU1".equals(oduType)) && (availableBW >= 2500L)) {
+                isOtnValid = true;
+                LOG.debug("PceLink: Selected ODU4 Link {} has available bandwidth and is eligible for {} creation ",
+                    linkId, oduType);
+            } else {
+                isOtnValid = false;
+                LOG.error(
+                    "PceLink: Selected OTN Link {} is not eligible for ODU creation: not enough available bandwidth",
+                    linkId);
+            }
+
+        } else {
+            isOtnValid = false;
+            LOG.error("PceLink: Not an OTN link. Link is ignored {}", linkId);
+        }
+
+        if ((this.linkId == null) || (this.linkType == null)
+                || (this.oppositeLink == null)) {
+            isOtnValid = false;
+            LOG.error("PceLink: No Link type or opposite link is available. Link is ignored {}", linkId);
+        }
+        if ((this.sourceId == null) || (this.destId == null)
+                || (this.sourceTP == null) || (this.destTP == null)) {
+            isOtnValid = false;
+            LOG.error("PceLink: No Link source or destination is available. Link is ignored {}", linkId);
+        }
+        if ((this.sourceNetworkSupNodeId.equals("")) || (this.destNetworkSupNodeId.equals(""))) {
+            isOtnValid = false;
+            LOG.error("PceLink: No Link source SuppNodeID or destination SuppNodeID is available. Link is ignored {}",
+                linkId);
+        }
+        if ((this.sourceCLLI.equals("")) || (this.destCLLI.equals(""))) {
+            isOtnValid = false;
+            LOG.error("PceLink: No Link source CLLI or destination CLLI is available. Link is ignored {}", linkId);
+        }
+
+        return isOtnValid;
+    }
+
     public String toString() {
         return "PceLink type=" + linkType + " ID=" + linkId.getValue() + " latency=" + latency;
     }
index c869f16757d785ad0995bd092fd89ecaa9209ef8..52e01056ac19ec6af2a7aa5c992528536922b1a8 100644 (file)
@@ -15,6 +15,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.TreeMap;
 
+import org.opendaylight.transportpce.common.NetworkUtils;
 import org.opendaylight.transportpce.pce.SortPortsByName;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.TerminationPoint1;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.Node1;
@@ -35,10 +36,11 @@ public class PceNode {
 
     private boolean valid = true;
 
-    private final Node node;
-    private final NodeId nodeId;
-    private final OpenroadmNodeType nodeType;
+    protected final Node node;
+    protected final NodeId nodeId;
+    protected final OpenroadmNodeType nodeType;
     private final String supNodeId;
+    private final String supNetworkNodeId;
     private final String clli;
 
     // wavelength calculation per node type
@@ -48,13 +50,19 @@ public class PceNode {
     private List<String> usedXpndrNWTps = new ArrayList<String>();
     private List<PceLink> outgoingLinks = new ArrayList<PceLink>();
     private Map<String, String> clientPerNwTp = new HashMap<String, String>();
+    private Map<String,List<Integer>> tpAvailableTribPort = new TreeMap<String,List<Integer>>();
+    private Map<String,List<Integer>> tpAvailableTribSlot = new TreeMap<String,List<Integer>>();
 
     public PceNode(Node node, OpenroadmNodeType nodeType, NodeId nodeId) {
         this.node = node;
         this.nodeId = nodeId;
         this.nodeType = nodeType;
         this.supNodeId = getSupNodeId(node);
-        this.clli = MapUtils.getCLLI(node);
+        this.supNetworkNodeId = getNetworkSupNodeId(node);
+        //this.clli = MapUtils.getCLLI(node);
+        this.clli = getClliSupNodeId(node);
+        this.tpAvailableTribPort.clear();
+        this.tpAvailableTribSlot.clear();
 
         if ((node == null) || (nodeId == null) || (nodeType == null)) {
             LOG.error("PceNode: one of parameters is not populated : nodeId, node type");
@@ -289,23 +297,49 @@ public class PceNode {
         }
     }
 
+    private String getClliSupNodeId(Node inputNode) {
+        TreeMap<String, String> allSupNodes = new TreeMap<String, String>();
+        String tempNetworkSupNodeId = "";
+        allSupNodes = MapUtils.getAllSupNode(inputNode);
+        if (allSupNodes.get(NetworkUtils.CLLI_NETWORK_ID) == null) {
+            LOG.error("getClliSupNodeId: No Supporting node at CLLI layer for node: [{}].", inputNode.getNodeId());
+        } else {
+            tempNetworkSupNodeId = allSupNodes.get(NetworkUtils.CLLI_NETWORK_ID);
+        }
+        return tempNetworkSupNodeId;
+    }
+
+    public String getClliSupNodeId() {
+        return clli;
+    }
+
+    private String getNetworkSupNodeId(Node inputNode) {
+        TreeMap<String, String> allSupNodes = new TreeMap<String, String>();
+        String tempNetworkSupNodeId = "";
+        allSupNodes = MapUtils.getAllSupNode(inputNode);
+        if (allSupNodes.get(NetworkUtils.UNDERLAY_NETWORK_ID) == null) {
+            LOG.error(
+                "getNetworkSupNodeId: No Supporting node at NETWORK layer for node: [{}].", inputNode.getNodeId());
+        } else {
+            tempNetworkSupNodeId = allSupNodes.get(NetworkUtils.UNDERLAY_NETWORK_ID);
+        }
+        return tempNetworkSupNodeId;
+    }
+
+
     public void validateAZxponder(String anodeId, String znodeId) {
         if (!isValid()) {
             return;
         }
-
         if (this.nodeType != OpenroadmNodeType.XPONDER) {
             return;
         }
-
         // Detect A and Z
-        if (this.supNodeId.equals(anodeId) || (this.supNodeId.equals(znodeId))) {
-
+        if (this.supNetworkNodeId.equals(anodeId) || (this.supNetworkNodeId.equals(znodeId))) {
             LOG.info("validateAZxponder: A or Z node detected == {}", nodeId.getValue());
             initXndrTps();
             return;
         }
-
         LOG.debug("validateAZxponder: XPONDER is ignored == {}", nodeId.getValue());
         valid = false;
     }
@@ -323,7 +357,7 @@ public class PceNode {
     }
 
     public boolean isValid() {
-        if ((node == null) || (nodeId == null) || (nodeType == null) || (supNodeId == null) || (clli == null)) {
+        if ((node == null) || (nodeId == null) || (nodeType == null) || (supNetworkNodeId == null) || (clli == null)) {
             LOG.error("PceNode: one of parameters is not populated : nodeId, node type, supporting nodeId");
             valid = false;
         }
@@ -354,6 +388,10 @@ public class PceNode {
         return supNodeId;
     }
 
+    public String getSupNetworkNodeIdPceNode() {
+        return supNetworkNodeId;
+    }
+
     public String getCLLI() {
         return clli;
     }
@@ -366,4 +404,12 @@ public class PceNode {
         LOG.info(" outgoing links of node {} : {} ", nodeId.getValue(), this.getOutgoingLinks().toString());
     }
 
+    public Map<String,List<Integer>> getAvailableTribPorts() {
+        return tpAvailableTribPort;
+    }
+
+    public Map<String,List<Integer>> getAvailableTribSlots() {
+        return tpAvailableTribSlot;
+    }
+
 }
diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceOtnNode.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceOtnNode.java
new file mode 100644 (file)
index 0000000..9da697f
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * Copyright Â© 2019 Orange, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.transportpce.pce.networkanalyzer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+//import java.util.Optional;
+import java.util.TreeMap;
+
+//import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.transportpce.common.NetworkUtils;
+//import org.opendaylight.transportpce.pce.SortPortsByName;
+//import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.Node1;
+//import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.TerminationPoint1;
+//import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.networks
+//.network.node.termination.point.pp.attributes.UsedWavelength;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev181130.xpdr.odu.switching.pools.OduSwitchingPools;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.types.rev181130.xpdr.odu.switching.pools.odu.switching.pools.NonBlockingList;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmNodeType;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmTpType;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.xpdr.tp.supported.interfaces.SupportedInterfaceCapability;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev181130.ODTU4TsAllocated;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.TerminationPoint1;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.networks.network.node.SwitchingPools;
+//import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev181130.If100GEODU4;
+//import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev181130.If10GEODU2e;
+//import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev181130.If1GEODU0;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.xponder.rev181130.xpdr.otn.tp.attributes.OdtuTpnPool;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PceOtnNode extends PceNode {
+    /* Logging. */
+    private static final Logger LOG = LoggerFactory.getLogger(PceCalculation.class);
+    ////////////////////////// OTN NODES ///////////////////////////
+    /*
+     * For This Class the node passed shall be at the otn-openroadm Layer
+     */
+
+    private boolean valid = true;
+
+    private final String supNetworkNodeId;
+    private final String supTopoNodeId;
+    private final String clli;
+    private final String otnServiceType;
+
+    private Map<String, List<Integer>> tpAvailableTribPort = new TreeMap<String, List<Integer>>();
+    private Map<String, List<Integer>> tpAvailableTribSlot = new TreeMap<String, List<Integer>>();
+    private Map<String, OpenroadmTpType> availableXponderTp = new TreeMap<String, OpenroadmTpType>();
+    private List<String> usedXpdrNWTps = new ArrayList<String>();
+    private List<String> unusableXpdrNWTps = new ArrayList<String>();
+    private List<String> usedXpdrClientTps = new ArrayList<String>();
+    private List<String> unusableXpdrClientTps = new ArrayList<String>();
+    private List<PceLink> outgoingLinks = new ArrayList<PceLink>();
+    private Map<String, String> clientPerNwTp = new HashMap<String, String>();
+
+    public PceOtnNode(Node node, OpenroadmNodeType nodeType, NodeId nodeId, String serviceType) {
+        super(node, nodeType, nodeId);
+        this.supNetworkNodeId = getNetworkSupNodeId(node);
+        this.supTopoNodeId = getTopoSupNodeId(node);
+        this.clli = getClliSupNodeId(node);
+        this.otnServiceType = serviceType;
+        this.tpAvailableTribPort.clear();
+        this.tpAvailableTribSlot.clear();
+        this.usedXpdrNWTps.clear();
+        this.unusableXpdrNWTps.clear();
+        this.usedXpdrClientTps.clear();
+        this.unusableXpdrClientTps.clear();
+
+        if ((node == null) || (nodeId == null) || (nodeType == null)) {
+            LOG.error("PceOtnNode: one of parameters is not populated : nodeId, node type");
+            this.valid = false;
+        }
+    }
+
+    public void initXndrTps(String mode) {
+        LOG.info("initXndrTps for node : {}", this.nodeId);
+        int availableNetworkTpNumber = 0;
+        int availableClientTpNumber = 0;
+
+        this.availableXponderTp.clear();
+
+        if (!isValid()) {
+            return;
+        }
+        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1 nodeTp =
+            this.node.augmentation(
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1.class);
+        List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
+            .network.node.TerminationPoint> allTps = nodeTp.getTerminationPoint();
+        this.valid = false;
+        if (allTps == null) {
+            LOG.error("initXndrTps: XPONDER TerminationPoint list is empty for node {}", this.toString());
+            return;
+        }
+
+        for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
+                .network.node.TerminationPoint tp : allTps) {
+            TerminationPoint1 otnTp1 = tp.augmentation(TerminationPoint1.class);
+            //TODO many nested if-structures below, this needs to be reworked
+            if (otnTp1.getTpType() == OpenroadmTpType.XPONDERNETWORK) {
+                if (otnTp1.getXpdrTpPortConnectionAttributes().getWavelength() != null) {
+                    this.usedXpdrNWTps.add(tp.getTpId().getValue());
+                } else {
+                    // find server of this network TP
+                    String server = otnTp1.getXpdrTpPortConnectionAttributes().getTailEquipmentId();
+                    if ((server.equals("")) || (server == null)) {
+                        this.unusableXpdrNWTps.add(tp.getTpId().getValue());
+                    } else {
+                        // tp is not used and as a tail to server WDM layer
+                        if (("10GE".equals(this.otnServiceType)) || ("1GE".equals(this.otnServiceType))) {
+                            // LO-ODU needs to be created on a parent HO-ODU
+                            // interface
+                            List<OdtuTpnPool> presenceOdtu =
+                                otnTp1.getXpdrTpPortConnectionAttributes().getOdtuTpnPool();
+                            if (presenceOdtu == null) {
+                                this.unusableXpdrNWTps.add(tp.getTpId().getValue());
+                            } else {
+                                List<SupportedInterfaceCapability> sic =
+                                    otnTp1.getTpSupportedInterfaces().getSupportedInterfaceCapability();
+                                if ((findNetworkCompliantInterface(sic)) & (checkAvailableTribPort(tp))
+                                    & (checkAvailableTribSlot(tp))) {
+                                    this.availableXponderTp.put(tp.getTpId().getValue(),
+                                        OpenroadmTpType.XPONDERNETWORK);
+                                    availableNetworkTpNumber++;
+                                }
+                                /*
+                                 * Add the retrieval of outgoing ingoing links
+                                 * through an external function
+                                 */
+                            }
+                        } else {
+                            // service is HO service
+                            List<SupportedInterfaceCapability> sic =
+                                otnTp1.getTpSupportedInterfaces().getSupportedInterfaceCapability();
+                            if (findNetworkCompliantInterface(sic)) {
+                                this.availableXponderTp.put(tp.getTpId().getValue(), OpenroadmTpType.XPONDERNETWORK);
+                                availableNetworkTpNumber++;
+                                /*
+                                 * Add the retrieval of outgoing ingoing links
+                                 * through an external function
+                                 */
+                            } else {
+                                this.unusableXpdrNWTps.add(tp.getTpId().getValue());
+
+                            }
+
+                        }
+
+                    }
+
+                }
+
+                // The port is not a network port
+            } else if (otnTp1.getTpType() == OpenroadmTpType.XPONDERCLIENT) {
+                // For Client port we verify that it supports needed interfaces
+                // TBD : How shall we check a client port is available and not
+                // in use?
+                List<SupportedInterfaceCapability> sic =
+                    otnTp1.getTpSupportedInterfaces().getSupportedInterfaceCapability();
+                if (findClientCompliantInterface(sic)) {
+                    this.availableXponderTp.put(tp.getTpId().getValue(), OpenroadmTpType.XPONDERCLIENT);
+                    availableClientTpNumber++;
+                }
+            }
+            LOG.debug("initXndrTps: XPONDER tp = {} is used", tp.getTpId().getValue());
+            LOG.error("initXndrTps: XPONDER {} NW TP doesn't have defined server ROADM SRG {}", this.toString(), tp
+                .getTpId().getValue());
+        }
+        if ("AZ".equals(mode)) {
+            if ((availableClientTpNumber >= 1) || (availableNetworkTpNumber >= 1)) {
+                // for A and Z node we need to have one valid client port & one
+                // valid network port
+                this.valid = true;
+            }
+        } else if ("intermediate".equals(mode)) {
+            if ((availableNetworkTpNumber >= 2)) {
+                // for OTN switching node used in transit we need to have two
+                // valid network ports
+                this.valid = true;
+            }
+        }
+
+        if (!isValid()) {
+            LOG.debug("initXndrTps: XPONDER doesn't have the required ports available  {}", this.toString());
+            return;
+        } else {
+            LOG.debug("initXndrTps: XPONDER {} is elligible", this.toString());
+        }
+    }
+
+    private Boolean findClientCompliantInterface(List<SupportedInterfaceCapability> sic) {
+        boolean compliant = false;
+        for (SupportedInterfaceCapability sit : sic) {
+            String interfacetype = sit.getIfCapType().toString();
+            switch (interfacetype) {
+                case "If1GEODU0":
+                case "If1GE":
+                    if ("1GE".equals(this.otnServiceType)) {
+                        compliant = true;
+                    }
+                    break;
+                case "If10GEODU2e":
+                case "If10GE":
+                    if ("10GE".equals(this.otnServiceType)) {
+                        compliant = true;
+                    }
+                    break;
+                case "If100GEODU4":
+                case "If100GE":
+                    if ("100GE".equals(this.otnServiceType)) {
+                        compliant = true;
+                    }
+                    break;
+                case "IfOTU4ODU4":
+                case "IfOCHOTU4ODU4":
+                    if (("OTU4".equals(this.otnServiceType)) || ("ODU4".equals(this.otnServiceType))) {
+                        compliant = true;
+                    }
+                    break;
+                default:
+                    compliant = false;
+                    break;
+            }
+
+        }
+        return compliant;
+    }
+
+    private Boolean findNetworkCompliantInterface(List<SupportedInterfaceCapability> sic) {
+        boolean compliant = false;
+        for (SupportedInterfaceCapability sit : sic) {
+            String interfacetype = sit.getIfCapType().toString();
+            switch (interfacetype) {
+                case "IfOTU4ODU4":
+                case "IfOCHOTU4ODU4":
+                    compliant = true;
+                    break;
+                case "IfOTU2ODU2":
+                case "IfOCHOTU2ODU2":
+                    if (("1GE".equals(this.otnServiceType)) || ("10GE".equals(this.otnServiceType))) {
+                        compliant = true;
+                    }
+                    break;
+                // add all use case with higher rate interfaces when it shows up
+                default:
+                    compliant = false;
+                    break;
+            }
+
+        }
+        return compliant;
+    }
+
+    private String getClliSupNodeId(Node inputNode) {
+        TreeMap<String, String> allSupNodes = new TreeMap<String, String>();
+        String tempNetworkSupNodeId = "";
+        allSupNodes = MapUtils.getAllSupNode(inputNode);
+        if (allSupNodes.get(NetworkUtils.CLLI_NETWORK_ID) == null) {
+            LOG.error("getClliSupNodeId: No Supporting node at CLLI layer for node: [{}].", inputNode.getNodeId());
+        } else {
+            tempNetworkSupNodeId = allSupNodes.get(NetworkUtils.CLLI_NETWORK_ID);
+        }
+        return tempNetworkSupNodeId;
+    }
+
+    private String getNetworkSupNodeId(Node inputNode) {
+        TreeMap<String, String> allSupNodes = new TreeMap<String, String>();
+        String tempNetworkSupNodeId = "";
+        allSupNodes = MapUtils.getAllSupNode(inputNode);
+        if (allSupNodes.get(NetworkUtils.UNDERLAY_NETWORK_ID) == null) {
+            LOG.error(
+                "getNetworkSupNodeId: No Supporting node at NETWORK layer for node: [{}].", inputNode.getNodeId());
+        } else {
+            tempNetworkSupNodeId = allSupNodes.get(NetworkUtils.UNDERLAY_NETWORK_ID);
+        }
+        return tempNetworkSupNodeId;
+    }
+
+    private String getTopoSupNodeId(Node inputNode) {
+        TreeMap<String, String> allSupNodes = new TreeMap<String, String>();
+        String tempTopoSupNodeId = "";
+        allSupNodes = MapUtils.getAllSupNode(inputNode);
+        if (allSupNodes.get(NetworkUtils.OVERLAY_NETWORK_ID) == null) {
+            LOG.error(
+                "getTopologySupNodeId: No Supporting node at TOPOLOGY layer for node: [{}].", inputNode.getNodeId());
+        } else {
+            tempTopoSupNodeId = allSupNodes.get(NetworkUtils.OVERLAY_NETWORK_ID);
+        }
+        return tempTopoSupNodeId;
+    }
+
+    public void validateAZxponder(String anodeId, String znodeId) {
+        if (!isValid()) {
+            return;
+        }
+        if ((this.nodeType != OpenroadmNodeType.MUXPDR) & (this.nodeType != OpenroadmNodeType.SWITCH)
+            & (this.nodeType != OpenroadmNodeType.TPDR)) {
+            return;
+        }
+        // Detect A and Z, a/znodeId correspond to otn layer, supporting node
+        // might be of Network or Topology layer
+        if (this.nodeId.equals(anodeId) || (this.nodeId.equals(znodeId))) {
+            initXndrTps("AZ");
+            if (!this.valid) {
+                LOG.debug("validateAZxponder: XPONDER unusable for A or Z == {}", nodeId.getValue());
+            } else {
+                LOG.info("validateAZxponder: A or Z node detected and validated == {}", nodeId.getValue());
+            }
+            return;
+        } else {
+            LOG.debug("validateAZxponder: XPONDER is ignored == {}", nodeId.getValue());
+            valid = false;
+        }
+
+    }
+
+    public boolean validateSwitchingPoolBandwidth(
+            Node node,
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
+                .network.node.TerminationPoint tp1,
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
+                .network.node.TerminationPoint tp2,
+            Long neededBW) {
+        Long availableBW = 0L;
+        if (this.nodeType != OpenroadmNodeType.TPDR) {
+            return true;
+        } else {
+            org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.Node1 node1 =
+                node.augmentation(
+                    org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.Node1.class);
+            SwitchingPools sp = node1.getSwitchingPools();
+            List<OduSwitchingPools> osp = new ArrayList<OduSwitchingPools>();
+            osp = sp.getOduSwitchingPools();
+            for (OduSwitchingPools ospx : osp) {
+                List<NonBlockingList> nbl = ospx.getNonBlockingList();
+                for (NonBlockingList nbll : nbl) {
+                    if (nbll.getAvailableInterconnectBandwidth() >= neededBW) {
+                        List<TpId> tplist = new ArrayList<TpId>(nbll.getTpList());
+                        if ((tplist.contains(tp1.getTpId())) & (tplist.contains(tp2.getTpId()))) {
+                            LOG.debug("validateSwitchingPoolBandwidth: couple  of tp {} x {} valid for crossconnection",
+                                tp1.getTpId().toString(), tp2.getTpId().toString());
+                            return true;
+                        }
+                    }
+                }
+
+            }
+            LOG.debug("validateSwitchingPoolBandwidth: No valid Switching pool for crossconnecting tp {} and {}",
+                tp1.getTpId().toString(), tp2.getTpId().toString());
+            return false;
+        }
+
+    }
+
+    public void validateIntermediateSwitch() {
+        if (!isValid()) {
+            return;
+        }
+        if (this.nodeType != OpenroadmNodeType.SWITCH) {
+            return;
+        }
+        // Validate switch for use as an intermediate XPONDER on the path
+        initXndrTps("intermediate");
+        if (!this.valid) {
+            LOG.debug("validateIntermediateSwitch: Switch unusable for transit == {}", nodeId.getValue());
+        } else {
+            LOG.info("validateIntermediateSwitch: Switch usable for transit == {}", nodeId.getValue());
+        }
+        return;
+
+    }
+
+    public boolean checkAvailableTribPort(
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
+                    .network.node.TerminationPoint tp) {
+        boolean compatibleSupInt = false;
+        TerminationPoint1 otnTp1 = tp.augmentation(TerminationPoint1.class);
+        if (otnTp1.getTpType() == OpenroadmTpType.XPONDERNETWORK) {
+            try {
+                List<OdtuTpnPool> otpp = otnTp1.getXpdrTpPortConnectionAttributes().getOdtuTpnPool();
+
+                for (OdtuTpnPool otppi : otpp) {
+                    if (otppi.getOdtuType().getClass().equals(ODTU4TsAllocated.class)) {
+                        this.tpAvailableTribPort.put(tp.getTpId().getValue(), otppi.getTpnPool());
+                        LOG.debug("checkAvailableTribPort: tp {} and his trib Ports have been added to "
+                            + "tpAvailableTribPortMap", tp.getTpId().getValue());
+                        compatibleSupInt = true;
+
+                    }
+                }
+            } catch (NullPointerException e) {
+                LOG.debug("checkAvailableTribPort: OdtuTpnPool not present for tp {} ", tp.getTpId().toString());
+            }
+
+        } else {
+            LOG.debug("checkAvailableTribPort: tp {} has no odtu tpn Pool", tp.getTpId().getValue());
+        }
+        return compatibleSupInt;
+    }
+
+    public boolean checkAvailableTribSlot(
+            org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks
+                .network.node.TerminationPoint tp) {
+        boolean compatibleSupInt = false;
+        TerminationPoint1 otnTp1 = tp.augmentation(TerminationPoint1.class);
+        if (otnTp1.getTpType() == OpenroadmTpType.XPONDERNETWORK) {
+            List<OdtuTpnPool> otpp;
+            try {
+                otpp = otnTp1.getXpdrTpPortConnectionAttributes().getOdtuTpnPool();
+
+                for (OdtuTpnPool otppi : otpp) {
+                    if (otppi.getOdtuType().getClass().equals(ODTU4TsAllocated.class)) {
+                        this.tpAvailableTribSlot.put(
+                            tp.getTpId().getValue(),
+                            otnTp1.getXpdrTpPortConnectionAttributes().getTsPool());
+                        LOG.debug(
+                            "checkAvailableTribPort: tp {} and its trib Slots were added to tpAvailableTribSlotMap",
+                            tp.getTpId().getValue());
+                        compatibleSupInt = true;
+
+                    }
+                }
+
+            } catch (NullPointerException e) {
+                LOG.debug("checkAvailableTribSlot: OdtuTpnPool not present for tp {} ", tp.getTpId().toString());
+            }
+        } else {
+            LOG.debug("checkAvailableTribPort: tp {} is not a network Port", tp.getTpId().getValue());
+        }
+        return compatibleSupInt;
+    }
+
+    public String getXpdrClient(String tp) {
+        return this.clientPerNwTp.get(tp);
+    }
+
+    public boolean checkTP(String tp) {
+        return !((this.usedXpdrNWTps.contains(tp)) || (this.usedXpdrClientTps.contains(tp))
+            || (this.unusableXpdrNWTps.contains(tp)) || (this.unusableXpdrClientTps.contains(tp)));
+    }
+
+    public boolean isValid() {
+        if ((node == null) || (nodeId == null) || (nodeType == null) || (supNetworkNodeId == null) || (clli == null)) {
+            LOG.error("PceNode: one of parameters is not populated : nodeId, node type, supporting nodeId");
+            valid = false;
+        }
+        return valid;
+    }
+
+    public Map<String, OpenroadmTpType> getAvailableTps() {
+        return availableXponderTp;
+    }
+
+    public void addOutgoingLink(PceLink outLink) {
+        this.outgoingLinks.add(outLink);
+    }
+
+    public List<PceLink> getOutgoingLinks() {
+        return outgoingLinks;
+    }
+
+    public String getClient(String tp) {
+        return clientPerNwTp.get(tp);
+    }
+
+    public String getTopoSupNodeIdPceNode() {
+        return supTopoNodeId;
+    }
+
+    public String getNetworkSupNodeIdPceNode() {
+        return supNetworkNodeId;
+    }
+
+    public String getCLLI() {
+        return clli;
+    }
+
+    public String toString() {
+        return "PceNode type=" + nodeType + " ID=" + nodeId.getValue() + " CLLI=" + clli;
+    }
+
+    public void printLinksOfNode() {
+        LOG.info(" outgoing links of node {} : {} ", nodeId.getValue(), this.getOutgoingLinks().toString());
+    }
+
+    public Map<String, List<Integer>> getAvailableTribPorts() {
+        return tpAvailableTribPort;
+    }
+
+    public Map<String, List<Integer>> getAvailableTribSlots() {
+        return tpAvailableTribSlot;
+    }
+
+}
index abce70280999dc79d203304105e8ecfc8daebaa3..aea19299ff1f855c71e3e8e67347f0c5ad330f62 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.transportpce.pce.networkanalyzer;
 
 import org.opendaylight.transportpce.common.ResponseCodes;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.AToZDirection;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ZToADirection;
 
@@ -22,6 +23,7 @@ public class PceResult {
     private String responseCode = ResponseCodes.RESPONSE_FAILED;
     private long resultWavelength = -1;
     private long rate = -1;
+    private  ServiceFormat serviceFormat = ServiceFormat.OC;
 
     public enum LocalCause {
         NONE, TOO_HIGH_LATENCY, OUT_OF_SPEC_OSNR, NO_PATH_EXISTS, INT_PROBLEM, HD_NODE_INCLUDE;
@@ -102,6 +104,14 @@ public class PceResult {
         this.rate = rate;
     }
 
+    public ServiceFormat getServiceFormat() {
+        return serviceFormat;
+    }
+
+    public void setServiceFormat(ServiceFormat serviceFormat) {
+        this.serviceFormat = serviceFormat;
+    }
+
     public LocalCause getLocalCause() {
         return localCause;
     }
index 2a616bbb72b1ae745fe31d6c76075f41f4db5398..bc18c1359391a093213686481fc08c37c82d6186 100644 (file)
             <network-ref>openroadm-network</network-ref>
             <node-ref>ROADMC01</node-ref>
         </supporting-node>
+        <supporting-node>
+            <network-ref>clli-network</network-ref>
+            <node-ref>NodeC</node-ref>
+        </supporting-node>
         <srg-attributes xmlns="http://org/openroadm/network/topology">
             <available-wavelengths>
                 <index>93</index>
             <tp-id>DEG1-TTP-TXRX</tp-id>
             <tp-type xmlns="http://org/openroadm/common/network">DEGREE-TXRX-TTP</tp-type>
         </termination-point>
+        <node-type xmlns="http://org/openroadm/common/network">DEGREE</node-type>
         <supporting-node>
             <network-ref>openroadm-network</network-ref>
             <node-ref>ROADMC01</node-ref>
         </supporting-node>
-        <node-type xmlns="http://org/openroadm/common/network">DEGREE</node-type>
+        <supporting-node>
+            <network-ref>clli-network</network-ref>
+            <node-ref>NodeC</node-ref>
+        </supporting-node>
         <degree-attributes xmlns="http://org/openroadm/network/topology">
             <degree-number>1</degree-number>
             <available-wavelengths>
             <tp-id>DEG2-CTP-TXRX</tp-id>
             <tp-type xmlns="http://org/openroadm/common/network">DEGREE-TXRX-CTP</tp-type>
         </termination-point>
+        <node-type xmlns="http://org/openroadm/common/network">DEGREE</node-type>
         <supporting-node>
             <network-ref>openroadm-network</network-ref>
             <node-ref>ROADMC01</node-ref>
         </supporting-node>
-        <node-type xmlns="http://org/openroadm/common/network">DEGREE</node-type>
+        <supporting-node>
+            <network-ref>clli-network</network-ref>
+            <node-ref>NodeC</node-ref>
+        </supporting-node>
         <degree-attributes xmlns="http://org/openroadm/network/topology">
             <degree-number>2</degree-number>
             <available-wavelengths>
             <network-ref>openroadm-network</network-ref>
             <node-ref>ROADMA01</node-ref>
         </supporting-node>
+        <supporting-node>
+            <network-ref>clli-network</network-ref>
+            <node-ref>NodeA</node-ref>
+        </supporting-node>
         <srg-attributes xmlns="http://org/openroadm/network/topology">
             <available-wavelengths>
                 <index>93</index>
             <tp-type xmlns="http://org/openroadm/common/network">XPONDER-NETWORK</tp-type>
             <associated-connection-map-port xmlns="http://transportpce/topology">XPDR1-CLIENT1</associated-connection-map-port>
         </termination-point>
+        <node-type xmlns="http://org/openroadm/common/network">XPONDER</node-type>
         <supporting-node>
             <network-ref>openroadm-network</network-ref>
             <node-ref>XPDRA01</node-ref>
         </supporting-node>
-        <node-type xmlns="http://org/openroadm/common/network">XPONDER</node-type>
+        <supporting-node>
+            <network-ref>clli-network</network-ref>
+            <node-ref>NodeA</node-ref>
+        </supporting-node>
     </node>
     <node>
         <node-id>ROADMA01-DEG2</node-id>
             <tp-id>DEG2-CTP-TXRX</tp-id>
             <tp-type xmlns="http://org/openroadm/common/network">DEGREE-TXRX-CTP</tp-type>
         </termination-point>
+        <node-type xmlns="http://org/openroadm/common/network">DEGREE</node-type>
         <supporting-node>
             <network-ref>openroadm-network</network-ref>
             <node-ref>ROADMA01</node-ref>
         </supporting-node>
-        <node-type xmlns="http://org/openroadm/common/network">DEGREE</node-type>
+        <supporting-node>
+            <network-ref>clli-network</network-ref>
+            <node-ref>NodeA</node-ref>
+        </supporting-node>
         <degree-attributes xmlns="http://org/openroadm/network/topology">
             <degree-number>2</degree-number>
             <available-wavelengths>
             <tp-type xmlns="http://org/openroadm/common/network">XPONDER-NETWORK</tp-type>
             <associated-connection-map-port xmlns="http://transportpce/topology">XPDR1-CLIENT1</associated-connection-map-port>
         </termination-point>
+        <node-type xmlns="http://org/openroadm/common/network">XPONDER</node-type>
         <supporting-node>
             <network-ref>openroadm-network</network-ref>
             <node-ref>XPDRC01</node-ref>
         </supporting-node>
-        <node-type xmlns="http://org/openroadm/common/network">XPONDER</node-type>
+        <supporting-node>
+            <network-ref>clli-network</network-ref>
+            <node-ref>NodeC</node-ref>
+        </supporting-node>
     </node>
     <node>
         <node-id>ROADMA01-DEG1</node-id>
             <tp-id>DEG1-TTP-TXRX</tp-id>
             <tp-type xmlns="http://org/openroadm/common/network">DEGREE-TXRX-TTP</tp-type>
         </termination-point>
+        <node-type xmlns="http://org/openroadm/common/network">DEGREE</node-type>
         <supporting-node>
             <network-ref>openroadm-network</network-ref>
             <node-ref>ROADMA01</node-ref>
         </supporting-node>
-        <node-type xmlns="http://org/openroadm/common/network">DEGREE</node-type>
+        <supporting-node>
+            <network-ref>clli-network</network-ref>
+            <node-ref>NodeA</node-ref>
+        </supporting-node>
         <degree-attributes xmlns="http://org/openroadm/network/topology">
             <degree-number>1</degree-number>
             <available-wavelengths>
index 1465bf2dd64cc6f5b218169e1588012bc0d37316..2cad24181fe1e62311f9e486135969c0a2a37a25 100644 (file)
@@ -117,12 +117,14 @@ class TransportPCEtesting(unittest.TestCase):
                 },
                 "service-a-end": {
                     "node-id": "XPDRA01",
-                    "service-rate": "0",
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
                     "clli": "nodeA"
                 },
                 "service-z-end": {
                     "node-id": "XPDRC01",
-                    "service-rate": "0",
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
                     "clli": "nodeC"
                 }
             }
@@ -151,13 +153,15 @@ class TransportPCEtesting(unittest.TestCase):
                 },
                 "service-a-end": {
                     "node-id": "ROADMA01",
-                    "service-rate": "0",
-                    "clli": "nodeA"
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
+                    "clli": "NodeA"
                 },
                 "service-z-end": {
                     "node-id": "ROADMC01",
-                    "service-rate": "0",
-                    "clli": "nodeC"
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
+                    "clli": "NodeC"
                 }
             }
         }
@@ -250,13 +254,15 @@ class TransportPCEtesting(unittest.TestCase):
                 },
                 "service-a-end": {
                     "node-id": "XPONDER-1-2",
-                    "service-rate": "0",
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
                     "clli": "ORANGE1"
                 },
                 "service-z-end": {
                     "node-id": "XPONDER-3-2",
-                    "service-rate": "0",
-                    "clli": "ORANGE1"
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
+                    "clli": "ORANGE3"
                 }
             }
         }
@@ -282,12 +288,14 @@ class TransportPCEtesting(unittest.TestCase):
                   "request-id": "request1"
                 },
                 "service-a-end": {
-                  "service-rate": "0",
+                  "service-rate": "100",
+                  "service-format": "Ethernet",
                   "clli": "cll21",
                   "node-id": "OpenROADM-2-1"
                 },
                 "service-z-end": {
-                  "service-rate": "0",
+                  "service-rate": "100",
+                  "service-format": "Ethernet",
                   "clli": "ncli22",
                   "node-id": "OpenROADM-2-2"
                   },
@@ -400,8 +408,8 @@ class TransportPCEtesting(unittest.TestCase):
                 },
                 "service-a-end": {
                   "service-format": "Ethernet",
-                  "service-rate": "0",
-                  "clli": "clli11",
+                  "service-rate": "100",
+                  "clli": "ORANGE2",
                   "node-id": "XPONDER-2-2",
                   "tx-direction": {
                     "port": {
@@ -428,8 +436,8 @@ class TransportPCEtesting(unittest.TestCase):
                 },
                 "service-z-end": {
                   "service-format": "Ethernet",
-                  "service-rate": "0",
-                  "clli": "clli11",
+                  "service-rate": "100",
+                  "clli": "ORANGE1",
                   "node-id": "XPONDER-1-2",
                   "tx-direction": {
                     "port": {
@@ -500,12 +508,16 @@ class TransportPCEtesting(unittest.TestCase):
                     "request-id": "request 1"
                 },
                 "service-a-end": {
-                    "service-rate": "0",
-                    "node-id": "XPONDER-1-2"
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
+                    "node-id": "XPONDER-1-2",
+                    "clli": "ORANGE1"
                 },
                 "service-z-end": {
-                    "service-rate": "0",
-                    "node-id": "XPONDER-3-2"
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
+                    "node-id": "XPONDER-3-2",
+                    "clli": "ORANGE3"
              },
              "pce-metric": "hop-count"
            }
@@ -536,12 +548,16 @@ class TransportPCEtesting(unittest.TestCase):
                     "request-id": "request 1"
                 },
                 "service-a-end": {
-                    "service-rate": "0",
-                    "node-id": "XPONDER-1-2"
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
+                    "node-id": "XPONDER-1-2",
+                    "clli": "ORANGE1"
                 },
                 "service-z-end": {
-                    "service-rate": "0",
-                    "node-id": "XPONDER-3-2"
+                    "service-rate": "100",
+                    "service-format": "Ethernet",
+                    "node-id": "XPONDER-3-2",
+                    "clli": "ORANGE3"
                 },
                 "hard-constraints": {
                     "exclude_": {