Deprecate IndexedLambda and remove from optical intent compiler.
Allow drivers to report any spectral grid. Bugfixes.
ONOS-3495
Change-Id: Ied946660d48e482c1746d1e87735498b1637bb4b
diff --git a/apps/optical/src/main/java/org/onosproject/optical/testapp/LambdaForwarding.java b/apps/optical/src/main/java/org/onosproject/optical/testapp/LambdaForwarding.java
index 05d6f12..da3cc13 100644
--- a/apps/optical/src/main/java/org/onosproject/optical/testapp/LambdaForwarding.java
+++ b/apps/optical/src/main/java/org/onosproject/optical/testapp/LambdaForwarding.java
@@ -15,11 +15,6 @@
*/
package org.onosproject.optical.testapp;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.HashMap;
-import java.util.Map;
-
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
@@ -44,9 +39,17 @@
import org.onosproject.net.flow.instructions.Instructions;
import org.slf4j.Logger;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
/**
* Sample reactive forwarding application.
+ *
+ * @deprecated in Emu (ONOS 1.4).
*/
+@Deprecated
//@Component(immediate = true)
public class LambdaForwarding {
diff --git a/core/api/src/main/java/org/onosproject/net/ChannelSpacing.java b/core/api/src/main/java/org/onosproject/net/ChannelSpacing.java
index 4da9d6b..42183aa 100644
--- a/core/api/src/main/java/org/onosproject/net/ChannelSpacing.java
+++ b/core/api/src/main/java/org/onosproject/net/ChannelSpacing.java
@@ -25,7 +25,7 @@
CHL_50GHZ(50), // 50 GHz
CHL_25GHZ(25), // 25 GHz
CHL_12P5GHZ(12.5), // 12.5 GHz
- CHL_6P25GHZ(6.5); // 6.25 GHz
+ CHL_6P25GHZ(6.25); // 6.25 GHz
private final Frequency frequency;
diff --git a/core/api/src/main/java/org/onosproject/net/IndexedLambda.java b/core/api/src/main/java/org/onosproject/net/IndexedLambda.java
index 6b5fa65..84aa370 100644
--- a/core/api/src/main/java/org/onosproject/net/IndexedLambda.java
+++ b/core/api/src/main/java/org/onosproject/net/IndexedLambda.java
@@ -19,7 +19,10 @@
/**
* Implementation of Lambda simply designated by an index number of wavelength.
+ *
+ * @deprecated in Emu (ONOS 1.4).
*/
+@Deprecated
public class IndexedLambda implements Lambda {
private final long index;
diff --git a/core/api/src/main/java/org/onosproject/net/OchSignal.java b/core/api/src/main/java/org/onosproject/net/OchSignal.java
index 3adc908..d0dfdf3 100644
--- a/core/api/src/main/java/org/onosproject/net/OchSignal.java
+++ b/core/api/src/main/java/org/onosproject/net/OchSignal.java
@@ -16,10 +16,18 @@
package org.onosproject.net;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
import org.onlab.util.Frequency;
import org.onlab.util.Spectrum;
+import java.util.List;
import java.util.Objects;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -33,14 +41,13 @@
*/
public class OchSignal implements Lambda {
- public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5);
+ public static final Set<Integer> FIXED_GRID_SLOT_GRANULARITIES = ImmutableSet.of(1, 2, 4, 8);
private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM;
private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
-
private final GridType gridType;
private final ChannelSpacing channelSpacing;
- // Frequency = 193.1 THz + spacingMultiplier * channelSpacing
+ // Nominal central frequency = 193.1 THz + spacingMultiplier * channelSpacing
private final int spacingMultiplier;
// Slot width = slotGranularity * 12.5 GHz
private final int slotGranularity;
@@ -118,9 +125,9 @@
}
/**
- * Returns slow width granularity.
+ * Returns slot width granularity.
*
- * @return slow width granularity
+ * @return slot width granularity
*/
public int slotGranularity() {
return slotGranularity;
@@ -141,7 +148,56 @@
* @return slot width
*/
public Frequency slotWidth() {
- return FLEX_GRID_SLOT.multiply(slotGranularity);
+ return ChannelSpacing.CHL_12P5GHZ.frequency().multiply(slotGranularity);
+ }
+
+ /**
+ * Convert fixed grid OCh signal to sorted set of flex grid slots with 6.25 GHz spacing and 12.5 GHz slot width.
+ *
+ * @param ochSignal fixed grid lambda
+ * @return sorted set of flex grid OCh lambdas
+ */
+ public static SortedSet<OchSignal> toFlexGrid(OchSignal ochSignal) {
+ checkArgument(ochSignal.gridType() != GridType.FLEX);
+ checkArgument(ochSignal.channelSpacing() != ChannelSpacing.CHL_6P25GHZ);
+ checkArgument(FIXED_GRID_SLOT_GRANULARITIES.contains(ochSignal.slotGranularity()));
+
+ int startMultiplier = (int) (1 - ochSignal.slotGranularity() +
+ ochSignal.spacingMultiplier() * ochSignal.channelSpacing().frequency().asHz() /
+ ChannelSpacing.CHL_6P25GHZ.frequency().asHz());
+
+ Supplier<SortedSet<OchSignal>> supplier = () -> new TreeSet<>(new DefaultOchSignalComparator());
+ return IntStream.range(0, ochSignal.slotGranularity())
+ .mapToObj(i -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_6P25GHZ, startMultiplier + 2 * i, 1))
+ .collect(Collectors.toCollection(supplier));
+ }
+
+ /**
+ * Convert list of lambdas with flex grid 6.25 GHz spacing and 12.5 GHz width into fixed grid OCh signal.
+ *
+ * @param lambdas list of flex grid lambdas in sorted order
+ * @param spacing desired fixed grid spacing
+ * @return fixed grid lambda
+ */
+ public static OchSignal toFixedGrid(List<OchSignal> lambdas, ChannelSpacing spacing) {
+ // Number of slots of 12.5 GHz that fit into requested spacing
+ int ratio = (int) (spacing.frequency().asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz());
+ checkArgument(lambdas.size() == ratio);
+ lambdas.forEach(x -> checkArgument(x.gridType() == GridType.FLEX));
+ lambdas.forEach(x -> checkArgument(x.channelSpacing() == ChannelSpacing.CHL_6P25GHZ));
+ lambdas.forEach(x -> checkArgument(x.slotGranularity() == 1));
+ // Consecutive lambdas (multiplier increments by 2 because spacing is 6.25 GHz but slot width is 12.5 GHz)
+ IntStream.range(1, lambdas.size())
+ .forEach(i -> checkArgument(
+ lambdas.get(i).spacingMultiplier() == lambdas.get(i - 1).spacingMultiplier() + 2));
+ // Is center frequency compatible with requested spacing
+ Frequency center = lambdas.get(ratio / 2).centralFrequency().subtract(ChannelSpacing.CHL_6P25GHZ.frequency());
+ checkArgument(Spectrum.CENTER_FREQUENCY.subtract(center).asHz() % spacing.frequency().asHz() == 0);
+
+ // Multiplier sits in middle of given lambdas, then convert from 6.25 to requested spacing
+ int spacingMultiplier = (lambdas.get(ratio / 2).spacingMultiplier() + 1) / (ratio * 2);
+
+ return new OchSignal(GridType.DWDM, spacing, spacingMultiplier, lambdas.size());
}
@Override
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/IndexedLambdaCriterion.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/IndexedLambdaCriterion.java
index 88a6fe1..bc612cd 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/criteria/IndexedLambdaCriterion.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/IndexedLambdaCriterion.java
@@ -25,6 +25,7 @@
/**
* Implementation of indexed lambda criterion.
*/
+@Deprecated
public class IndexedLambdaCriterion implements Criterion {
private final IndexedLambda lambda;
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
index e017ac5..2d4545c 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
@@ -26,14 +26,14 @@
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.util.Frequency;
import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultOchSignalComparator;
import org.onosproject.net.DeviceId;
-import org.onosproject.net.IndexedLambda;
import org.onosproject.net.Link;
import org.onosproject.net.OchPort;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OchSignalType;
-import org.onosproject.net.OmsPort;
import org.onosproject.net.Path;
import org.onosproject.net.Port;
import org.onosproject.net.device.DeviceService;
@@ -53,6 +53,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -64,11 +65,12 @@
/**
* An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}.
*/
-// For now, remove component designation until dependency on the new resource manager is available.
@Component(immediate = true)
public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
protected static final Logger log = LoggerFactory.getLogger(OpticalConnectivityIntentCompiler.class);
+ // By default, allocate 50 GHz lambdas (4 slots of 12.5 GHz) for each intent.
+ private static final int SLOT_COUNT = 4;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentExtensionService intentManager;
@@ -133,16 +135,15 @@
srcOchPort.lambda().channelSpacing(),
srcOchPort.lambda().slotGranularity());
} else if (!srcOchPort.isTunable() || !dstOchPort.isTunable()) {
- // FIXME: also check OCh port
+ // FIXME: also check destination OCh port
ochSignal = srcOchPort.lambda();
} else {
// Request and reserve lambda on path
- IndexedLambda lambda = assignWavelength(intent, path);
- if (lambda == null) {
+ List<OchSignal> lambdas = assignWavelength(intent, path);
+ if (lambdas.isEmpty()) {
continue;
}
- OmsPort omsPort = (OmsPort) deviceService.getPort(path.src().deviceId(), path.src().port());
- ochSignal = new OchSignal((int) lambda.index(), omsPort.maxFrequency(), omsPort.grid());
+ ochSignal = OchSignal.toFixedGrid(lambdas, ChannelSpacing.CHL_50GHZ);
}
// Create installable optical path intent
@@ -174,48 +175,77 @@
* @param path path in WDM topology
* @return first available lambda allocated
*/
- private IndexedLambda assignWavelength(Intent intent, Path path) {
- Set<IndexedLambda> lambdas = findCommonLambdasOverLinks(path.links());
+ private List<OchSignal> assignWavelength(Intent intent, Path path) {
+ Set<OchSignal> lambdas = findCommonLambdasOverLinks(path.links());
if (lambdas.isEmpty()) {
- return null;
+ return Collections.emptyList();
}
- IndexedLambda minLambda = findFirstLambda(lambdas);
+ List<OchSignal> minLambda = findFirstLambda(lambdas, slotCount());
List<ResourcePath> lambdaResources = path.links().stream()
.flatMap(x -> Stream.of(
ResourcePath.discrete(x.src().deviceId(), x.src().port()),
ResourcePath.discrete(x.dst().deviceId(), x.dst().port())
))
- .map(x -> x.child(minLambda))
+ .flatMap(x -> minLambda.stream().map(l -> x.child(l)))
.collect(Collectors.toList());
List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), lambdaResources);
if (allocations.isEmpty()) {
log.info("Resource allocation for {} failed (resource request: {})", intent, lambdaResources);
- return null;
+ return Collections.emptyList();
}
return minLambda;
}
- private Set<IndexedLambda> findCommonLambdasOverLinks(List<Link> links) {
+ /**
+ * Get the number of 12.5 GHz slots required for the path.
+ *
+ * For now this returns a constant value of 4 (i.e., fixed grid 50 GHz slot),
+ * but in the future can depend on optical reach, line rate, transponder port capabilities, etc.
+ *
+ * @return number of slots
+ */
+ private int slotCount() {
+ return SLOT_COUNT;
+ }
+
+ private Set<OchSignal> findCommonLambdasOverLinks(List<Link> links) {
return links.stream()
.flatMap(x -> Stream.of(
ResourcePath.discrete(x.src().deviceId(), x.src().port()),
ResourcePath.discrete(x.dst().deviceId(), x.dst().port())
))
.map(resourceService::getAvailableResources)
- .map(x -> Iterables.filter(x, r -> r.last() instanceof IndexedLambda))
- .map(x -> Iterables.transform(x, r -> (IndexedLambda) r.last()))
- .map(x -> (Set<IndexedLambda>) ImmutableSet.copyOf(x))
+ .map(x -> Iterables.filter(x, r -> r.last() instanceof OchSignal))
+ .map(x -> Iterables.transform(x, r -> (OchSignal) r.last()))
+ .map(x -> (Set<OchSignal>) ImmutableSet.copyOf(x))
.reduce(Sets::intersection)
.orElse(Collections.emptySet());
}
- private IndexedLambda findFirstLambda(Set<IndexedLambda> lambdas) {
- return lambdas.stream()
- .findFirst()
- .get();
+ /**
+ * Returns list of consecutive resources in given set of lambdas.
+ *
+ * @param lambdas list of lambdas
+ * @param count number of consecutive lambdas to return
+ * @return list of consecutive lambdas
+ */
+ private List<OchSignal> findFirstLambda(Set<OchSignal> lambdas, int count) {
+ // Sort available lambdas
+ List<OchSignal> lambdaList = new ArrayList<>(lambdas);
+ lambdaList.sort(new DefaultOchSignalComparator());
+
+ // Look ahead by count and ensure spacing multiplier is as expected (i.e., no gaps)
+ for (int i = 0; i < lambdaList.size() - count; i++) {
+ if (lambdaList.get(i).spacingMultiplier() + 2 * count ==
+ lambdaList.get(i + count).spacingMultiplier()) {
+ return lambdaList.subList(i, i + count);
+ }
+ }
+
+ return Collections.emptyList();
}
private ConnectPoint staticPort(ConnectPoint connectPoint) {
diff --git a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java
index 46aeeb0..a1e545f 100644
--- a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java
+++ b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java
@@ -19,6 +19,7 @@
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onlab.util.ItemNotFoundException;
+import org.onosproject.net.DefaultOchSignalComparator;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
@@ -44,7 +45,9 @@
import java.util.Collections;
import java.util.List;
import java.util.SortedSet;
+import java.util.TreeSet;
import java.util.concurrent.ExecutorService;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -199,7 +202,10 @@
}
LambdaQuery query = handler.behaviour(LambdaQuery.class);
if (query != null) {
- return query.queryLambdas(port);
+ Supplier<SortedSet<OchSignal>> supplier = () -> new TreeSet<>(new DefaultOchSignalComparator());
+ return query.queryLambdas(port).stream()
+ .flatMap(x -> OchSignal.toFlexGrid(x).stream())
+ .collect(Collectors.toCollection(supplier));
} else {
return Collections.emptySortedSet();
}
diff --git a/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java b/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java
index 270008f..2f591d3 100644
--- a/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java
+++ b/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java
@@ -51,6 +51,7 @@
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -209,13 +210,12 @@
ChannelSpacing.CHL_12P5GHZ.frequency().asHz();
long stopSpacingMultiplier = Spectrum.O_BAND_MAX.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
ChannelSpacing.CHL_12P5GHZ.frequency().asHz();
- List<OchSignal> lambdas = IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier)
- .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x, 1))
- .collect(Collectors.toList());
+ Supplier<SortedSet<OchSignal>> supplier = () -> new TreeSet<>(new DefaultOchSignalComparator());
- SortedSet<OchSignal> result = new TreeSet<>(new DefaultOchSignalComparator());
- result.addAll(lambdas);
-
- return result;
+ // Only consider odd values for the multiplier (for easy mapping to fixed grid)
+ return IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier)
+ .filter(i -> i % 2 == 1)
+ .mapToObj(i -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_6P25GHZ, i, 1))
+ .collect(Collectors.toCollection(supplier));
}
}
diff --git a/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java b/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
index 23378e9..67a8f0e 100644
--- a/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
+++ b/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
@@ -59,6 +59,7 @@
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -74,7 +75,7 @@
* As LINC implements custom OF optical extensions (in contrast to the final standard as specified in
* ONF TS-022 (March 15, 2015), we need to rewrite flow stat requests and flow mods in {@link #sendMsg(OFMessage)}.
*
- * LINC exposes OchSignal resources: 80 lambdas of 50 GHz around ITU-T G.694.1 center frequency 193.1 GHz.
+ * LINC exposes OchSignal resources: 80 lambdas of 50 GHz (fixed grid) around ITU-T G.694.1 center frequency 193.1 GHz.
*
*/
public class OfOpticalSwitchImplLinc13
@@ -224,8 +225,9 @@
}
OFActionSetField sf = (OFActionSetField) action;
- if (!(sf instanceof OFOxmExpOchSigId)) {
+ if (!(sf.getField() instanceof OFOxmExpOchSigId)) {
newActions.add(action);
+ continue;
}
OFOxmExpOchSigId oxm = (OFOxmExpOchSigId) sf.getField();
@@ -259,7 +261,6 @@
OFFlowMod fm = (OFFlowMod) msg;
newMatch = rewriteMatch(fm.getMatch());
List<OFAction> actions = rewriteActions(fm.getActions());
-
newMsg = fm.createBuilder().setMatch(newMatch).setActions(actions).build();
}
@@ -371,15 +372,10 @@
return Collections.emptySortedSet();
}
- // OMS ports expose 80 lambdas of 50GHz width, centered around the ITU-T center frequency.
- // We report these with a spacing of 12.5 GHz.
- List<OchSignal> lambdas = IntStream.range(0, LAMBDA_COUNT)
- .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x - (LAMBDA_COUNT / 2), 1))
- .collect(Collectors.toList());
-
- SortedSet<OchSignal> result = new TreeSet<>(new DefaultOchSignalComparator());
- result.addAll(lambdas);
-
- return result;
+ // OMS ports expose 80 fixed grid lambdas of 50GHz width, centered around the ITU-T center frequency 193.1 THz.
+ Supplier<SortedSet<OchSignal>> supplier = () -> new TreeSet<>(new DefaultOchSignalComparator());
+ return IntStream.range(0, LAMBDA_COUNT)
+ .mapToObj(x -> new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, x - (LAMBDA_COUNT / 2), 4))
+ .collect(Collectors.toCollection(supplier));
}
}
diff --git a/tools/test/topos/opticalUtils.py b/tools/test/topos/opticalUtils.py
index 44f4e37..a990a8e 100644
--- a/tools/test/topos/opticalUtils.py
+++ b/tools/test/topos/opticalUtils.py
@@ -536,7 +536,9 @@
for link in LINCSwitch.opticalJSON[ 'links' ]:
linkDict = {}
linkDict[ 'type' ] = link[ 'type' ]
- linkDict.update(link[ 'annotations' ])
+ # FIXME: Clean up unnecessary link/device attributes, then re-enable annotations
+ linkDict['durable'] = True
+ # linkDict.update(link[ 'annotations' ])
linkSubj = link[ 'src' ] + '-' + link[ 'dst' ]
links[ linkSubj ] = { 'basic': linkDict }