package org.opendaylight.transportpce.pce.graph;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
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 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.rev210701.SpectrumAssignment;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.SpectrumAssignmentBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmLinkType;
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;
import org.slf4j.LoggerFactory;
public class PostAlgoPathValidator {
/* Logging. */
- private static final Logger LOG = LoggerFactory.getLogger(PceGraph.class);
+ private static final Logger LOG = LoggerFactory.getLogger(PostAlgoPathValidator.class);
- // 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;
+ @SuppressFBWarnings(
+ value = "SF_SWITCH_FALLTHROUGH",
+ justification = "intentional fallthrough")
public PceResult checkPath(GraphPath<String, PceGraphEdge> path, Map<NodeId, PceNode> allPceNodes,
PceResult pceResult, PceConstraints pceHardConstraints, String serviceType) {
// check if the path is empty
- if (path.getEdgeList().size() == 0) {
+ if (path.getEdgeList().isEmpty()) {
pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
return pceResult;
}
-
int tribSlotNb = 1;
- //variable to deal wih 1GE (Nb=1) and 10GE (Nb=10) cases
+ 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_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.toString());
-
- // TODO here other post algo validations can be added
- // more data can be sent to PceGraph module via PceResult structure if required
+ 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)) {
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);
break;
-
- case "10GE":
- tribSlotNb = 10;
+ case StringConstants.SERVICE_TYPE_100GE_M:
+ case StringConstants.SERVICE_TYPE_10GE:
+ tribSlotNb = StringConstants.SERVICE_TYPE_10GE.equals(serviceType) ? 8 : 20;
//fallthrough
- case "1GE":
+ case StringConstants.SERVICE_TYPE_1GE:
pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
pceResult.setServiceType(serviceType);
- Map<String, Integer> tribPort = chooseTribPort(path, allPceNodes);
- Map<String, List<Integer>> tribSlot = chooseTribSlot(path, allPceNodes, tribSlotNb);
+ Map<String, Uint16> tribPort = chooseTribPort(path, allPceNodes);
+ Map<String, List<Uint16>> tribSlot = chooseTribSlot(path, allPceNodes, tribSlotNb);
if (tribPort != null && tribSlot != null) {
pceResult.setResultTribPort(tribPort);
tribPort, tribSlot, tribSlotNb);
}
break;
-
- case "ODU4":
+ case StringConstants.SERVICE_TYPE_ODU4:
+ case StringConstants.SERVICE_TYPE_ODUC4:
pceResult.setRC(ResponseCodes.RESPONSE_OK);
- LOG.info("In PostAlgoPathValidator: ODU4 path found {}", path.toString());
+ LOG.info("In PostAlgoPathValidator: ODU4/ODUC4 path found {}", path);
break;
-
default:
pceResult.setRC(ResponseCodes.RESPONSE_FAILED);
LOG.warn("In PostAlgoPathValidator checkPath: unsupported serviceType {} found {}",
- serviceType, path.toString());
+ serviceType, path);
break;
}
return pceResult;
-
- // TODO other post algo validations can be added anf if needed,
- // more data can be sent to PceGraph module via PceResult structure
- }
-
- // 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;
- for (long i = 1; i <= MAX_WAWELENGTH; i++) {
- boolean completed = true;
- LOG.debug("In chooseWavelength: {} {}", path.getLength(), path.toString());
- for (PceGraphEdge edge : path.getEdgeList()) {
- LOG.debug("In chooseWavelength: source {} ", edge.link().getSourceId().toString());
- PceNode pceNode = allPceNodes.get(edge.link().getSourceId());
- if (!pceNode.checkWL(i)) {
- completed = false;
- break;
- }
- }
- if (completed) {
- wavelength = i;
- break;
- }
- }
- return wavelength;
}
// Check the latency
edge.link().getLinkId().getValue());
}
}
- if (latency > maxLatency) {
- return false;
- }
- return true;
+ return (latency < maxLatency);
}
// Check the inclusion if it is defined in the hard constraints
List<PceGraphEdge> pathEdges = path.getEdgeList();
LOG.debug(" in checkInclude vertex list: [{}]", path.getVertexList());
- List<String> listOfElementsSubNode = new ArrayList<String>();
+ 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<String>();
+ 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<String>();
+ List<String> listOfElementsSRLG = new ArrayList<>();
// first link is XPONDEROUTPUT, no SRLG for it
listOfElementsSRLG.add("NONE");
listOfElementsSRLG.addAll(listOfElementsBuild(pathEdges, PceConstraints.ResourceType.SRLG,
private List<String> listOfElementsBuild(List<PceGraphEdge> pathEdges, PceConstraints.ResourceType type,
PceConstraints pceHardConstraints) {
- List<String> listOfElements = new ArrayList<String>();
+ List<String> listOfElements = new ArrayList<>();
for (PceGraphEdge link : pathEdges) {
switch (type) {
case NODE:
listOfElements.add(srlgStr);
LOG.info("listOfElementsBuild. FOUND SRLG {} in link {}", srlgStr, link.link());
found = true;
- continue;
}
}
if (!found) {
return listOfElements;
}
- private Map<String, Integer> chooseTribPort(GraphPath<String,
+ private Map<String, Uint16> chooseTribPort(GraphPath<String,
PceGraphEdge> path, Map<NodeId, PceNode> allPceNodes) {
- LOG.info("In choosetribPort: edgeList = {} ", path.getEdgeList().toString());
- Map<String, Integer> tribPortMap = new HashMap<>();
+ LOG.info("In choosetribPort: edgeList = {} ", path.getEdgeList());
+ Map<String, Uint16> tribPortMap = new HashMap<>();
for (PceGraphEdge edge : path.getEdgeList()) {
NodeId linkSrcNode = edge.link().getSourceId();
String linkDestTp = edge.link().getDestTP().toString();
PceNode pceOtnNodeSrc = allPceNodes.get(linkSrcNode);
PceNode pceOtnNodeDest = allPceNodes.get(linkDestNode);
- List<Integer> srcTpnPool = pceOtnNodeSrc.getAvailableTribPorts().get(linkSrcTp);
- List<Integer> destTpnPool = pceOtnNodeDest.getAvailableTribPorts().get(linkDestTp);
- List<Integer> commonEdgeTpnPool = new ArrayList<>();
- for (Integer integer : srcTpnPool) {
+ List<Uint16> srcTpnPool = pceOtnNodeSrc.getAvailableTribPorts().get(linkSrcTp);
+ List<Uint16> destTpnPool = pceOtnNodeDest.getAvailableTribPorts().get(linkDestTp);
+ List<Uint16> commonEdgeTpnPool = new ArrayList<>();
+ for (Uint16 integer : srcTpnPool) {
if (destTpnPool.contains(integer)) {
commonEdgeTpnPool.add(integer);
}
return tribPortMap;
}
- private Map<String, List<Integer>> chooseTribSlot(GraphPath<String,
+ private Map<String, List<Uint16>> chooseTribSlot(GraphPath<String,
PceGraphEdge> path, Map<NodeId, PceNode> allPceNodes, int nbSlot) {
- LOG.info("In choosetribSlot2: edgeList = {} ", path.getEdgeList().toString());
- Map<String, List<Integer>> tribSlotMap = new HashMap<>();
+ LOG.info("In choosetribSlot: edgeList = {} ", path.getEdgeList());
+ Map<String, List<Uint16>> tribSlotMap = new HashMap<>();
for (PceGraphEdge edge : path.getEdgeList()) {
NodeId linkSrcNode = edge.link().getSourceId();
String linkDestTp = edge.link().getDestTP().toString();
PceNode pceOtnNodeSrc = allPceNodes.get(linkSrcNode);
PceNode pceOtnNodeDest = allPceNodes.get(linkDestNode);
- List<Integer> srcTsPool = pceOtnNodeSrc.getAvailableTribSlots().get(linkSrcTp);
- List<Integer> destTsPool = pceOtnNodeDest.getAvailableTribSlots().get(linkDestTp);
- List<Integer> commonEdgeTsPool = new ArrayList<>();
- List<Integer> tribSlotList = new ArrayList<>();
- for (Integer integer : srcTsPool) {
+ List<Uint16> srcTsPool = pceOtnNodeSrc.getAvailableTribSlots().get(linkSrcTp);
+ List<Uint16> destTsPool = pceOtnNodeDest.getAvailableTribSlots().get(linkDestTp);
+ List<Uint16> commonEdgeTsPool = new ArrayList<>();
+ List<Uint16> tribSlotList = new ArrayList<>();
+ for (Uint16 integer : srcTsPool) {
if (destTsPool.contains(integer)) {
commonEdgeTsPool.add(integer);
}
int index = 0;
while (discontinue && (commonEdgeTsPool.size() - index >= nbSlot)) {
discontinue = false;
- Integer val = commonEdgeTsPool.get(index);
+ Integer val = commonEdgeTsPool.get(index).toJava();
for (int i = 0; i < nbSlot; i++) {
- if (commonEdgeTsPool.get(index + i).equals(val + i)) {
+ if (commonEdgeTsPool.get(index + i).equals(Uint16.valueOf(val + i))) {
tribSlotList.add(commonEdgeTsPool.get(index + i));
} else {
discontinue = true;
return tribSlotMap;
}
- private List<List<Integer>> chooseTribSlot3(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(PceNode.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;
return false;
}
LOG.info("In checkOSNR: OSNR of the path is {} dB", osnrDb);
- 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;
+ return ((osnrDb + SYS_MARGIN) > MIN_OSNR_W100G);
}
private double getOsnrDb(double osnrLu) {
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<String, PceGraphEdge> path,
+ Map<NodeId, PceNode> 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().equals(GridConstant.SLOT_WIDTH_50))
+ && (pceNode.getCentralFreqGranularity().equals(GridConstant.SLOT_WIDTH_50))) {
+ LOG.info("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 = 1;
+ if (isFlexGrid) {
+ nbSteps = spectralWidthSlotNumber;
+ }
+ //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();
+ }
+}
\ No newline at end of file