+ int spectralWidthSlotNumber =
+ GridConstant.SPECTRAL_WIDTH_SLOT_NUMBER_MAP.getOrDefault(serviceType, GridConstant.NB_SLOTS_100G);
+ SpectrumAssignment spectrumAssignment = null;
+ //variable to deal with 1GE (Nb=1) and 10GE (Nb=10) cases
+ switch (serviceType) {
+ case StringConstants.SERVICE_TYPE_OTUC2:
+ case StringConstants.SERVICE_TYPE_OTUC3:
+ case StringConstants.SERVICE_TYPE_OTUC4:
+ case StringConstants.SERVICE_TYPE_400GE:
+ spectralWidthSlotNumber =
+ GridConstant.SPECTRAL_WIDTH_SLOT_NUMBER_MAP.getOrDefault(serviceType, GridConstant.NB_SLOTS_400G);
+ //fallthrough
+ case StringConstants.SERVICE_TYPE_100GE_T:
+ case StringConstants.SERVICE_TYPE_OTU4:
+ spectrumAssignment = getSpectrumAssignment(path, allPceNodes, spectralWidthSlotNumber);
+ pceResult.setServiceType(serviceType);
+ if (spectrumAssignment.getBeginIndex().equals(Uint16.valueOf(0))
+ && spectrumAssignment.getStopIndex().equals(Uint16.valueOf(0))) {
+ pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
+ pceResult.setLocalCause(PceResult.LocalCause.NO_PATH_EXISTS);
+ return pceResult;
+ }
+ if (spectrumAssignment.getFlexGrid()) {
+ LOG.debug("Spectrum assignment flexgrid mode");
+ pceResult.setResultWavelength(GridConstant.IRRELEVANT_WAVELENGTH_NUMBER);
+ } else {
+ LOG.debug("Spectrum assignment fixedgrid mode");
+ pceResult.setResultWavelength(
+ GridUtils.getWaveLengthIndexFromSpectrumAssigment(spectrumAssignment.getBeginIndex().toJava()));
+ }
+ pceResult.setMinFreq(GridUtils.getStartFrequencyFromIndex(spectrumAssignment.getBeginIndex().toJava()));
+ pceResult.setMaxFreq(GridUtils.getStopFrequencyFromIndex(spectrumAssignment.getStopIndex().toJava()));
+ LOG.debug("In PostAlgoPathValidator: spectrum assignment found {} {}", spectrumAssignment, path);
+
+ // Check the OSNR
+ CatalogUtils cu = new CatalogUtils(networkTransactionService);
+ if (cu.isCatalogFilled()) {
+ double margin1 = checkOSNR(path, allPceNodes, allPceLinks, serviceType,
+ StringConstants.SERVICE_DIRECTION_AZ, cu);
+ double margin2 = checkOSNR(path, allPceNodes, allPceLinks, serviceType,
+ StringConstants.SERVICE_DIRECTION_ZA, cu);
+ if (margin1 < 0 || margin2 < 0 || margin1 == Double.NEGATIVE_INFINITY
+ || margin2 == Double.NEGATIVE_INFINITY) {
+ pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
+ pceResult.setLocalCause(PceResult.LocalCause.OUT_OF_SPEC_OSNR);
+ return pceResult;
+ }
+ this.tpceCalculatedMargin = Math.min(margin1, margin2);
+ LOG.info(
+ "In PostAlgoPathValidator: Minimum margin estimated by tpce on AtoZ and ZtoA path is of {} dB",
+ this.tpceCalculatedMargin);
+ } else {
+ this.tpceCalculatedMargin = 0.0;
+ LOG.info("In PostAlgoPathValidator: Operational mode Catalog not filled, delegate OSNR calculation"
+ + " to GNPy and margin set to 0");
+ }
+ // Check if MaxLatency is defined in the hard constraints
+ if (pceHardConstraints.getMaxLatency() != -1
+ && !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, mode)) {
+ pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
+ pceResult.setLocalCause(PceResult.LocalCause.HD_NODE_INCLUDE);
+ return pceResult;
+ }
+ // TODO here other post algo validations can be added
+ // more data can be sent to PceGraph module via PceResult structure if required
+ pceResult.setRC(ResponseCodes.RESPONSE_OK);
+ pceResult.setLocalCause(PceResult.LocalCause.NONE);
+ return pceResult;
+ case StringConstants.SERVICE_TYPE_100GE_M:
+ case StringConstants.SERVICE_TYPE_10GE:
+ case StringConstants.SERVICE_TYPE_1GE:
+ int tribSlotNb = Map.of(
+ StringConstants.SERVICE_TYPE_100GE_M, 20,
+ StringConstants.SERVICE_TYPE_10GE, 8,
+ StringConstants.SERVICE_TYPE_1GE, 1)
+ .get(serviceType);
+ pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
+ pceResult.setServiceType(serviceType);
+ Map<String, List<Uint16>> tribSlot = chooseTribSlot(path, allPceNodes, tribSlotNb);
+ Map<String, Uint16> tribPort = chooseTribPort(path, allPceNodes, tribSlot, tribSlotNb);
+ List<OpucnTribSlotDef> resultTribPortTribSlot = getMinMaxTpTs(tribPort, tribSlot);
+ if (resultTribPortTribSlot.get(0) != null && resultTribPortTribSlot.get(1) != null) {
+ pceResult.setResultTribPortTribSlot(resultTribPortTribSlot);
+ pceResult.setRC(ResponseCodes.RESPONSE_OK);
+ LOG.info("In PostAlgoPathValidator: found TribPort {} - tribSlot {} - tribSlotNb {}",
+ tribPort, tribSlot, tribSlotNb);
+ }
+ return pceResult;
+ case StringConstants.SERVICE_TYPE_ODU4:
+ case StringConstants.SERVICE_TYPE_ODUC2:
+ case StringConstants.SERVICE_TYPE_ODUC3:
+ case StringConstants.SERVICE_TYPE_ODUC4:
+ case StringConstants.SERVICE_TYPE_100GE_S:
+ pceResult.setRC(ResponseCodes.RESPONSE_OK);
+ pceResult.setServiceType(serviceType);
+ LOG.info("In PostAlgoPathValidator: ODU4/ODUCn path found {}", path);
+ return pceResult;
+ default:
+ pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
+ LOG.warn("In PostAlgoPathValidator checkPath: unsupported serviceType {} found {}",
+ serviceType, path);
+ return pceResult;
+ }
+ }
+
+ // Check the latency
+ private boolean checkLatency(Long maxLatency, GraphPath<String, PceGraphEdge> path) {
+ double latency = 0;
+ for (PceGraphEdge edge : path.getEdgeList()) {
+ if (edge.link() == null || edge.link().getLatency() == null) {
+ LOG.warn("- In checkLatency: the link {} does not contain latency field",
+ edge.link().getLinkId().getValue());
+ return false;
+ }
+ latency += edge.link().getLatency();
+ LOG.debug("- In checkLatency: latency of {} = {} units", edge.link().getLinkId().getValue(), latency);
+ }
+ return (latency < maxLatency);
+ }
+
+ // Check the inclusion if it is defined in the hard constraints
+ //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(
+ listOfElementsBuild(pathEdges, PceConstraints.ResourceType.NODE, pceHardConstraintsInput));
+ List<String> listOfElementsCLLI = new ArrayList<>();
+ listOfElementsCLLI.add(pathEdges.get(0).link().getsourceCLLI());
+ listOfElementsCLLI.addAll(
+ listOfElementsBuild(pathEdges, PceConstraints.ResourceType.CLLI, pceHardConstraintsInput));
+ List<String> 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
+ 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()))
+ .map(ResourcePair::getName).collect(Collectors.toList()))
+ && listOfElementsCLLI.containsAll(
+ listToInclude
+ .stream().filter(rp -> PceConstraints.ResourceType.CLLI.equals(rp.getType()))
+ .map(ResourcePair::getName).collect(Collectors.toList()));
+ }
+
+ private List<String> listOfElementsBuild(List<PceGraphEdge> pathEdges, PceConstraints.ResourceType type,
+ PceConstraints pceHardConstraints) {
+ Set<String> listOfElements = new LinkedHashSet<>();
+ for (PceGraphEdge link : pathEdges) {
+ switch (type) {
+ case NODE:
+ listOfElements.add(link.link().getdestNetworkSupNodeId());
+ 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<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());
+ found = true;
+ }
+ }
+ 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 new ArrayList<>(listOfElements);
+ }