From 2d17c9909f309efd566e98391092bc353ae7effe Mon Sep 17 00:00:00 2001 From: =?utf8?q?Joakim=20T=C3=B6rnqvist?= Date: Wed, 3 Jul 2024 12:27:16 +0200 Subject: [PATCH] Error in TAPI creating frequency ranges MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When an OpenROADM service is converted to TAPI, an exception (ArrayIndexOutOfBoundsException) is thrown. A byte array (size 96) was used when the code was actually expecting size 768 (i.e. 96 x 8), when trying to create a Map with frequency ranges. The use of method getFreqMapFromBitSet in ConvertORToTapiTopology has been replaced with the package org.opendaylight.transportpce.tapi.frequency. A refactored version of getFreqMapFromBitSet can be found in the class org.opendaylight.transportpce.tapi.frequency.NumericFrequency. JIRA: TRNSPRTPCE-802 Change-Id: I423507decaae38b44d9f6968882179c3ec1b11d4 Signed-off-by: Joakim Törnqvist --- .../topology/ConvertORToTapiTopology.java | 170 ++++++++++-------- .../topology/ConvertORToTapiTopologyTest.java | 100 +++++++++++ 2 files changed, 196 insertions(+), 74 deletions(-) create mode 100644 tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopologyTest.java diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopology.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopology.java index de85dcb4e..76a4ae715 100644 --- a/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopology.java +++ b/tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopology.java @@ -24,8 +24,12 @@ import java.util.TreeMap; import java.util.UUID; import java.util.stream.Collectors; import org.opendaylight.transportpce.common.fixedflex.GridConstant; -import org.opendaylight.transportpce.common.fixedflex.GridUtils; import org.opendaylight.transportpce.tapi.TapiStringConstants; +import org.opendaylight.transportpce.tapi.frequency.Available; +import org.opendaylight.transportpce.tapi.frequency.AvailableGrid; +import org.opendaylight.transportpce.tapi.frequency.FrequencyMath; +import org.opendaylight.transportpce.tapi.frequency.Numeric; +import org.opendaylight.transportpce.tapi.frequency.NumericFrequency; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.TerminationPoint1; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State; import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev230526.degree.used.wavelengths.UsedWavelengths; @@ -165,6 +169,7 @@ public class ConvertORToTapiTopology { private Map tapiLinks; private Map tapiSips; private Map uuidMap; + private final Numeric numericFrequency; static { OPMODE_LOOPRATE_MAP = new TreeMap<>(Comparator.reverseOrder()); @@ -212,11 +217,23 @@ public class ConvertORToTapiTopology { public ConvertORToTapiTopology(Uuid tapiTopoUuid) { + this( + tapiTopoUuid, + new NumericFrequency( + GridConstant.START_EDGE_FREQUENCY, + GridConstant.EFFECTIVE_BITS, + new FrequencyMath() + ) + ); + } + + public ConvertORToTapiTopology(Uuid tapiTopoUuid, Numeric numericFrequency) { this.tapiTopoUuid = tapiTopoUuid; this.tapiNodes = new HashMap<>(); this.tapiLinks = new HashMap<>(); this.uuidMap = new HashMap<>(); this.tapiSips = new HashMap<>(); + this.numericFrequency = numericFrequency; } public void convertNode(Node ietfNode, List networkPorts) { @@ -732,20 +749,28 @@ public class ConvertORToTapiTopology { if (txttpAttAvlFreqMaps == null || !txttpAttAvlFreqMaps.keySet().toString().contains(GridConstant.C_BAND)) { return null; } - byte[] freqBitSet = new byte[GridConstant.NB_OCTECTS]; - LOG.debug("Creation of Bitset {}", freqBitSet); + byte[] freqByteSet = new byte[GridConstant.NB_OCTECTS]; + LOG.debug("Creation of Bitset {}", freqByteSet); AvailFreqMapsKey availFreqMapsKey = new AvailFreqMapsKey(GridConstant.C_BAND); - freqBitSet = txttpAttAvlFreqMaps.entrySet().stream() + freqByteSet = txttpAttAvlFreqMaps.entrySet().stream() .filter(afm -> afm.getKey().equals(availFreqMapsKey)) .findFirst().orElseThrow().getValue().getFreqMap(); - for (int i = 0; i < GridConstant.EFFECTIVE_BITS; i++) { - if (freqBitSet[i] == 0) { - freqBitSet[i] = 1; - } else { - freqBitSet[i] = 0; - } - } - return getFreqMapFromBitSet(freqBitSet); + + LOG.debug("TTP used frequency byte set ({} bytes, 0 represents 8 used frequencies): {} ", + freqByteSet.length, + freqByteSet + ); + Available bitMap = new AvailableGrid(freqByteSet); + + LOG.debug("TTP used frequency bit set (min=0, max={}, each number represents a used frequency): {} ", + GridConstant.EFFECTIVE_BITS, + bitMap.assignedFrequencies() + ); + Map assignedFrequencyRanges = numericFrequency.assignedFrequency(bitMap); + + LOG.info("TTP used frequency map {}", assignedFrequencyRanges); + return assignedFrequencyRanges; + } Map freqMap = new HashMap<>(); for (Map.Entry usedLambdas : txttpAttUsedWvl.entrySet()) { @@ -770,13 +795,29 @@ public class ConvertORToTapiTopology { if (avlFreqMaps == null || !avlFreqMaps.keySet().toString().contains(GridConstant.C_BAND)) { return null; } - byte[] byteArray = new byte[GridConstant.NB_OCTECTS]; - LOG.debug("Creation of Bitset {}", byteArray); + byte[] freqByteSet = new byte[GridConstant.NB_OCTECTS]; + LOG.debug("Creation of Bitset {}", freqByteSet); AvailFreqMapsKey availFreqMapsKey = new AvailFreqMapsKey(GridConstant.C_BAND); - return getFreqMapFromBitSet( - avlFreqMaps.entrySet().stream() + freqByteSet = avlFreqMaps.entrySet().stream() .filter(afm -> afm.getKey().equals(availFreqMapsKey)) - .findFirst().orElseThrow().getValue().getFreqMap()); + .findFirst().orElseThrow().getValue().getFreqMap(); + + + LOG.debug("TTP available frequency byte set ({} bytes, 0 represents 8 available frequencies): {} ", + freqByteSet.length, + freqByteSet + ); + Available bitMap = new AvailableGrid(freqByteSet); + + LOG.debug("TTP available frequency bit set (min=0, max={}, each number represents an available frequency): {}", + GridConstant.EFFECTIVE_BITS, + bitMap.availableFrequencies() + ); + Map availableFrequencyRanges = numericFrequency.availableFrequency(bitMap); + + LOG.info("TTP available frequency map {}", availableFrequencyRanges); + return availableFrequencyRanges; + } public Map getTTP11AvailableFreqMap( @@ -792,13 +833,28 @@ public class ConvertORToTapiTopology { if (avlFreqMaps == null || !avlFreqMaps.keySet().toString().contains(GridConstant.C_BAND)) { return null; } - byte[] byteArray = new byte[GridConstant.NB_OCTECTS]; - LOG.debug("Creation of Bitset {}", byteArray); + byte[] freqByteSet = new byte[GridConstant.NB_OCTECTS]; + LOG.debug("Creation of Bitset {}", freqByteSet); AvailFreqMapsKey availFreqMapsKey = new AvailFreqMapsKey(GridConstant.C_BAND); - return getFreqMapFromBitSet( - avlFreqMaps.entrySet().stream() + freqByteSet = avlFreqMaps.entrySet().stream() .filter(afm -> afm.getKey().equals(availFreqMapsKey)) - .findFirst().orElseThrow().getValue().getFreqMap()); + .findFirst().orElseThrow().getValue().getFreqMap(); + + LOG.debug("TTP11 available frequency byte set ({} bytes, 0 represents 8 available frequencies): {} ", + freqByteSet.length, + freqByteSet + ); + Available bitMap = new AvailableGrid(freqByteSet); + + LOG.debug("TTP11 available frequency bit set (min=0, max={}, " + + "each number represents an available frequency): {}", + GridConstant.EFFECTIVE_BITS, + bitMap.availableFrequencies() + ); + Map availableFrequencyRanges = numericFrequency.availableFrequency(bitMap); + + LOG.info("TTP11 available frequency map {}", availableFrequencyRanges); + return availableFrequencyRanges; } public Map getPP11UsedWavelength( @@ -837,20 +893,27 @@ public class ConvertORToTapiTopology { if (txttpAttAvlFreqMaps == null || !txttpAttAvlFreqMaps.keySet().toString().contains(GridConstant.C_BAND)) { return null; } - byte[] freqBitSet = new byte[GridConstant.NB_OCTECTS]; - LOG.debug("Creation of Bitset {}", freqBitSet); + byte[] freqByteSet = new byte[GridConstant.NB_OCTECTS]; + LOG.debug("Creation of Bitset {}", freqByteSet); AvailFreqMapsKey availFreqMapsKey = new AvailFreqMapsKey(GridConstant.C_BAND); - freqBitSet = txttpAttAvlFreqMaps.entrySet().stream() + freqByteSet = txttpAttAvlFreqMaps.entrySet().stream() .filter(afm -> afm.getKey().equals(availFreqMapsKey)) .findFirst().orElseThrow().getValue().getFreqMap(); - for (int i = 0; i < GridConstant.EFFECTIVE_BITS; i++) { - if (freqBitSet[i] == 0) { - freqBitSet[i] = 1; - } else { - freqBitSet[i] = 0; - } - } - return getFreqMapFromBitSet(freqBitSet); + + LOG.debug("TTP11 used frequency byte set ({} bytes, 0 represents 8 used frequencies): {} ", + freqByteSet.length, + freqByteSet + ); + Available bitMap = new AvailableGrid(freqByteSet); + + LOG.debug("TTP11 used frequency bit set (min=0, max={}, each number represents a used frequency): {}", + GridConstant.EFFECTIVE_BITS, + bitMap.assignedFrequencies() + ); + Map assignedFrequencyRanges = numericFrequency.assignedFrequency(bitMap); + + LOG.info("TTP11 used frequency map {}", assignedFrequencyRanges); + return assignedFrequencyRanges; } Map freqMap = new HashMap<>(); for (Map.Entry usedLambdas : txttpAttUsedWvl.entrySet()) { @@ -862,47 +925,6 @@ public class ConvertORToTapiTopology { return freqMap; } - public Map getFreqMapFromBitSet(byte[] byteArray) { - // Provides a Map describing start and stop frequencies of all slots that are available - // in the ByteArray describing the spectrum : bit sets initially sets to 1/true - // In case the byte array has been inverted before calling this method, it provides respectively a map - // describing all occupied slots! - Map freqMap = new HashMap<>(); - Double startFreq = GridConstant.START_EDGE_FREQUENCY; - Double stopFreq = 0.0; - boolean occupied = false; - if (byteArray[0] == 0) { - occupied = true; - } - for (int index = 0 ; index < GridConstant.EFFECTIVE_BITS ; index++) { - if (occupied) { - if (byteArray[index] == 1) { - startFreq = GridUtils.getStartFrequencyFromIndex(index).doubleValue(); - stopFreq = GridUtils.getStartFrequencyFromIndex(index).doubleValue(); - occupied = false; - } - } else { - if (byteArray[index] == 0) { - stopFreq = GridUtils.getStartFrequencyFromIndex(index).doubleValue(); - occupied = true; - } - } - if (occupied) { - if (stopFreq.doubleValue() > startFreq.doubleValue()) { - freqMap.put(startFreq, stopFreq); - startFreq = stopFreq; - } - } else { - if (index == GridConstant.EFFECTIVE_BITS - 1 - && Double.compare(startFreq.doubleValue(), stopFreq.doubleValue()) == 0) { - stopFreq = GridUtils.getStopFrequencyFromIndex(index).doubleValue(); - freqMap.put(startFreq, stopFreq); - } - } - } - return freqMap; - } - public OwnedNodeEdgePointBuilder addPayloadStructureAndPhotSpecToOnep(String nodeId, Map freqMap, List operModeList, Collection sicColl, OwnedNodeEdgePointBuilder onepBldr, String keyword) { diff --git a/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopologyTest.java b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopologyTest.java new file mode 100644 index 000000000..eb3ac0711 --- /dev/null +++ b/tapi/src/test/java/org/opendaylight/transportpce/tapi/topology/ConvertORToTapiTopologyTest.java @@ -0,0 +1,100 @@ +/* + * Copyright © 2024 Smartoptics and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.tapi.topology; + + +import java.util.Arrays; +import java.util.Map; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.opendaylight.transportpce.tapi.frequency.Math; +import org.opendaylight.transportpce.tapi.frequency.NumericFrequency; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.networks.network.node.termination.point.TxTtpAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.available.freq.map.AvailFreqMaps; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.available.freq.map.AvailFreqMapsBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.available.freq.map.AvailFreqMapsKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointBuilder; +import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Uuid; + +class ConvertORToTapiTopologyTest { + + private ConvertORToTapiTopology convertORToTapiTopology; + + private TerminationPoint1 terminationPoint1; + + private TerminationPoint terminationPoint; + + @BeforeEach + void setUp() { + Math math = Mockito.mock(Math.class); + Mockito.when(math.getStartFrequencyFromIndex(760)).thenReturn(196.075); + Mockito.when(math.getStopFrequencyFromIndex(767)).thenReturn(196.125); + + convertORToTapiTopology = new ConvertORToTapiTopology( + Uuid.getDefaultInstance("123"), + new NumericFrequency( + 191.325, + 768, + math + ) + ); + + byte[] availableFrequencyMap = new byte[96]; + Arrays.fill(availableFrequencyMap, (byte) 255); + availableFrequencyMap[96 - 1] = (byte) 0; + + AvailFreqMaps freqMap = new AvailFreqMapsBuilder() + .setMapName(new AvailFreqMapsKey("cband").getMapName()) + .setFreqMap(availableFrequencyMap) + .build(); + + terminationPoint1 = new TerminationPoint1Builder() + .setTxTtpAttributes( + new TxTtpAttributesBuilder() + .setAvailFreqMaps(Map.of(freqMap.key(), freqMap)) + .build() + ).build(); + + terminationPoint = new TerminationPointBuilder() + .setTpId(TpId.getDefaultInstance("1")) + .addAugmentation(terminationPoint1) + .build(); + } + + @Test + void getTTPUsedFreqMap() { + Map expected = Map.of(196.075, 196.125); + Assertions.assertEquals(expected, convertORToTapiTopology.getTTPUsedFreqMap(terminationPoint)); + } + + @Test + void getTTPAvailableFreqMap() { + Map expected = Map.of(191.325, 196.075); + Assertions.assertEquals(expected, convertORToTapiTopology.getTTPAvailableFreqMap(terminationPoint)); + } + + @Test + void getTTP11UsedFreqMap() { + Map expected = Map.of(196.075, 196.125); + Assertions.assertEquals(expected, convertORToTapiTopology.getTTP11UsedFreqMap(terminationPoint1)); + } + + @Test + void getTTP11AvailableFreqMap() { + Map expected = Map.of(191.325, 196.075); + Assertions.assertEquals(expected, convertORToTapiTopology.getTTP11AvailableFreqMap(terminationPoint1)); + } + +} -- 2.36.6