Implementation of lambda query behaviour for LINC and Calient drivers.
ONOS-3431
Change-Id: I03b7e7c9d2b0ba7e55d09745cfc6ceb57cc6eb5e
diff --git a/core/api/src/main/java/org/onosproject/net/DefaultOchSignalComparator.java b/core/api/src/main/java/org/onosproject/net/DefaultOchSignalComparator.java
new file mode 100644
index 0000000..e605dcf
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/DefaultOchSignalComparator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.util.Comparator;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Comparator implementation for OchSignal. Assumes identical grid type and channel spacing.
+ */
+public class DefaultOchSignalComparator implements Comparator<OchSignal> {
+ @Override
+ public int compare(OchSignal o1, OchSignal o2) {
+ checkNotNull(o1.gridType());
+ checkNotNull(o1.channelSpacing());
+
+ checkArgument(o1.gridType().equals(o2.gridType()));
+ checkArgument(o1.channelSpacing().equals(o2.channelSpacing()));
+
+ return o1.spacingMultiplier() * o1.slotGranularity() - o2.spacingMultiplier() * o2.slotGranularity();
+ }
+}
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 5a5af34..3adc908 100644
--- a/core/api/src/main/java/org/onosproject/net/OchSignal.java
+++ b/core/api/src/main/java/org/onosproject/net/OchSignal.java
@@ -17,6 +17,7 @@
import com.google.common.base.MoreObjects;
import org.onlab.util.Frequency;
+import org.onlab.util.Spectrum;
import java.util.Objects;
@@ -32,7 +33,6 @@
*/
public class OchSignal implements Lambda {
- public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1);
public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5);
private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM;
private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
@@ -78,7 +78,7 @@
this.gridType = DEFAULT_OCH_GRIDTYPE;
this.channelSpacing = DEFAULT_CHANNEL_SPACING;
- this.spacingMultiplier = (int) (centerFrequency.subtract(OchSignal.CENTER_FREQUENCY).asHz() / grid.asHz());
+ this.spacingMultiplier = (int) (centerFrequency.subtract(Spectrum.CENTER_FREQUENCY).asHz() / grid.asHz());
this.slotGranularity = (int) Math.round((double) grid.asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz());
}
@@ -86,7 +86,7 @@
this.gridType = DEFAULT_OCH_GRIDTYPE;
this.channelSpacing = channelSpacing;
this.spacingMultiplier = (int) Math.round((double) centerFrequency.
- subtract(OchSignal.CENTER_FREQUENCY).asHz() / channelSpacing().frequency().asHz());
+ subtract(Spectrum.CENTER_FREQUENCY).asHz() / channelSpacing().frequency().asHz());
this.slotGranularity = slotGranularity;
}
@@ -132,7 +132,7 @@
* @return frequency in MHz
*/
public Frequency centralFrequency() {
- return CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier));
+ return Spectrum.CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier));
}
/**
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 df4dfa5..270008f 100644
--- a/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java
+++ b/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java
@@ -17,7 +17,14 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import org.onlab.util.Spectrum;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.DefaultOchSignalComparator;
import org.onosproject.net.Device;
+import org.onosproject.net.GridType;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.LambdaQuery;
import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
import org.onosproject.openflow.controller.PortDescPropertyType;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
@@ -41,9 +48,24 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
-public class CalientFiberSwitchHandshaker extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
+/**
+ * Driver for Calient S160 Optical Circuit Switch. Untested on Calient S320 but probably works ok.
+ *
+ * Driver implements custom handshaker, and rewrites flow stats as expected by the device. Port stats are currently
+ * not supported.
+ *
+ * The device consists of OMS ports only, and each port exposes lambda resources covering the whole
+ * usable optical spectrum (U to O band, see {@link Spectrum} for spectrum definitions).
+ */
+public class CalientFiberSwitchHandshaker
+ extends AbstractOpenFlowSwitch
+ implements OpenFlowOpticalSwitch, LambdaQuery {
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
private List<OFCalientPortDescStatsEntry> fiberPorts = new ArrayList<>();
@@ -178,4 +200,22 @@
super.sendMsg(newMsg);
}
+
+ @Override
+ public SortedSet<OchSignal> queryLambdas(PortNumber port) {
+ // S160 data sheet
+ // Wavelength range: 1260 - 1630 nm
+ long startSpacingMultiplier = Spectrum.U_BAND_MIN.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
+ 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());
+
+ SortedSet<OchSignal> result = new TreeSet<>(new DefaultOchSignalComparator());
+ result.addAll(lambdas);
+
+ return result;
+ }
}
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 f91e2a7..23378e9 100644
--- a/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
+++ b/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
@@ -16,7 +16,13 @@
package org.onosproject.driver.handshaker;
import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.DefaultOchSignalComparator;
import org.onosproject.net.Device;
+import org.onosproject.net.GridType;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.LambdaQuery;
import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
import org.onosproject.openflow.controller.PortDescPropertyType;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
@@ -42,7 +48,6 @@
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmExpOchSigId;
import org.projectfloodlight.openflow.types.CircuitSignalID;
-import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.U8;
import java.io.IOException;
@@ -51,7 +56,11 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
/**
* LINC-OE Optical Emulator switch class.
@@ -65,10 +74,13 @@
* 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.
+ *
*/
public class OfOpticalSwitchImplLinc13
- extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
+ extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch, LambdaQuery {
+ private static final int LAMBDA_COUNT = 80;
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
private long barrierXidToWaitFor = -1;
@@ -267,13 +279,13 @@
/**
* Checks if given port is also part of the regular port desc stats, i.e., is the port a tap port.
*
- * @param port given OF port
+ * @param port given port number
* @return true if the port is a tap (OCh), false otherwise (OMS port)
*/
- private boolean hasPort(OFPort port) {
+ private boolean isOChPort(long port) {
for (OFPortDescStatsReply reply : this.ports) {
for (OFPortDesc p : reply.getEntries()) {
- if (p.getPortNo().equals(port)) {
+ if (p.getPortNo().getPortNumber() == port) {
return true;
}
}
@@ -328,7 +340,7 @@
short signalType;
// FIXME: use constants once loxi has full optical extensions
- if (hasPort(p.getPortNo())) {
+ if (isOChPort(p.getPortNo().getPortNumber())) {
signalType = 5; // OCH port
} else {
signalType = 2; // OMS port
@@ -351,4 +363,23 @@
public Set<PortDescPropertyType> getPortTypes() {
return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT);
}
+
+ @Override
+ public SortedSet<OchSignal> queryLambdas(PortNumber port) {
+ // OCh ports don't have lambdas
+ if (isOChPort(port.toLong())) {
+ 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;
+ }
}
diff --git a/drivers/src/main/resources/onos-drivers.xml b/drivers/src/main/resources/onos-drivers.xml
index 6989683..2494e12 100644
--- a/drivers/src/main/resources/onos-drivers.xml
+++ b/drivers/src/main/resources/onos-drivers.xml
@@ -74,6 +74,8 @@
swVersion="LINC-OE OpenFlow Software Switch 1.1">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OfOpticalSwitchImplLinc13"/>
+ <behaviour api="org.onosproject.net.behaviour.LambdaQuery"
+ impl="org.onosproject.driver.handshaker.OfOpticalSwitchImplLinc13"/>
</driver>
<driver name="corsa"
manufacturer="Corsa" hwVersion="Corsa Element" swVersion="2.3.1">
@@ -135,6 +137,8 @@
swVersion="ocs switch">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
+ <behaviour api="org.onosproject.net.behaviour.LambdaQuery"
+ impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
</driver>
<driver name="onosfw" extends="ovs"
manufacturer="" hwVersion="" swVersion="">
diff --git a/utils/misc/src/main/java/org/onlab/util/Spectrum.java b/utils/misc/src/main/java/org/onlab/util/Spectrum.java
index 42d7609..ca01c6e 100644
--- a/utils/misc/src/main/java/org/onlab/util/Spectrum.java
+++ b/utils/misc/src/main/java/org/onlab/util/Spectrum.java
@@ -19,11 +19,12 @@
* Telecom optical wavelength bands: O, E, S, C, L and U bands.
*
* See ITU-T G-Series Recommendations, Supplement 39
+ * See ITU-T G.694.1 for center frequency definition.
*/
public final class Spectrum {
- private Spectrum() {
- }
+ // Center frequency
+ public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1);
// O band (original): 1260 to 1360 nm
public static final Frequency O_BAND_MIN = Frequency.ofTHz(220.436);
@@ -48,4 +49,7 @@
// U band (ultra-long wavelength): 1625 to 1675 nm
public static final Frequency U_BAND_MIN = Frequency.ofTHz(178.981);
public static final Frequency U_BAND_MAX = Frequency.ofTHz(184.488);
+
+ private Spectrum() {
+ }
}