From: Gilles Thouenon <gilles.thouenon@orange.com> Date: Wed, 25 Oct 2023 11:30:09 +0000 (+0200) Subject: Fix PCE bug to select the path proposed by GNPy X-Git-Tag: 9.0.0~74 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=1f526e901ac556cff9914b3c001c852db3b555e4;p=transportpce.git Fix PCE bug to select the path proposed by GNPy Introduce the "loose" or "strict" mode to differentiate two ways to manage include node constraints: either the path must simply include some nodes whatever the order of node inside the list is, or the path must be exactly equal to the list of nodes. JIRA: TRNSPRTPCE-769 Signed-off-by: Gilles Thouenon <gilles.thouenon@orange.com> Change-Id: I34c0e3491fc341af3de0ff5b0dc702f40c7dd653 --- 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 1319a8248b..90a8862ddf 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java @@ -22,6 +22,7 @@ import org.opendaylight.transportpce.pce.networkanalyzer.PceCalculation; import org.opendaylight.transportpce.pce.networkanalyzer.PceResult; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInput; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInputBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PceConstraintMode; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.reroute.request.input.Endpoints; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.service.path.rpc.result.PathDescriptionBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.HardConstraints; @@ -108,7 +109,8 @@ public class PceSendingPceRPCs { LOG.info("cancelResourceReserve ..."); } - public void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints) { + private void pathComputationWithConstraints(PceConstraints hardConstraints, PceConstraints softConstraints, + PceConstraintMode mode) { PceCalculation nwAnalizer = new PceCalculation(input, networkTransaction, hardConstraints, softConstraints, rc, portMapping, endpoints); @@ -122,7 +124,7 @@ public class PceSendingPceRPCs { LOG.info("PceGraph ..."); PceGraph graph = new PceGraph(nwAnalizer.getaendPceNode(), nwAnalizer.getzendPceNode(), nwAnalizer.getAllPceNodes(), nwAnalizer.getAllPceLinks(), hardConstraints, softConstraints, - rc, serviceType, networkTransaction); + rc, serviceType, networkTransaction, mode); graph.calcPath(); rc = graph.getReturnStructure(); if (!rc.getStatus()) { @@ -159,7 +161,7 @@ public class PceSendingPceRPCs { PceConstraintsCalc constraints = new PceConstraintsCalc(input, networkTransaction); pceHardConstraints = constraints.getPceHardConstraints(); pceSoftConstraints = constraints.getPceSoftConstraints(); - pathComputationWithConstraints(pceHardConstraints, pceSoftConstraints); + pathComputationWithConstraints(pceHardConstraints, pceSoftConstraints, PceConstraintMode.Loose); this.success = rc.getStatus(); this.message = rc.getMessage(); this.responseCode = rc.getResponseCode(); @@ -233,7 +235,7 @@ public class PceSendingPceRPCs { PceConstraintsCalc constraintsGnpy = new PceConstraintsCalc(inputFromGnpy, networkTransaction); PceConstraints gnpyHardConstraints = constraintsGnpy.getPceHardConstraints(); PceConstraints gnpySoftConstraints = constraintsGnpy.getPceSoftConstraints(); - pathComputationWithConstraints(gnpyHardConstraints, gnpySoftConstraints); + pathComputationWithConstraints(gnpyHardConstraints, gnpySoftConstraints, PceConstraintMode.Strict); AToZDirection atoz = rc.getAtoZDirection(); ZToADirection ztoa = rc.getZtoADirection(); if (gnpyToCheckFeasiblity(atoz, ztoa,gnpy)) { 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 0a2d75fc67..dbd4111b2e 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 @@ -29,6 +29,7 @@ import org.opendaylight.transportpce.pce.networkanalyzer.PceLink; import org.opendaylight.transportpce.pce.networkanalyzer.PceNode; import org.opendaylight.transportpce.pce.networkanalyzer.PceResult; import org.opendaylight.transportpce.pce.networkanalyzer.PceResult.LocalCause; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PceConstraintMode; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State; 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.topology.rev180226.LinkId; @@ -55,6 +56,7 @@ public class PceGraph { private Double margin = null; PceConstraints pceHardConstraints; PceConstraints pceSoftConstraints; + private PceConstraintMode pceConstraintMode; // results private PceResult pceResult = null; @@ -69,7 +71,8 @@ public class PceGraph { public PceGraph(PceNode aendNode, PceNode zendNode, Map<NodeId, PceNode> allPceNodes, Map<LinkId, PceLink> allPceLinks, PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, - PceResult pceResult, String serviceType, NetworkTransactionService networkTransactionService) { + PceResult pceResult, String serviceType, NetworkTransactionService networkTransactionService, + PceConstraintMode mode) { super(); this.apceNode = aendNode; this.zpceNode = zendNode; @@ -80,6 +83,7 @@ public class PceGraph { this.pceSoftConstraints = pceSoftConstraints; this.serviceType = serviceType; this.networkTransactionService = networkTransactionService; + this.pceConstraintMode = mode; LOG.info("In GraphCalculator: A and Z = {} / {} ", aendNode, zendNode); LOG.debug("In GraphCalculator: allPceNodes size {}, nodes {} ", allPceNodes.size(), allPceNodes); @@ -104,7 +108,8 @@ public class PceGraph { GraphPath<String, PceGraphEdge> path = entry.getValue(); LOG.info("validating path n° {} - {}", entry.getKey(), path.getVertexList()); PostAlgoPathValidator papv = new PostAlgoPathValidator(networkTransactionService); - pceResult = papv.checkPath(path, allPceNodes, allPceLinks, pceResult, pceHardConstraints, serviceType); + pceResult = papv.checkPath( + path, allPceNodes, allPceLinks, pceResult, pceHardConstraints, serviceType, pceConstraintMode); this.margin = papv.getTpceCalculatedMargin(); if (ResponseCodes.RESPONSE_OK.equals(pceResult.getResponseCode())) { LOG.info("Path is validated"); 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 cf4c7e9bbb..7a3124b492 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 @@ -16,8 +16,10 @@ import java.util.Arrays; import java.util.BitSet; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import org.jgrapht.GraphPath; @@ -36,6 +38,7 @@ import org.opendaylight.transportpce.pce.constraints.PceConstraints.ResourcePair import org.opendaylight.transportpce.pce.networkanalyzer.PceLink; import org.opendaylight.transportpce.pce.networkanalyzer.PceNode; import org.opendaylight.transportpce.pce.networkanalyzer.PceResult; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PceConstraintMode; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.SpectrumAssignment; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.SpectrumAssignmentBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1; @@ -55,6 +58,7 @@ public class PostAlgoPathValidator { public static final Long CONST_OSNR = 1L; public static final double SYS_MARGIN = 0; + private Double tpceCalculatedMargin = 0.0; private final NetworkTransactionService networkTransactionService; @@ -68,7 +72,7 @@ public class PostAlgoPathValidator { justification = "intentional fallthrough") public PceResult checkPath(GraphPath<String, PceGraphEdge> path, Map<NodeId, PceNode> allPceNodes, Map<LinkId, PceLink> allPceLinks, PceResult pceResult, PceConstraints pceHardConstraints, - String serviceType) { + String serviceType, PceConstraintMode mode) { LOG.info("path = {}", path); // check if the path is empty if (path.getEdgeList().isEmpty()) { @@ -139,7 +143,7 @@ public class PostAlgoPathValidator { return pceResult; } // Check if nodes are included in the hard constraints - if (!checkInclude(path, pceHardConstraints)) { + if (!checkInclude(path, pceHardConstraints, mode)) { pceResult.setRC(ResponseCodes.RESPONSE_FAILED); pceResult.setLocalCause(PceResult.LocalCause.HD_NODE_INCLUDE); return pceResult; @@ -202,15 +206,17 @@ public class PostAlgoPathValidator { } // 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() - .stream().sorted((rp1, rp2) -> rp1.getName().compareTo(rp2.getName())) - .collect(Collectors.toList()); + //TODO: remove this checkstyle false positive warning when the checkstyle bug will be fixed + @SuppressWarnings("MissingSwitchDefault") + private boolean checkInclude(GraphPath<String, PceGraphEdge> path, PceConstraints pceHardConstraintsInput, + PceConstraintMode mode) { + List<ResourcePair> listToInclude = pceHardConstraintsInput.getListToInclude(); if (listToInclude.isEmpty()) { return true; } List<PceGraphEdge> pathEdges = path.getEdgeList(); LOG.debug(" in checkInclude vertex list: [{}]", path.getVertexList()); + LOG.debug("listToInclude = {}", listToInclude); List<String> listOfElementsSubNode = new ArrayList<>(); listOfElementsSubNode.add(pathEdges.get(0).link().getsourceNetworkSupNodeId()); listOfElementsSubNode.addAll( @@ -225,10 +231,17 @@ public class PostAlgoPathValidator { listOfElementsSRLG.addAll( listOfElementsBuild(pathEdges, PceConstraints.ResourceType.SRLG, pceHardConstraintsInput)); // validation: check each type for each element - return listOfElementsSubNode.containsAll( - listToInclude - .stream().filter(rp -> PceConstraints.ResourceType.NODE.equals(rp.getType())) - .map(ResourcePair::getName).collect(Collectors.toList())) + LOG.debug("listOfElementsSubNode = {}", listOfElementsSubNode); + return switch (mode) { + case Loose -> listOfElementsSubNode + .containsAll(listToInclude.stream() + .filter(rp -> PceConstraints.ResourceType.NODE.equals(rp.getType())) + .map(ResourcePair::getName).collect(Collectors.toList())); + case Strict -> listOfElementsSubNode + .equals(listToInclude.stream() + .filter(rp -> PceConstraints.ResourceType.NODE.equals(rp.getType())) + .map(ResourcePair::getName).collect(Collectors.toList())); + } && listOfElementsSRLG.containsAll( listToInclude .stream().filter(rp -> PceConstraints.ResourceType.SRLG.equals(rp.getType())) @@ -241,7 +254,7 @@ public class PostAlgoPathValidator { private List<String> listOfElementsBuild(List<PceGraphEdge> pathEdges, PceConstraints.ResourceType type, PceConstraints pceHardConstraints) { - List<String> listOfElements = new ArrayList<>(); + Set<String> listOfElements = new LinkedHashSet<>(); for (PceGraphEdge link : pathEdges) { switch (type) { case NODE: @@ -277,7 +290,7 @@ public class PostAlgoPathValidator { LOG.debug("listOfElementsBuild unsupported resource type"); } } - return listOfElements; + return new ArrayList<>(listOfElements); } private Map<String, Uint16> chooseTribPort(GraphPath<String, diff --git a/pce/src/test/java/org/opendaylight/transportpce/pce/graph/PceGraphTest.java b/pce/src/test/java/org/opendaylight/transportpce/pce/graph/PceGraphTest.java index 44d2e8b3ee..1a3297bc91 100644 --- a/pce/src/test/java/org/opendaylight/transportpce/pce/graph/PceGraphTest.java +++ b/pce/src/test/java/org/opendaylight/transportpce/pce/graph/PceGraphTest.java @@ -58,6 +58,7 @@ import org.opendaylight.transportpce.test.stub.MountPointServiceStub; import org.opendaylight.transportpce.test.stub.MountPointStub; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInput; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInputBuilder; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PceConstraintMode; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.request.input.ServiceAEndBuilder; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.request.input.ServiceZEndBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.port.PortBuilder; @@ -248,7 +249,7 @@ public class PceGraphTest extends AbstractTest { pceCalc.retrievePceNetwork(); pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(), pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints, - null, rc, StringConstants.SERVICE_TYPE_100GE_T, netTransServ); + null, rc, StringConstants.SERVICE_TYPE_100GE_T, netTransServ, PceConstraintMode.Loose); assertEquals(pceGraph.calcPath(), true); assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(3.0919881995992924)); } @@ -261,7 +262,7 @@ public class PceGraphTest extends AbstractTest { pceCalc.retrievePceNetwork(); pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(), pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints, - null, rc, StringConstants.SERVICE_TYPE_OTUC2, netTransServ); + null, rc, StringConstants.SERVICE_TYPE_OTUC2, netTransServ, PceConstraintMode.Loose); assertEquals(pceGraph.calcPath(), true); assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(1.1559963686478447)); } @@ -274,7 +275,7 @@ public class PceGraphTest extends AbstractTest { pceCalc.retrievePceNetwork(); pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(), pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints, - null, rc, StringConstants.SERVICE_TYPE_OTUC3, netTransServ); + null, rc, StringConstants.SERVICE_TYPE_OTUC3, netTransServ, PceConstraintMode.Loose); assertEquals(pceGraph.calcPath(), true); assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(0.3351048800367167)); } @@ -287,7 +288,7 @@ public class PceGraphTest extends AbstractTest { pceCalc.retrievePceNetwork(); pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(), pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints, - null, rc, StringConstants.SERVICE_TYPE_400GE, netTransServ); + null, rc, StringConstants.SERVICE_TYPE_400GE, netTransServ, PceConstraintMode.Loose); assertEquals(pceGraph.calcPath(), false); assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(0.0)); } @@ -300,7 +301,7 @@ public class PceGraphTest extends AbstractTest { pceCalc.retrievePceNetwork(); pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(), pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints, - null, rc, StringConstants.SERVICE_TYPE_400GE, netTransServ); + null, rc, StringConstants.SERVICE_TYPE_400GE, netTransServ, PceConstraintMode.Loose); assertEquals(pceGraph.calcPath(), true); assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(1.4432381874659086)); } @@ -313,7 +314,7 @@ public class PceGraphTest extends AbstractTest { pceCalc.retrievePceNetwork(); pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(), pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints, - null, rc, StringConstants.SERVICE_TYPE_OTUC4, netTransServ); + null, rc, StringConstants.SERVICE_TYPE_OTUC4, netTransServ, PceConstraintMode.Loose); assertEquals(pceGraph.calcPath(), true); assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(1.4432381874659086)); } @@ -326,7 +327,7 @@ public class PceGraphTest extends AbstractTest { pceCalc.retrievePceNetwork(); pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(), pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints, - null, rc, StringConstants.SERVICE_TYPE_OTUC4, netTransServ); + null, rc, StringConstants.SERVICE_TYPE_OTUC4, netTransServ, PceConstraintMode.Loose); assertEquals(pceGraph.calcPath(), true); assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(0.0)); } @@ -339,7 +340,7 @@ public class PceGraphTest extends AbstractTest { pceCalc.retrievePceNetwork(); pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(), pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints, - null, rc, StringConstants.SERVICE_TYPE_100GE_T, netTransServ); + null, rc, StringConstants.SERVICE_TYPE_100GE_T, netTransServ, PceConstraintMode.Loose); assertEquals(pceGraph.calcPath(), true); assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(3.0919881995992924)); } @@ -353,7 +354,7 @@ public class PceGraphTest extends AbstractTest { pceHardConstraints.setPceMetrics(PceMetric.PropagationDelay); pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(), pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints, - null, rc, StringConstants.SERVICE_TYPE_100GE_T, netTransServ); + null, rc, StringConstants.SERVICE_TYPE_100GE_T, netTransServ, PceConstraintMode.Loose); pceGraph.setConstrains(pceHardConstraints, null); assertEquals(pceGraph.calcPath(), true); @@ -416,7 +417,7 @@ public class PceGraphTest extends AbstractTest { new NodeId("optical"), pceOtnNode, new NodeId("optical2"), pceOtnNode2); return new PceGraph(pceOtnNode, pceOtnNode2, allPceNodes, allPceLinks, pceHardConstraints, null, - new PceResult(), type, null); + new PceResult(), type, null, PceConstraintMode.Loose); } private void saveOpenRoadmNetwork(Network network, String networkId)