X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=pce%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Ftransportpce%2Fpce%2Fgraph%2FPostAlgoPathValidator.java;h=960ae3bc1e6e407399d5aa99b40b042e11631d6a;hb=66f6af8141d231619ad9d6e6133910e14f3a32e2;hp=2aa455cb73951528cee6ee3c2e24d8e15a4c2d5c;hpb=a0c703ac04217369edcc80c55d2fafd1a0efefe4;p=transportpce.git 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 2aa455cb7..960ae3bc1 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,19 +8,29 @@ package org.opendaylight.transportpce.pce.graph; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.math.RoundingMode; import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; - +import java.util.stream.Collectors; import org.jgrapht.GraphPath; import org.opendaylight.transportpce.common.ResponseCodes; +import org.opendaylight.transportpce.common.StringConstants; +import org.opendaylight.transportpce.common.fixedflex.GridConstant; +import org.opendaylight.transportpce.common.fixedflex.GridUtils; 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.http.org.opendaylight.transportpce.pce.rev220615.SpectrumAssignment; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220615.SpectrumAssignmentBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.OpenroadmLinkType; +import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev181130.OpucnTribSlotDef; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId; import org.opendaylight.yangtools.yang.common.Uint16; import org.slf4j.Logger; @@ -30,13 +40,16 @@ public class PostAlgoPathValidator { /* Logging. */ private static final Logger LOG = LoggerFactory.getLogger(PostAlgoPathValidator.class); - 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; + @SuppressWarnings("fallthrough") + @SuppressFBWarnings( + value = "SF_SWITCH_FALLTHROUGH", + justification = "intentional fallthrough") public PceResult checkPath(GraphPath path, Map allPceNodes, PceResult pceResult, PceConstraints pceHardConstraints, String serviceType) { @@ -45,23 +58,40 @@ public class PostAlgoPathValidator { pceResult.setRC(ResponseCodes.RESPONSE_FAILED); return pceResult; } - - int tribSlotNb = 1; + 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 "100GE": - case "OTU4": - // choose wavelength available in all nodes of the path - Long waveL = chooseWavelength(path, allPceNodes); + 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 (waveL < 0) { + 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; } - pceResult.setResultWavelength(waveL); - LOG.info("In PostAlgoPathValidator: chooseWavelength WL found {} {}", waveL, path); + if (spectrumAssignment.getFlexGrid()) { + LOG.info("Spectrum assignment flexgrid mode"); + pceResult.setResultWavelength(GridConstant.IRRELEVANT_WAVELENGTH_NUMBER); + } else { + LOG.info("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.info("In PostAlgoPathValidator: spectrum assignment found {} {}", spectrumAssignment, path); // Check the OSNR if (!checkOSNR(path)) { @@ -90,77 +120,58 @@ public class PostAlgoPathValidator { pceResult.setRC(ResponseCodes.RESPONSE_OK); pceResult.setLocalCause(PceResult.LocalCause.NONE); - break; - - case "10GE": - tribSlotNb = 10; - //fallthrough - case "1GE": + case StringConstants.SERVICE_TYPE_100GE_M: + case StringConstants.SERVICE_TYPE_10GE: + case StringConstants.SERVICE_TYPE_1GE: + Map tribSlotNbMap = Map.of( + StringConstants.SERVICE_TYPE_100GE_M, 20, + StringConstants.SERVICE_TYPE_10GE, 8, + StringConstants.SERVICE_TYPE_1GE, 1); + int tribSlotNb = tribSlotNbMap.get(serviceType); pceResult.setRC(ResponseCodes.RESPONSE_FAILED); pceResult.setServiceType(serviceType); - Map tribPort = chooseTribPort(path, allPceNodes); Map> tribSlot = chooseTribSlot(path, allPceNodes, tribSlotNb); + Map tribPort = chooseTribPort(path, allPceNodes, tribSlot, tribSlotNb); + List resultTribPortTribSlot = getMinMaxTpTs(tribPort, tribSlot); - if (tribPort != null && tribSlot != null) { - pceResult.setResultTribPort(tribPort); - pceResult.setResultTribSlot(tribSlot); - pceResult.setResultTribSlotNb(tribSlotNb); + 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); } break; - - case "ODU4": + 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); - LOG.info("In PostAlgoPathValidator: ODU4 path found {}", path); + pceResult.setServiceType(serviceType); + LOG.info("In PostAlgoPathValidator: ODU4/ODUCn path found {}", path); break; - default: pceResult.setRC(ResponseCodes.RESPONSE_FAILED); LOG.warn("In PostAlgoPathValidator checkPath: unsupported serviceType {} found {}", serviceType, path); break; } - return pceResult; } - // Choose the first available wavelength from the source to the destination - private Long chooseWavelength(GraphPath path, Map allPceNodes) { - Long wavelength = -1L; - for (long i = 1; i <= MAX_WAWELENGTH; i++) { - boolean completed = true; - LOG.debug("In chooseWavelength: {} {}", path.getLength(), path); - for (PceGraphEdge edge : path.getEdgeList()) { - LOG.debug("In chooseWavelength: source {} ", edge.link().getSourceId()); - PceNode pceNode = allPceNodes.get(edge.link().getSourceId()); - if (!pceNode.checkWL(i)) { - completed = false; - break; - } - } - if (completed) { - wavelength = i; - break; - } - } - return wavelength; - } - // 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) { + 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); } @@ -192,42 +203,19 @@ public class PostAlgoPathValidator { 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; + List listNodeToInclude = listToInclude + .stream().filter(rp -> PceConstraints.ResourceType.NODE.equals(rp.getType())) + .map(ResourcePair::getName).collect(Collectors.toList()); + List listSrlgToInclude = listToInclude + .stream().filter(rp -> PceConstraints.ResourceType.SRLG.equals(rp.getType())) + .map(ResourcePair::getName).collect(Collectors.toList()); + List listClliToInclude = listToInclude + .stream().filter(rp -> PceConstraints.ResourceType.CLLI.equals(rp.getType())) + .map(ResourcePair::getName).collect(Collectors.toList()); + + return listOfElementsSubNode.containsAll(listNodeToInclude) + && listOfElementsSRLG.containsAll(listSrlgToInclude) + && listOfElementsCLLI.containsAll(listClliToInclude); } private List listOfElementsBuild(List pathEdges, PceConstraints.ResourceType type, @@ -273,28 +261,34 @@ public class PostAlgoPathValidator { } private Map chooseTribPort(GraphPath path, Map allPceNodes) { + PceGraphEdge> path, Map allPceNodes, Map> tribSlotMap, int nbSlot) { LOG.info("In choosetribPort: edgeList = {} ", path.getEdgeList()); Map tribPortMap = new HashMap<>(); for (PceGraphEdge edge : path.getEdgeList()) { NodeId linkSrcNode = edge.link().getSourceId(); - String linkSrcTp = edge.link().getSourceTP().toString(); + String linkSrcTp = edge.link().getSourceTP().getValue(); NodeId linkDestNode = edge.link().getDestId(); - String linkDestTp = edge.link().getDestTP().toString(); + String linkDestTp = edge.link().getDestTP().getValue(); PceNode pceOtnNodeSrc = allPceNodes.get(linkSrcNode); PceNode pceOtnNodeDest = allPceNodes.get(linkDestNode); List srcTpnPool = pceOtnNodeSrc.getAvailableTribPorts().get(linkSrcTp); List destTpnPool = pceOtnNodeDest.getAvailableTribPorts().get(linkDestTp); List commonEdgeTpnPool = new ArrayList<>(); - for (Uint16 integer : srcTpnPool) { - if (destTpnPool.contains(integer)) { - commonEdgeTpnPool.add(integer); + for (Uint16 srcTpn : srcTpnPool) { + if (destTpnPool.contains(srcTpn)) { + commonEdgeTpnPool.add(srcTpn); } } - Collections.sort(commonEdgeTpnPool); + if (!commonEdgeTpnPool.isEmpty()) { - tribPortMap.put(edge.link().getLinkId().getValue(), commonEdgeTpnPool.get(0)); + Integer startTribSlot = tribSlotMap.values().stream().findFirst().get().get(0).toJava(); + Integer tribPort = (int) Math.ceil((double)startTribSlot / nbSlot); + for (Uint16 commonTribPort : commonEdgeTpnPool) { + if (tribPort.equals(commonTribPort.toJava())) { + tribPortMap.put(edge.link().getLinkId().getValue(), commonTribPort); + } + } } } tribPortMap.forEach((k,v) -> LOG.info("TribPortMap : k = {}, v = {}", k, v)); @@ -303,39 +297,47 @@ public class PostAlgoPathValidator { private Map> chooseTribSlot(GraphPath path, Map allPceNodes, int nbSlot) { - LOG.info("In choosetribSlot2: edgeList = {} ", path.getEdgeList()); + LOG.info("In choosetribSlot: edgeList = {} ", path.getEdgeList()); Map> tribSlotMap = new HashMap<>(); for (PceGraphEdge edge : path.getEdgeList()) { NodeId linkSrcNode = edge.link().getSourceId(); - String linkSrcTp = edge.link().getSourceTP().toString(); + String linkSrcTp = edge.link().getSourceTP().getValue(); NodeId linkDestNode = edge.link().getDestId(); - String linkDestTp = edge.link().getDestTP().toString(); + String linkDestTp = edge.link().getDestTP().getValue(); PceNode pceOtnNodeSrc = allPceNodes.get(linkSrcNode); PceNode pceOtnNodeDest = allPceNodes.get(linkDestNode); List srcTsPool = pceOtnNodeSrc.getAvailableTribSlots().get(linkSrcTp); List destTsPool = pceOtnNodeDest.getAvailableTribSlots().get(linkDestTp); - List commonEdgeTsPool = new ArrayList<>(); + List commonEdgeTsPoolList = new ArrayList<>(); List tribSlotList = new ArrayList<>(); for (Uint16 integer : srcTsPool) { if (destTsPool.contains(integer)) { - commonEdgeTsPool.add(integer); + commonEdgeTsPoolList.add(integer); } } - Collections.sort(commonEdgeTsPool); - boolean discontinue = true; - int index = 0; - while (discontinue && (commonEdgeTsPool.size() - index >= nbSlot)) { - discontinue = false; - Integer val = commonEdgeTsPool.get(index).toJava(); - for (int i = 0; i < nbSlot; i++) { - if (commonEdgeTsPool.get(index + i).equals(Uint16.valueOf(val + i))) { - tribSlotList.add(commonEdgeTsPool.get(index + i)); - } else { - discontinue = true; - tribSlotList.clear(); - index += i; - break; + Collections.sort(commonEdgeTsPoolList); + List commonGoodStartEdgeTsPoolList = new ArrayList<>(); + for (Uint16 startEdgeTsPool : commonEdgeTsPoolList) { + if (Integer.valueOf(1).equals(startEdgeTsPool.toJava() % nbSlot) + || nbSlot == 1) { + commonGoodStartEdgeTsPoolList.add(startEdgeTsPool); + } + } + Collections.sort(commonGoodStartEdgeTsPoolList); + boolean goodTsList = false; + for (Uint16 goodStartTsPool : commonGoodStartEdgeTsPoolList) { + int goodStartIndex = commonEdgeTsPoolList.indexOf(Uint16.valueOf(goodStartTsPool.intValue())); + if (!goodTsList && commonEdgeTsPoolList.size() - goodStartIndex >= nbSlot) { + for (int i = 0; i < nbSlot; i++) { + if (!commonEdgeTsPoolList.get(goodStartIndex + i) + .equals(Uint16.valueOf(goodStartTsPool.toJava() + i))) { + goodTsList = false; + tribSlotList.clear(); + break; + } + tribSlotList.add(commonEdgeTsPoolList.get(goodStartIndex + i)); + goodTsList = true; } } } @@ -345,59 +347,18 @@ public class PostAlgoPathValidator { return tribSlotMap; } - private List> chooseTribSlot3(GraphPath path, - Map allPceNodes) { - List> 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(PceNode.class)) { - LOG.debug("In choosetribPort: {} {}", path.getLength(), path); - } - for (PceGraphEdge edge : path.getEdgeList()) { - LOG.debug("In chooseTribSlot: source {} ", edge.link().getSourceId()); - 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 tribSlotEdgeSourceN = pceNode.getAvailableTribSlots().get(tps.toString()); - List 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).equals(tribSlotEdgeDestN.get(i))) { - check = true; - } else { - check = false; - LOG.debug("In chooseTribSlot: Misalignement of trib slots between source {} and dest {}", - edge.link().getSourceId(), edge.link().getDestId()); - break; - } - } - if (check) { - tribSlot.add(tribSlotEdgeSourceN); - } - } else { - LOG.debug("In chooseTribSlot: source {} does not have provisonned hosting HO interface ", - edge.link().getSourceId()); - statusOK = false; - } - } - if (statusOK && check) { - return tribSlot; - } else { - tribSlot.clear(); - return tribSlot; - } + private List getMinMaxTpTs(Map tribPort, Map> tribSlot) { + String tribport = tribPort.values().toArray()[0].toString(); + @SuppressWarnings("unchecked") + List tsList = (List) tribSlot.values().toArray()[0]; + OpucnTribSlotDef minOpucnTs = OpucnTribSlotDef + .getDefaultInstance(String.join(".", tribport, tsList.get(0).toString())); + OpucnTribSlotDef maxOpucnTs = OpucnTribSlotDef + .getDefaultInstance(String.join(".", tribport, tsList.get(tsList.size() - 1).toString())); + List minmaxTpTsList = new ArrayList<>(); + minmaxTpTsList.add(minOpucnTs); + minmaxTpTsList.add(maxOpucnTs); + return minmaxTpTsList; } // Check the path OSNR @@ -427,17 +388,94 @@ public class PostAlgoPathValidator { } private double getOsnrDb(double osnrLu) { - double osnrDb; - osnrDb = 10 * Math.log10(osnrLu); - return osnrDb; + return (10 * Math.log10(osnrLu)); } private double getInverseOsnrLinkLu(double linkOsnrDb) { // 1 over the link OSNR, in linear units - double linkOsnrLu; - linkOsnrLu = Math.pow(10, (linkOsnrDb / 10.0)); + double linkOsnrLu = Math.pow(10, (linkOsnrDb / 10.0)); LOG.debug("In retrieveosnr: the inverse of link osnr is {} (Linear Unit)", linkOsnrLu); return (CONST_OSNR / linkOsnrLu); } + /** + * Get spectrum assignment for path. + * + * @param path the path for which we get spectrum assignment. + * @param allPceNodes all optical nodes. + * @param spectralWidthSlotNumber number of slot for spectral width. Depends on + * service type. + * @return a spectrum assignment object which contains begin and end index. If + * no spectrum assignment found, beginIndex = stopIndex = 0 + */ + private SpectrumAssignment getSpectrumAssignment(GraphPath path, + Map allPceNodes, int spectralWidthSlotNumber) { + byte[] freqMap = new byte[GridConstant.NB_OCTECTS]; + Arrays.fill(freqMap, (byte) GridConstant.AVAILABLE_SLOT_VALUE); + BitSet result = BitSet.valueOf(freqMap); + boolean isFlexGrid = true; + LOG.info("Processing path {} with length {}", path, path.getLength()); + BitSet pceNodeFreqMap; + for (PceGraphEdge edge : path.getEdgeList()) { + LOG.info("Processing source {} ", edge.link().getSourceId()); + if (allPceNodes.containsKey(edge.link().getSourceId())) { + PceNode pceNode = allPceNodes.get(edge.link().getSourceId()); + LOG.info("Processing PCE node {}", pceNode); + if (StringConstants.OPENROADM_DEVICE_VERSION_1_2_1.equals(pceNode.getVersion())) { + LOG.info("Node {}: version is {} and slot width granularity is {} -> fixed grid mode", + pceNode.getNodeId(), pceNode.getVersion(), pceNode.getSlotWidthGranularity()); + isFlexGrid = false; + } + if ((pceNode.getSlotWidthGranularity().setScale(0, RoundingMode.CEILING) + .equals(GridConstant.SLOT_WIDTH_50)) + && (pceNode.getCentralFreqGranularity().setScale(0, RoundingMode.CEILING) + .equals(GridConstant.SLOT_WIDTH_50))) { + LOG.debug("Node {}: version is {} with slot width granularity {} and central " + + "frequency granularity is {} -> fixed grid mode", + pceNode.getNodeId(), pceNode.getVersion(), pceNode.getSlotWidthGranularity(), + pceNode.getCentralFreqGranularity()); + isFlexGrid = false; + } + pceNodeFreqMap = pceNode.getBitSetData(); + LOG.debug("Pce node bitset {}", pceNodeFreqMap); + if (pceNodeFreqMap != null) { + result.and(pceNodeFreqMap); + LOG.debug("intermediate bitset {}", result); + } + } + } + LOG.debug("Bitset result {}", result); + return computeBestSpectrumAssignment(result, spectralWidthSlotNumber, isFlexGrid); + } + + /** + * Compute spectrum assignment from spectrum occupation for spectral width. + * + * @param spectrumOccupation the spectrum occupation BitSet. + * @param spectralWidthSlotNumber the nb slots for spectral width. + * @param isFlexGrid true if flexible grid, false otherwise. + * @return a spectrum assignment object which contains begin and stop index. If + * no spectrum assignment found, beginIndex = stopIndex = 0 + */ + private SpectrumAssignment computeBestSpectrumAssignment(BitSet spectrumOccupation, int spectralWidthSlotNumber, + boolean isFlexGrid) { + SpectrumAssignmentBuilder spectrumAssignmentBldr = new SpectrumAssignmentBuilder() + .setBeginIndex(Uint16.valueOf(0)) + .setStopIndex(Uint16.valueOf(0)) + .setFlexGrid(isFlexGrid); + BitSet referenceBitSet = new BitSet(spectralWidthSlotNumber); + referenceBitSet.set(0, spectralWidthSlotNumber); + int nbSteps = isFlexGrid ? spectralWidthSlotNumber : 1; + //higher is the frequency, smallest is the wavelength number + //in operational, the allocation is done through wavelength starting from the smallest + //so we have to loop from the last element of the spectrum occupation + for (int i = spectrumOccupation.size(); i >= spectralWidthSlotNumber; i -= nbSteps) { + if (spectrumOccupation.get(i - spectralWidthSlotNumber, i).equals(referenceBitSet)) { + spectrumAssignmentBldr.setBeginIndex(Uint16.valueOf(i - spectralWidthSlotNumber)); + spectrumAssignmentBldr.setStopIndex(Uint16.valueOf(i - 1)); + break; + } + } + return spectrumAssignmentBldr.build(); + } }