From 442088b23f7f20667badfa66759c15d48ee28605 Mon Sep 17 00:00:00 2001 From: atriki Date: Thu, 12 Dec 2019 15:27:36 +0100 Subject: [PATCH] Consolidation of the PCE - change k from 10 to 100 in the case of nodes inclusion in the hard constraints and in the case when a first execution of k-shortest-path failed - conslidate the osnr calculation - add the OUT_OF_SPEC_OSNR as a cause of path computation failure - add the HD_NODE_INCLUDE as a cause of path computation failure - detect TOO_HIGH_LATENCY in the case where the MaxLatency is exceeded - Verfication of MaxLatency and node inclusion violation in postAlgoPathValidator instead of inAlgoPathValidator - change the name of the method calcPath() of PceCalculation to retrievePceNetwork() JIRA: TRNSPRTPCE-146, TRNSPRTPCE-147, TRNSPRTPCE-93 Change-Id: Ie2f8bf502af81de857dadbdc5a879f5c4b10c96b Signed-off-by: atriki --- .../transportpce/pce/PceSendingPceRPCs.java | 11 +- .../pce/constraints/PceConstraints.java | 17 +- .../gnpy/ServiceDataStoreOperationsImpl.java | 4 +- .../pce/graph/InAlgoPathValidator.java | 162 +------------ .../transportpce/pce/graph/PceGraph.java | 35 +-- .../pce/graph/PostAlgoPathValidator.java | 227 ++++++++++++++++-- .../pce/networkanalyzer/PceCalculation.java | 4 +- .../pce/networkanalyzer/PceLink.java | 155 +++++------- .../pce/networkanalyzer/PceResult.java | 7 +- 9 files changed, 306 insertions(+), 316 deletions(-) diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java b/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java index 4b6b05133..e8f0f9aac 100755 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java @@ -91,7 +91,7 @@ public class PceSendingPceRPCs { PceCalculation nwAnalizer = new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc); - nwAnalizer.calcPath(); + nwAnalizer.retrievePceNetwork(); rc = nwAnalizer.getReturnStructure(); if (!rc.getStatus()) { LOG.error("In pathComputationWithConstraints, nwAnalizer: result = {}", rc.toString()); @@ -104,7 +104,7 @@ public class PceSendingPceRPCs { graph.calcPath(); rc = graph.getReturnStructure(); if (!rc.getStatus()) { - LOG.warn("In pathComputation : Graph return without Path "); + LOG.warn("In pathComputationWithConstraints : Graph return without Path "); // TODO fix. This is quick workaround for algorithm problem if ((rc.getLocalCause() == PceResult.LocalCause.TOO_HIGH_LATENCY) && (hardConstraints.getPceMetrics() == PceMetric.HopCount) @@ -112,6 +112,12 @@ public class PceSendingPceRPCs { hardConstraints.setPceMetrics(PceMetric.PropagationDelay); graph = patchRerunGraph(graph); } + + if (rc.getLocalCause() == PceResult.LocalCause.HD_NODE_INCLUDE) { + graph.setKpathsToBring(graph.getKpathsToBring() * 10); + graph = patchRerunGraph(graph); + } + if (!rc.getStatus()) { LOG.error("In pathComputationWithConstraints, graph.calcPath: result = {}", rc.toString()); return; @@ -144,6 +150,7 @@ public class PceSendingPceRPCs { ztoa = rc.getZtoADirection(); } + //Connect to Gnpy to check path feasibility and recompute another path in case of path non-feasibility try { ConnectToGnpyServer connectToGnpy = new ConnectToGnpyServer(); if (connectToGnpy.isGnpyURLExist()) { diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/constraints/PceConstraints.java b/pce/src/main/java/org/opendaylight/transportpce/pce/constraints/PceConstraints.java index 5b79cb9a9..202b42874 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/constraints/PceConstraints.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/constraints/PceConstraints.java @@ -24,7 +24,7 @@ public class PceConstraints { private RoutingConstraintsSp.PceMetric pceMetrics = RoutingConstraintsSp.PceMetric.HopCount; private Long maxLatency = (long) -1; - /////////////// EXCLUDE /////////////////// + // Structure related to EXCLUDE constraints // Nodes/CLLI/SRLG lists might consist of two types of elements : (1)from diversity constraints (2)from exclude list // e.g.: nodesToExclude - topo-level nodes IDs - comes from diversity constraints // : supNodesToExclude - supporting nodes IDs - comes from exclude list @@ -37,16 +37,12 @@ public class PceConstraints { private List clliToExclude = new ArrayList(); private List clliNodesToExclude = new ArrayList(); + + ///Structures related to INCLUDE constraints private List nodesToInclude = new ArrayList(); private List pceNodesToInclude = new ArrayList(); - - public static final Long CONST_OSNR = 1L; - private double maxOSNR = (CONST_OSNR / (Math.pow(10, (24 / 10.0)))); - - /**. - * /////////////// INCLUDE CONSTRAINTS./////////////////// - */ private List listToInclude = new ArrayList(); + private List srlgNames = new ArrayList(); public enum ResourceType { @@ -159,11 +155,6 @@ public class PceConstraints { this.pceNodesToInclude.add(node); } - public Double getMaxOSNR() { - LOG.debug("in Pceconstraints getMaxOSNR = {}", maxOSNR); - return maxOSNR; - } - public class ResourcePair { public ResourcePair(ResourceType type, String name) { super(); diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java index 5d813a83c..5342387af 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java @@ -27,7 +27,6 @@ import org.opendaylight.transportpce.common.DataStoreContext; import org.opendaylight.transportpce.common.converter.XMLDataObjectConverter; import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; -import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; @@ -113,8 +112,7 @@ public class ServiceDataStoreOperationsImpl implements ServiceDataStoreOperation scPath.getParent(), scPath.getLastComponent().getNamespace(), JsonWriterFactory.createJsonWriter(writer, 2)); // The write part - final BindingStreamEventWriter bindingWriter = codecRegistry.newWriter(id, domWriter); - codecRegistry.getSerializer(id.getTargetType()).serialize(object, bindingWriter); + codecRegistry.getSerializer(id.getTargetType()).serialize(object, codecRegistry.newWriter(id, domWriter)); domWriter.close(); writer.close(); } catch (IOException | YangSyntaxErrorException | ReactorException e) { diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/graph/InAlgoPathValidator.java b/pce/src/main/java/org/opendaylight/transportpce/pce/graph/InAlgoPathValidator.java index 768fb41f8..963ce4564 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/graph/InAlgoPathValidator.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/graph/InAlgoPathValidator.java @@ -8,14 +8,8 @@ package org.opendaylight.transportpce.pce.graph; -import java.util.ArrayList; -import java.util.List; - import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.PathValidator; -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.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,13 +18,8 @@ public class InAlgoPathValidator implements PathValidator /* Logging. */ private static final Logger LOG = LoggerFactory.getLogger(PceGraph.class); - private PceConstraints pceHardConstraints = null; - private PceNode zendNode = null; - - public InAlgoPathValidator(PceConstraints pceHardConstraints, PceNode zendNode) { + public InAlgoPathValidator() { super(); - this.pceHardConstraints = pceHardConstraints; - this.zendNode = zendNode; } @Override @@ -42,9 +31,7 @@ public class InAlgoPathValidator implements PathValidator LOG.debug("InAlgoPathValidator: partialPath size: {} prev edge {} new edge {}", size, edge.link().getlinkType(), partialPath.getEdgeList().get(size - 1).link().getlinkType()); - if ((!checkTurn(partialPath.getEdgeList().get(size - 1).link().getlinkType(), edge.link().getlinkType())) - || (!checkLimits(partialPath, edge, pceHardConstraints)) - || (!checkInclude(partialPath, edge, zendNode, pceHardConstraints))) { + if ((!checkTurn(partialPath.getEdgeList().get(size - 1).link().getlinkType(), edge.link().getlinkType()))) { return false; } else { return true; @@ -86,147 +73,4 @@ public class InAlgoPathValidator implements PathValidator return true; } - /* - * this method should be added to JgraphT as accumulated values inside path - * (RankingPathElementList) - */ - private boolean checkLimits(GraphPath partialPath, - PceGraphEdge edge, PceConstraints pceHardConstraintsInput) { - - Long latencyConstraint = pceHardConstraintsInput.getMaxLatency(); - if (latencyConstraint > 0) { - long newLatency = Math.round(calcLatency(partialPath) + edge.link().getLatency()); - if (newLatency > latencyConstraint) { - LOG.warn("In validateLatency: AtoZ path is dropped because of MAX LATENCY {} > {}", - newLatency, latencyConstraint); - return false; - } - } - - return true; - } - - private double calcLatency(GraphPath path) { - double latency = 0; - for (PceGraphEdge edge : path.getEdgeList()) { - latency = latency + edge.link().getLatency(); - } - return latency; - } - - /* - * checkInclude this method ensures the path is going over path elements - * to be included, alway check target node in the new edge - * - */ - private boolean checkInclude(GraphPath partialPath, - PceGraphEdge edge, PceNode zendNodeInput, - PceConstraints pceHardConstraintsInput) { - - List listToInclude = pceHardConstraintsInput.getListToInclude(); - if (listToInclude.isEmpty()) { - return true; - } - - // run this check only for the last edge of path - if (!edge.link().getDestId().getValue().equals(zendNodeInput.getNodeId().getValue())) { - return true; - } - List pathEdges = partialPath.getEdgeList(); - pathEdges.add(edge); - LOG.info(" in checkInclude vertex list: [{}]", partialPath.getVertexList()); - - List listOfElementsSubNode = new ArrayList(); - listOfElementsSubNode.add(pathEdges.get(0).link().getsourceSupNodeId()); - listOfElementsSubNode.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.NODE)); - - List listOfElementsCLLI = new ArrayList(); - listOfElementsCLLI.add(pathEdges.get(0).link().getsourceCLLI()); - listOfElementsCLLI.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.CLLI)); - - List listOfElementsSRLG = new ArrayList(); - // first link is XPONDEROUTPUT, no SRLG for it - listOfElementsSRLG.add("NONE"); - listOfElementsSRLG.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.SRLG)); - - // validation: check each type for each element - for (ResourcePair next : listToInclude) { - int indx = -1; - switch (next.getType()) { - case NODE: - if (listOfElementsSubNode.contains(next.getName())) { - indx = listOfElementsSubNode.indexOf(next.getName()); - } - break; - case SRLG: - if (listOfElementsSRLG.contains(next.getName())) { - indx = listOfElementsSRLG.indexOf(next.getName()); - } - break; - case CLLI: - if (listOfElementsCLLI.contains(next.getName())) { - indx = listOfElementsCLLI.indexOf(next.getName()); - } - break; - default: - LOG.warn(" in checkInclude vertex list unsupported resource type: [{}]", next.getType()); - } - - if (indx < 0) { - LOG.debug(" in checkInclude stopped : {} ", next.getName()); - return false; - } - - LOG.debug(" in checkInclude next found {} in {}", next.getName(), partialPath.getVertexList()); - - listOfElementsSubNode.subList(0, indx).clear(); - listOfElementsCLLI.subList(0, indx).clear(); - listOfElementsSRLG.subList(0, indx).clear(); - } - - LOG.info(" in checkInclude passed : {} ", partialPath.getVertexList()); - return true; - } - - private List listOfElementsBuild(List pathEdges, PceConstraints.ResourceType type) { - List listOfElements = new ArrayList(); - - for (PceGraphEdge link: pathEdges) { - switch (type) { - case NODE: - listOfElements.add(link.link().getdestSupNodeId()); - break; - case CLLI: - listOfElements.add(link.link().getdestCLLI()); - break; - case SRLG: - if (link.link().getlinkType() != OpenroadmLinkType.ROADMTOROADM) { - listOfElements.add("NONE"); - break; - } - - // srlg of link is List. 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()); - found = true; - continue; - } - } - if (!found) { - // there is no specific srlg to include. thus add to list just the first one - listOfElements.add("NONE"); - } - break; - default: - LOG.debug("listOfElementsBuild unsupported resource type"); - } - } - - return listOfElements; - } -} +} \ No newline at end of file diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/graph/PceGraph.java b/pce/src/main/java/org/opendaylight/transportpce/pce/graph/PceGraph.java index f4132e04c..3f2210b53 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/graph/PceGraph.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/graph/PceGraph.java @@ -35,9 +35,10 @@ public class PceGraph { ////////////////////////// for Graph /////////////////////////// // how many paths to bring - int kpathsToBring = 10; + private int kpathsToBring = 10; + // max #hops - int mhopsPerPath = 50; + private int mhopsPerPath = 50; // input private Map allPceNodes = new HashMap(); @@ -68,7 +69,6 @@ public class PceGraph { LOG.info("In GraphCalculator: A and Z = {} / {} ", aendNode.toString(), zendNode.toString()); LOG.debug("In GraphCalculator: allPceNodes size {}, nodes {} ", allPceNodes.size(), allPceNodes.toString()); - } public boolean calcPath() { @@ -88,9 +88,8 @@ public class PceGraph { // validate found paths pceResult.setRC(ResponseCodes.RESPONSE_FAILED); for (GraphPath path : allWPaths) { - PostAlgoPathValidator papv = new PostAlgoPathValidator(); - pceResult = papv.checkPath(path, allPceNodes, pceResult); + pceResult = papv.checkPath(path, allPceNodes, pceResult, pceHardConstraints); LOG.info("In calcPath after PostAlgoPathValidator {} {}", pceResult.getResponseCode(), ResponseCodes.RESPONSE_OK); @@ -124,16 +123,7 @@ public class PceGraph { if (weightedGraph.edgeSet().isEmpty() || weightedGraph.vertexSet().isEmpty()) { return false; } - - PathValidator wpv = new InAlgoPathValidator(pceHardConstraints, zpceNode); - - // local optimization. if 'include' constraint exists then increase amount of paths to return. - // it's because this constraint is checked at the last step when part of good paths - // are dropped by other constraints - if (!pceHardConstraints.getListToInclude().isEmpty()) { - kpathsToBring = kpathsToBring * 10; - LOG.info("k = {}",kpathsToBring); - } + PathValidator wpv = new InAlgoPathValidator(); // KShortestPaths on weightedGraph KShortestSimplePaths swp = @@ -149,7 +139,7 @@ public class PceGraph { // debug print for (GraphPath path : allWPaths) { - LOG.info("path Weight: {} : {}", path.getWeight(), path.getVertexList().toString()); + LOG.debug("path Weight: {} : {}", path.getWeight(), path.getVertexList().toString()); } return true; @@ -241,7 +231,18 @@ public class PceGraph { return weight; } - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + public int getKpathsToBring() { + return kpathsToBring; + } + + public void setKpathsToBring(int kpathsToBring) { + this.kpathsToBring = kpathsToBring; + } + + public void setMhopsPerPath(int mhopsPerPath) { + this.mhopsPerPath = mhopsPerPath; + } + public List getPathAtoZ() { return shortestPathAtoZ; } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/graph/PostAlgoPathValidator.java b/pce/src/main/java/org/opendaylight/transportpce/pce/graph/PostAlgoPathValidator.java index 55ea21b5f..626895fd1 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/graph/PostAlgoPathValidator.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/graph/PostAlgoPathValidator.java @@ -8,12 +8,17 @@ package org.opendaylight.transportpce.pce.graph; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.jgrapht.GraphPath; 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.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; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,32 +29,62 @@ public class PostAlgoPathValidator { // TODO hard-coded 96 private static final int MAX_WAWELENGTH = 96; + private static final double MIN_OSNR_W100G = 17; + private static final double TRX_OSNR = 33; + private static final double ADD_OSNR = 30; + public static final Long CONST_OSNR = 1L; + public static final double SYS_MARGIN = 0; public PceResult checkPath(GraphPath path, - Map allPceNodes, PceResult pceResult) { + Map allPceNodes, PceResult pceResult, PceConstraints pceHardConstraints) { + //check if the path is empty if (path.getEdgeList().size() == 0) { pceResult.setRC(ResponseCodes.RESPONSE_FAILED); return pceResult; } - // choose wavelength available in all nodes of the path - pceResult.setRC(ResponseCodes.RESPONSE_FAILED); + //Choose wavelength available in all nodes of the path Long waveL = chooseWavelength(path, allPceNodes); - if (waveL > 0) { - pceResult.setResultWavelength(waveL); - pceResult.setRC(ResponseCodes.RESPONSE_OK); - LOG.info("In PostAlgoPathValidator: chooseWavelength WL found {} {}", waveL, path.toString()); + 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 - stubCheckOSNR(path); + // 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 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 nodes are included in the hard constraints + if (!checkInclude(path, pceHardConstraints)) { + pceResult.setRC(ResponseCodes.RESPONSE_FAILED); + pceResult.setLocalCause(PceResult.LocalCause.HD_NODE_INCLUDE); + return pceResult; + } + + pceResult.setRC(ResponseCodes.RESPONSE_OK); return pceResult; } + //Choose the first available wavelength from the source to the destination private Long chooseWavelength(GraphPath path, Map allPceNodes) { Long wavelength = -1L; @@ -72,12 +107,174 @@ public class PostAlgoPathValidator { return wavelength; } - private boolean stubCheckOSNR(GraphPath path) { - double localOsnr = 0L; + //Check the latency + private boolean checkLatency(Long maxLatency, GraphPath 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); + } catch (NullPointerException e) { + LOG.warn("- In checkLatency: the link {} does not contain latency field", + edge.link().getLinkId().getValue()); + } + } + if (latency > maxLatency) { + return false; + } + return true; + } + + //Check the inclusion if it is defined in the hard constraints + private boolean checkInclude(GraphPath path, PceConstraints pceHardConstraintsInput) { + List listToInclude = pceHardConstraintsInput.getListToInclude(); + if (listToInclude.isEmpty()) { + return true; + } + + List pathEdges = path.getEdgeList(); + LOG.debug(" in checkInclude vertex list: [{}]", path.getVertexList()); + + List listOfElementsSubNode = new ArrayList(); + listOfElementsSubNode.add(pathEdges.get(0).link().getsourceSupNodeId()); + listOfElementsSubNode.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.NODE, + pceHardConstraintsInput)); + + List listOfElementsCLLI = new ArrayList(); + listOfElementsCLLI.add(pathEdges.get(0).link().getsourceCLLI()); + listOfElementsCLLI.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.CLLI, + pceHardConstraintsInput)); + + List listOfElementsSRLG = new ArrayList(); + // first link is XPONDEROUTPUT, no SRLG for it + listOfElementsSRLG.add("NONE"); + listOfElementsSRLG.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.SRLG, + pceHardConstraintsInput)); + + // validation: check each type for each element + for (ResourcePair next : listToInclude) { + int indx = -1; + switch (next.getType()) { + case NODE: + if (listOfElementsSubNode.contains(next.getName())) { + indx = listOfElementsSubNode.indexOf(next.getName()); + } + break; + case SRLG: + if (listOfElementsSRLG.contains(next.getName())) { + indx = listOfElementsSRLG.indexOf(next.getName()); + } + break; + case CLLI: + if (listOfElementsCLLI.contains(next.getName())) { + indx = listOfElementsCLLI.indexOf(next.getName()); + } + break; + default: + LOG.warn(" in checkInclude vertex list unsupported resource type: [{}]", next.getType()); + } + + if (indx < 0) { + LOG.debug(" in checkInclude stopped : {} ", next.getName()); + return false; + } + + LOG.debug(" in checkInclude next found {} in {}", next.getName(), path.getVertexList()); + + listOfElementsSubNode.subList(0, indx).clear(); + listOfElementsCLLI.subList(0, indx).clear(); + listOfElementsSRLG.subList(0, indx).clear(); + } + + LOG.info(" in checkInclude passed : {} ", path.getVertexList()); + return true; + } + + private List listOfElementsBuild(List pathEdges, PceConstraints.ResourceType type, + PceConstraints pceHardConstraints) { + + List listOfElements = new ArrayList(); + for (PceGraphEdge link: pathEdges) { + switch (type) { + case NODE: + listOfElements.add(link.link().getdestSupNodeId()); + break; + case CLLI: + listOfElements.add(link.link().getdestCLLI()); + break; + case SRLG: + if (link.link().getlinkType() != OpenroadmLinkType.ROADMTOROADM) { + listOfElements.add("NONE"); + break; + } + + // srlg of link is List. 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()); + found = true; + continue; + } + } + if (!found) { + // there is no specific srlg to include. thus add to list just the first one + listOfElements.add("NONE"); + } + break; + default: + LOG.debug("listOfElementsBuild unsupported resource type"); + } + } + return listOfElements; + } + + //Check the path OSNR + private boolean checkOSNR(GraphPath path) { + double linkOsnrDb; + double osnrDb = 0; + LOG.info("- In checkOSNR: OSNR of the transmitter = {} dB", TRX_OSNR); + LOG.info("- In checkOSNR: add-path incremental OSNR = {} dB", ADD_OSNR); + double inverseLocalOsnr = getInverseOsnrLinkLu(TRX_OSNR) + getInverseOsnrLinkLu(ADD_OSNR); for (PceGraphEdge edge : path.getEdgeList()) { - localOsnr = localOsnr + edge.link().getosnr(); + if (edge.link().getlinkType() == OpenroadmLinkType.ROADMTOROADM) { + // link OSNR in dB + linkOsnrDb = edge.link().getosnr(); + LOG.info("- In checkOSNR: OSNR of {} = {} dB", edge.link().getLinkId().getValue(), linkOsnrDb); + // 1 over the local OSNR, in linear units + inverseLocalOsnr += getInverseOsnrLinkLu(linkOsnrDb); + } + } + try { + osnrDb = getOsnrDb(1 / inverseLocalOsnr); + } + catch (ArithmeticException e) { + LOG.debug("In checkOSNR: OSNR is equal to 0 and the number of links is: {}", path.getEdgeList().size()); + return false; + } + LOG.info("In checkOSNR: OSNR of the path is {} dB", osnrDb); + if ((osnrDb + SYS_MARGIN) < MIN_OSNR_W100G) { + return false; } - LOG.info("In OSNR Stub: {}", localOsnr); return true; } -} + + private double getOsnrDb(double osnrLu) { + double osnrDb; + osnrDb = 10 * Math.log10(osnrLu); + return osnrDb; + } + + private double getInverseOsnrLinkLu(double linkOsnrDb) { + // 1 over the link OSNR, in linear units + double linkOsnrLu; + linkOsnrLu = Math.pow(10, (linkOsnrDb / 10.0)); + LOG.debug("In retrieveosnr: the inverse of link osnr is {} (Linear Unit)", linkOsnrLu); + return (CONST_OSNR / linkOsnrLu); + } + +} \ No newline at end of file diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceCalculation.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceCalculation.java index 4c5688439..7217b0c3a 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceCalculation.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceCalculation.java @@ -86,9 +86,9 @@ public class PceCalculation { parseInput(); } - public void calcPath() { + public void retrievePceNetwork() { - LOG.info("In PceCalculation calcPath: "); + LOG.info("In PceCalculation retrieveNetwork: "); if (!readMdSal()) { returnStructure.setRC(ResponseCodes.RESPONSE_FAILED); diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceLink.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceLink.java index 3dc56b225..58215e8f2 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceLink.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceLink.java @@ -10,8 +10,8 @@ package org.opendaylight.transportpce.pce.networkanalyzer; import java.util.List; -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.FiberType; 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.NodeId; @@ -24,20 +24,15 @@ public class PceLink { /* Logging. */ private static final Logger LOG = LoggerFactory.getLogger(PceLink.class); - ///////////////////////// LINKS //////////////////// /* * extension of Link to include constraints and Graph weight */ - double weight = 0; - private boolean isValid = true; - // this member is for XPONDER INPUT/OUTPUT links. - // it keeps name of client correcponding to NETWORK TP + // it keeps name of client corresponding to NETWORK TP private String client = ""; - private final LinkId linkId; private final OpenroadmLinkType linkType; private final NodeId sourceId; @@ -53,6 +48,11 @@ public class PceLink { private final List srlgList; private final double osnr; private final Span omsAttributesSpan; + private static final double CELERITY = 2.99792458 * 1e5; //meter per ms + private static final double NOISE_MASK_A = 0.571429; + private static final double NOISE_MASK_B = 39.285714; + private static final double UPPER_BOUND_OSNR = 33; + private static final double LOWER_BOUND_OSNR = 0.1; public PceLink(Link link, PceNode source, PceNode dest) { LOG.debug("PceLink: : PceLink start "); @@ -74,47 +74,24 @@ public class PceLink { this.linkType = MapUtils.calcType(link); this.oppositeLink = calcOpposite(link); - this.latency = calcLatency(link); if (this.linkType == OpenroadmLinkType.ROADMTOROADM) { this.omsAttributesSpan = MapUtils.getOmsAttributesSpan(link); this.srlgList = MapUtils.getSRLG(link); - this.osnr = retrieveOSNR(); + this.latency = calcLatency(link); + this.osnr = calcSpanOSNR(); } else { this.omsAttributesSpan = null; this.srlgList = null; - this.osnr = 0.0; + this.latency = 0L; + this.osnr = 100L; //infinite OSNR in DB } - LOG.debug("PceLink: created PceLink {}", toString()); } - /*private OpenroadmLinkType calcType(Link link) { - org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.@Nullable Link1 link1 = null; - OpenroadmLinkType tmplinkType = null; - - // ID and type - link1 = link.augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130 - .Link1.class); - if (link1 == null) { - this.isValid = false; - LOG.error("PceLink: No Link augmentation available. Link is ignored {}", this.linkId); - return null; - } - - tmplinkType = link1.getLinkType(); - if (tmplinkType == null) { - this.isValid = false; - LOG.error("PceLink: No Link type available. Link is ignored {}", this.linkId); - return null; - } - return tmplinkType; - }*/ - + //Retrieve the opposite link private LinkId calcOpposite(Link link) { - // opposite link - LinkId tmpoppositeLink = MapUtils.extractOppositeLink(link); if (tmpoppositeLink == null) { LOG.error("PceLink: Error calcOpposite. Link is ignored {}", link.getLinkId().getValue()); @@ -123,97 +100,73 @@ public class PceLink { return tmpoppositeLink; } + //Compute the link latency : if the latency is not defined, the latency it is computed from the omsAttributesSpan private Long calcLatency(Link link) { - Long tmplatency = 1L; Link1 link1 = null; - // latency link1 = link.augmentation(Link1.class); + Long tmplatency = link1.getLinkLatency(); + if (tmplatency != null) { + return tmplatency; + } + try { - tmplatency = link1.getLinkLatency(); + double tmp = 0; + for (int i = 0; i < this.omsAttributesSpan.getLinkConcatenation().size(); i++) { + //Length is expressed in meter and latency is expressed in ms according to OpenROADM MSA + tmp += this.omsAttributesSpan.getLinkConcatenation().get(i).getSRLGLength() / CELERITY; + LOG.info("In PceLink: The latency of link {} == {}",link.getLinkId(),tmplatency); + } + tmplatency = (long) Math.ceil(tmp); } catch (NullPointerException e) { - LOG.debug("the latency does not exist for this link"); + LOG.debug("In PceLink: cannot compute the latency for the link {}",link.getLinkId().getValue()); + tmplatency = 1L; } return tmplatency; } - @SuppressWarnings("checkstyle:VariableDeclarationUsageDistance") - public double retrieveOSNR() { - // sum of 1 over the span OSNRs (linear units) - double sum = 0; - // link OSNR, in dB - //double linkOsnrDb; - // link OSNR, in dB - double linkOsnrLu; - // span OSNR, in dB - double spanOsnrDb; - // span OSNR, in linear units - double spanOsnrLu; - // default amplifier noise value, in dB - //double ampNoise = 5.5; - // fiber span measured loss, in dB - double loss; - // launch power, in dB - double power; - double constantA = 38.97293; - double constantB = 0.72782; - double constantC = -0.532331; - double constactD = -0.019549; - double upperBoundosnr = 33; - double lowerBoundosnr = 0.1; - - if (omsAttributesSpan == null) { - // indicates no data or N/A + //Compute the OSNR of a span + public double calcSpanOSNR() { + try { + double pout; //power on the output of the previous ROADM (dBm) + pout = retrievePower(this.omsAttributesSpan.getLinkConcatenation().get(0).getFiberType()); + double spanLoss = this.omsAttributesSpan.getSpanlossCurrent().getValue().doubleValue(); // span loss (dB) + double pin = pout - spanLoss; //power on the input of the current ROADM (dBm) + double spanOsnrDb; + spanOsnrDb = NOISE_MASK_A * pin + NOISE_MASK_B; + if (spanOsnrDb > UPPER_BOUND_OSNR) { + spanOsnrDb = UPPER_BOUND_OSNR; + } else if (spanOsnrDb < LOWER_BOUND_OSNR) { + spanOsnrDb = LOWER_BOUND_OSNR; + } + return spanOsnrDb; + } catch (NullPointerException e) { + LOG.error("in PceLink : Null field in the OmsAttrubtesSpan"); return 0L; } - loss = omsAttributesSpan.getSpanlossCurrent().getValue().doubleValue(); - switch (omsAttributesSpan.getLinkConcatenation().get(0).getFiberType()) { + } + + private double retrievePower(FiberType fiberType) { + double power; + switch (fiberType) { case Smf: power = 2; break; - case Eleaf: power = 1; break; - - case Oleaf: - power = 0; - break; - - case Dsf: - power = 0; - break; - - case Truewave: - power = 0; - break; - case Truewavec: power = -1; break; - + case Oleaf: + case Dsf: + case Truewave: case NzDsf: - power = 0; - break; - case Ull: - power = 0; - break; - default: power = 0; break; } - spanOsnrDb = constantA + constantB * power + constantC * loss + constactD * power * loss; - if (spanOsnrDb > upperBoundosnr) { - spanOsnrDb = upperBoundosnr; - } else if (spanOsnrDb < lowerBoundosnr) { - spanOsnrDb = lowerBoundosnr; - } - spanOsnrLu = Math.pow(10, (spanOsnrDb / 10.0)); - sum = PceConstraints.CONST_OSNR / spanOsnrLu; - linkOsnrLu = sum; - LOG.debug("In retrieveosnr: link osnr is {} dB", linkOsnrLu); - return linkOsnrLu; + return power; } public LinkId getOppositeLink() { @@ -313,7 +266,7 @@ public class PceLink { } public String toString() { - return "PceLink type=" + linkType + " ID=" + linkId.getValue() + " latecy=" + latency; + return "PceLink type=" + linkType + " ID=" + linkId.getValue() + " latency=" + latency; } } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceResult.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceResult.java index 233d785d8..abce70280 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceResult.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceResult.java @@ -21,11 +21,10 @@ public class PceResult { private boolean calcStatus = false; private String responseCode = ResponseCodes.RESPONSE_FAILED; private long resultWavelength = -1; - // for now it is constant returned as received from A-end private long rate = -1; public enum LocalCause { - NONE, TOO_HIGH_LATENCY, NO_PATH_EXISTS, INT_PROBLEM; + NONE, TOO_HIGH_LATENCY, OUT_OF_SPEC_OSNR, NO_PATH_EXISTS, INT_PROBLEM, HD_NODE_INCLUDE; } private LocalCause localCause = LocalCause.NONE; @@ -39,14 +38,14 @@ public class PceResult { public void setRC(String rc) { switch (rc) { case ResponseCodes.RESPONSE_OK : - calcMessage = "Path is calculated"; + calcMessage = "Path is calculated by PCE"; calcStatus = true; responseCode = ResponseCodes.RESPONSE_OK; break; case ResponseCodes.RESPONSE_FAILED : responseCode = ResponseCodes.RESPONSE_FAILED; calcStatus = false; - calcMessage = "No path available"; + calcMessage = "No path available by PCE"; break; default: LOG.error("setRC: RespondeCodes unknown"); -- 2.36.6