Marc De Leenheer

Implementation of lambda query behaviour for LINC and Calient drivers.

ONOS-3431

Change-Id: I03b7e7c9d2b0ba7e55d09745cfc6ceb57cc6eb5e
/*
* 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();
}
}
......@@ -17,6 +17,7 @@ package org.onosproject.net;
import com.google.common.base.MoreObjects;
import org.onlab.util.Frequency;
import org.onlab.util.Spectrum;
import java.util.Objects;
......@@ -32,7 +33,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
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 @@ public class OchSignal implements Lambda {
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 @@ public class OchSignal implements Lambda {
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 @@ public class OchSignal implements Lambda {
* @return frequency in MHz
*/
public Frequency centralFrequency() {
return CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier));
return Spectrum.CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier));
}
/**
......
......@@ -17,7 +17,14 @@ package org.onosproject.driver.handshaker;
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.io.IOException;
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 @@ public class CalientFiberSwitchHandshaker extends AbstractOpenFlowSwitch impleme
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;
}
}
......
......@@ -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.Match;
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.Collections;
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 @@ import java.util.concurrent.atomic.AtomicBoolean;
* 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 @@ public class OfOpticalSwitchImplLinc13
/**
* 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 @@ public class OfOpticalSwitchImplLinc13
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 class OfOpticalSwitchImplLinc13
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;
}
}
......
......@@ -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="">
......
......@@ -19,11 +19,12 @@ package org.onlab.util;
* 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 @@ public final class Spectrum {
// 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() {
}
}
......