Marc De Leenheer

Implementation of lambda query behaviour for LINC and Calient drivers.

ONOS-3431

Change-Id: I03b7e7c9d2b0ba7e55d09745cfc6ceb57cc6eb5e
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.net;
17 +
18 +import java.util.Comparator;
19 +
20 +import static com.google.common.base.Preconditions.checkArgument;
21 +import static com.google.common.base.Preconditions.checkNotNull;
22 +
23 +/**
24 + * Comparator implementation for OchSignal. Assumes identical grid type and channel spacing.
25 + */
26 +public class DefaultOchSignalComparator implements Comparator<OchSignal> {
27 + @Override
28 + public int compare(OchSignal o1, OchSignal o2) {
29 + checkNotNull(o1.gridType());
30 + checkNotNull(o1.channelSpacing());
31 +
32 + checkArgument(o1.gridType().equals(o2.gridType()));
33 + checkArgument(o1.channelSpacing().equals(o2.channelSpacing()));
34 +
35 + return o1.spacingMultiplier() * o1.slotGranularity() - o2.spacingMultiplier() * o2.slotGranularity();
36 + }
37 +}
...@@ -17,6 +17,7 @@ package org.onosproject.net; ...@@ -17,6 +17,7 @@ package org.onosproject.net;
17 17
18 import com.google.common.base.MoreObjects; 18 import com.google.common.base.MoreObjects;
19 import org.onlab.util.Frequency; 19 import org.onlab.util.Frequency;
20 +import org.onlab.util.Spectrum;
20 21
21 import java.util.Objects; 22 import java.util.Objects;
22 23
...@@ -32,7 +33,6 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -32,7 +33,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
32 */ 33 */
33 public class OchSignal implements Lambda { 34 public class OchSignal implements Lambda {
34 35
35 - public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1);
36 public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5); 36 public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5);
37 private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM; 37 private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM;
38 private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ; 38 private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
...@@ -78,7 +78,7 @@ public class OchSignal implements Lambda { ...@@ -78,7 +78,7 @@ public class OchSignal implements Lambda {
78 78
79 this.gridType = DEFAULT_OCH_GRIDTYPE; 79 this.gridType = DEFAULT_OCH_GRIDTYPE;
80 this.channelSpacing = DEFAULT_CHANNEL_SPACING; 80 this.channelSpacing = DEFAULT_CHANNEL_SPACING;
81 - this.spacingMultiplier = (int) (centerFrequency.subtract(OchSignal.CENTER_FREQUENCY).asHz() / grid.asHz()); 81 + this.spacingMultiplier = (int) (centerFrequency.subtract(Spectrum.CENTER_FREQUENCY).asHz() / grid.asHz());
82 this.slotGranularity = (int) Math.round((double) grid.asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz()); 82 this.slotGranularity = (int) Math.round((double) grid.asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz());
83 } 83 }
84 84
...@@ -86,7 +86,7 @@ public class OchSignal implements Lambda { ...@@ -86,7 +86,7 @@ public class OchSignal implements Lambda {
86 this.gridType = DEFAULT_OCH_GRIDTYPE; 86 this.gridType = DEFAULT_OCH_GRIDTYPE;
87 this.channelSpacing = channelSpacing; 87 this.channelSpacing = channelSpacing;
88 this.spacingMultiplier = (int) Math.round((double) centerFrequency. 88 this.spacingMultiplier = (int) Math.round((double) centerFrequency.
89 - subtract(OchSignal.CENTER_FREQUENCY).asHz() / channelSpacing().frequency().asHz()); 89 + subtract(Spectrum.CENTER_FREQUENCY).asHz() / channelSpacing().frequency().asHz());
90 this.slotGranularity = slotGranularity; 90 this.slotGranularity = slotGranularity;
91 } 91 }
92 92
...@@ -132,7 +132,7 @@ public class OchSignal implements Lambda { ...@@ -132,7 +132,7 @@ public class OchSignal implements Lambda {
132 * @return frequency in MHz 132 * @return frequency in MHz
133 */ 133 */
134 public Frequency centralFrequency() { 134 public Frequency centralFrequency() {
135 - return CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier)); 135 + return Spectrum.CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier));
136 } 136 }
137 137
138 /** 138 /**
......
...@@ -17,7 +17,14 @@ package org.onosproject.driver.handshaker; ...@@ -17,7 +17,14 @@ package org.onosproject.driver.handshaker;
17 17
18 import com.google.common.collect.ImmutableList; 18 import com.google.common.collect.ImmutableList;
19 import com.google.common.collect.ImmutableSet; 19 import com.google.common.collect.ImmutableSet;
20 +import org.onlab.util.Spectrum;
21 +import org.onosproject.net.ChannelSpacing;
22 +import org.onosproject.net.DefaultOchSignalComparator;
20 import org.onosproject.net.Device; 23 import org.onosproject.net.Device;
24 +import org.onosproject.net.GridType;
25 +import org.onosproject.net.OchSignal;
26 +import org.onosproject.net.PortNumber;
27 +import org.onosproject.net.behaviour.LambdaQuery;
21 import org.onosproject.openflow.controller.OpenFlowOpticalSwitch; 28 import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
22 import org.onosproject.openflow.controller.PortDescPropertyType; 29 import org.onosproject.openflow.controller.PortDescPropertyType;
23 import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch; 30 import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
...@@ -41,9 +48,24 @@ import java.io.IOException; ...@@ -41,9 +48,24 @@ import java.io.IOException;
41 import java.util.ArrayList; 48 import java.util.ArrayList;
42 import java.util.List; 49 import java.util.List;
43 import java.util.Set; 50 import java.util.Set;
51 +import java.util.SortedSet;
52 +import java.util.TreeSet;
44 import java.util.concurrent.atomic.AtomicBoolean; 53 import java.util.concurrent.atomic.AtomicBoolean;
54 +import java.util.stream.Collectors;
55 +import java.util.stream.IntStream;
45 56
46 -public class CalientFiberSwitchHandshaker extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch { 57 +/**
58 + * Driver for Calient S160 Optical Circuit Switch. Untested on Calient S320 but probably works ok.
59 + *
60 + * Driver implements custom handshaker, and rewrites flow stats as expected by the device. Port stats are currently
61 + * not supported.
62 + *
63 + * The device consists of OMS ports only, and each port exposes lambda resources covering the whole
64 + * usable optical spectrum (U to O band, see {@link Spectrum} for spectrum definitions).
65 + */
66 +public class CalientFiberSwitchHandshaker
67 + extends AbstractOpenFlowSwitch
68 + implements OpenFlowOpticalSwitch, LambdaQuery {
47 69
48 private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false); 70 private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
49 private List<OFCalientPortDescStatsEntry> fiberPorts = new ArrayList<>(); 71 private List<OFCalientPortDescStatsEntry> fiberPorts = new ArrayList<>();
...@@ -178,4 +200,22 @@ public class CalientFiberSwitchHandshaker extends AbstractOpenFlowSwitch impleme ...@@ -178,4 +200,22 @@ public class CalientFiberSwitchHandshaker extends AbstractOpenFlowSwitch impleme
178 200
179 super.sendMsg(newMsg); 201 super.sendMsg(newMsg);
180 } 202 }
203 +
204 + @Override
205 + public SortedSet<OchSignal> queryLambdas(PortNumber port) {
206 + // S160 data sheet
207 + // Wavelength range: 1260 - 1630 nm
208 + long startSpacingMultiplier = Spectrum.U_BAND_MIN.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
209 + ChannelSpacing.CHL_12P5GHZ.frequency().asHz();
210 + long stopSpacingMultiplier = Spectrum.O_BAND_MAX.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
211 + ChannelSpacing.CHL_12P5GHZ.frequency().asHz();
212 + List<OchSignal> lambdas = IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier)
213 + .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x, 1))
214 + .collect(Collectors.toList());
215 +
216 + SortedSet<OchSignal> result = new TreeSet<>(new DefaultOchSignalComparator());
217 + result.addAll(lambdas);
218 +
219 + return result;
220 + }
181 } 221 }
......
...@@ -16,7 +16,13 @@ ...@@ -16,7 +16,13 @@
16 package org.onosproject.driver.handshaker; 16 package org.onosproject.driver.handshaker;
17 17
18 import com.google.common.collect.ImmutableSet; 18 import com.google.common.collect.ImmutableSet;
19 +import org.onosproject.net.ChannelSpacing;
20 +import org.onosproject.net.DefaultOchSignalComparator;
19 import org.onosproject.net.Device; 21 import org.onosproject.net.Device;
22 +import org.onosproject.net.GridType;
23 +import org.onosproject.net.OchSignal;
24 +import org.onosproject.net.PortNumber;
25 +import org.onosproject.net.behaviour.LambdaQuery;
20 import org.onosproject.openflow.controller.OpenFlowOpticalSwitch; 26 import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
21 import org.onosproject.openflow.controller.PortDescPropertyType; 27 import org.onosproject.openflow.controller.PortDescPropertyType;
22 import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch; 28 import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
...@@ -42,7 +48,6 @@ import org.projectfloodlight.openflow.protocol.match.Match; ...@@ -42,7 +48,6 @@ import org.projectfloodlight.openflow.protocol.match.Match;
42 import org.projectfloodlight.openflow.protocol.match.MatchField; 48 import org.projectfloodlight.openflow.protocol.match.MatchField;
43 import org.projectfloodlight.openflow.protocol.oxm.OFOxmExpOchSigId; 49 import org.projectfloodlight.openflow.protocol.oxm.OFOxmExpOchSigId;
44 import org.projectfloodlight.openflow.types.CircuitSignalID; 50 import org.projectfloodlight.openflow.types.CircuitSignalID;
45 -import org.projectfloodlight.openflow.types.OFPort;
46 import org.projectfloodlight.openflow.types.U8; 51 import org.projectfloodlight.openflow.types.U8;
47 52
48 import java.io.IOException; 53 import java.io.IOException;
...@@ -51,7 +56,11 @@ import java.util.Collections; ...@@ -51,7 +56,11 @@ import java.util.Collections;
51 import java.util.LinkedList; 56 import java.util.LinkedList;
52 import java.util.List; 57 import java.util.List;
53 import java.util.Set; 58 import java.util.Set;
59 +import java.util.SortedSet;
60 +import java.util.TreeSet;
54 import java.util.concurrent.atomic.AtomicBoolean; 61 import java.util.concurrent.atomic.AtomicBoolean;
62 +import java.util.stream.Collectors;
63 +import java.util.stream.IntStream;
55 64
56 /** 65 /**
57 * LINC-OE Optical Emulator switch class. 66 * LINC-OE Optical Emulator switch class.
...@@ -65,10 +74,13 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -65,10 +74,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
65 * As LINC implements custom OF optical extensions (in contrast to the final standard as specified in 74 * As LINC implements custom OF optical extensions (in contrast to the final standard as specified in
66 * ONF TS-022 (March 15, 2015), we need to rewrite flow stat requests and flow mods in {@link #sendMsg(OFMessage)}. 75 * ONF TS-022 (March 15, 2015), we need to rewrite flow stat requests and flow mods in {@link #sendMsg(OFMessage)}.
67 * 76 *
77 + * LINC exposes OchSignal resources: 80 lambdas of 50 GHz around ITU-T G.694.1 center frequency 193.1 GHz.
78 + *
68 */ 79 */
69 public class OfOpticalSwitchImplLinc13 80 public class OfOpticalSwitchImplLinc13
70 - extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch { 81 + extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch, LambdaQuery {
71 82
83 + private static final int LAMBDA_COUNT = 80;
72 private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false); 84 private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
73 private long barrierXidToWaitFor = -1; 85 private long barrierXidToWaitFor = -1;
74 86
...@@ -267,13 +279,13 @@ public class OfOpticalSwitchImplLinc13 ...@@ -267,13 +279,13 @@ public class OfOpticalSwitchImplLinc13
267 /** 279 /**
268 * Checks if given port is also part of the regular port desc stats, i.e., is the port a tap port. 280 * Checks if given port is also part of the regular port desc stats, i.e., is the port a tap port.
269 * 281 *
270 - * @param port given OF port 282 + * @param port given port number
271 * @return true if the port is a tap (OCh), false otherwise (OMS port) 283 * @return true if the port is a tap (OCh), false otherwise (OMS port)
272 */ 284 */
273 - private boolean hasPort(OFPort port) { 285 + private boolean isOChPort(long port) {
274 for (OFPortDescStatsReply reply : this.ports) { 286 for (OFPortDescStatsReply reply : this.ports) {
275 for (OFPortDesc p : reply.getEntries()) { 287 for (OFPortDesc p : reply.getEntries()) {
276 - if (p.getPortNo().equals(port)) { 288 + if (p.getPortNo().getPortNumber() == port) {
277 return true; 289 return true;
278 } 290 }
279 } 291 }
...@@ -328,7 +340,7 @@ public class OfOpticalSwitchImplLinc13 ...@@ -328,7 +340,7 @@ public class OfOpticalSwitchImplLinc13
328 short signalType; 340 short signalType;
329 341
330 // FIXME: use constants once loxi has full optical extensions 342 // FIXME: use constants once loxi has full optical extensions
331 - if (hasPort(p.getPortNo())) { 343 + if (isOChPort(p.getPortNo().getPortNumber())) {
332 signalType = 5; // OCH port 344 signalType = 5; // OCH port
333 } else { 345 } else {
334 signalType = 2; // OMS port 346 signalType = 2; // OMS port
...@@ -351,4 +363,23 @@ public class OfOpticalSwitchImplLinc13 ...@@ -351,4 +363,23 @@ public class OfOpticalSwitchImplLinc13
351 public Set<PortDescPropertyType> getPortTypes() { 363 public Set<PortDescPropertyType> getPortTypes() {
352 return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT); 364 return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT);
353 } 365 }
366 +
367 + @Override
368 + public SortedSet<OchSignal> queryLambdas(PortNumber port) {
369 + // OCh ports don't have lambdas
370 + if (isOChPort(port.toLong())) {
371 + return Collections.emptySortedSet();
372 + }
373 +
374 + // OMS ports expose 80 lambdas of 50GHz width, centered around the ITU-T center frequency.
375 + // We report these with a spacing of 12.5 GHz.
376 + List<OchSignal> lambdas = IntStream.range(0, LAMBDA_COUNT)
377 + .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x - (LAMBDA_COUNT / 2), 1))
378 + .collect(Collectors.toList());
379 +
380 + SortedSet<OchSignal> result = new TreeSet<>(new DefaultOchSignalComparator());
381 + result.addAll(lambdas);
382 +
383 + return result;
384 + }
354 } 385 }
......
...@@ -74,6 +74,8 @@ ...@@ -74,6 +74,8 @@
74 swVersion="LINC-OE OpenFlow Software Switch 1.1"> 74 swVersion="LINC-OE OpenFlow Software Switch 1.1">
75 <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" 75 <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
76 impl="org.onosproject.driver.handshaker.OfOpticalSwitchImplLinc13"/> 76 impl="org.onosproject.driver.handshaker.OfOpticalSwitchImplLinc13"/>
77 + <behaviour api="org.onosproject.net.behaviour.LambdaQuery"
78 + impl="org.onosproject.driver.handshaker.OfOpticalSwitchImplLinc13"/>
77 </driver> 79 </driver>
78 <driver name="corsa" 80 <driver name="corsa"
79 manufacturer="Corsa" hwVersion="Corsa Element" swVersion="2.3.1"> 81 manufacturer="Corsa" hwVersion="Corsa Element" swVersion="2.3.1">
...@@ -135,6 +137,8 @@ ...@@ -135,6 +137,8 @@
135 swVersion="ocs switch"> 137 swVersion="ocs switch">
136 <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" 138 <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
137 impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/> 139 impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
140 + <behaviour api="org.onosproject.net.behaviour.LambdaQuery"
141 + impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
138 </driver> 142 </driver>
139 <driver name="onosfw" extends="ovs" 143 <driver name="onosfw" extends="ovs"
140 manufacturer="" hwVersion="" swVersion=""> 144 manufacturer="" hwVersion="" swVersion="">
......
...@@ -19,11 +19,12 @@ package org.onlab.util; ...@@ -19,11 +19,12 @@ package org.onlab.util;
19 * Telecom optical wavelength bands: O, E, S, C, L and U bands. 19 * Telecom optical wavelength bands: O, E, S, C, L and U bands.
20 * 20 *
21 * See ITU-T G-Series Recommendations, Supplement 39 21 * See ITU-T G-Series Recommendations, Supplement 39
22 + * See ITU-T G.694.1 for center frequency definition.
22 */ 23 */
23 public final class Spectrum { 24 public final class Spectrum {
24 25
25 - private Spectrum() { 26 + // Center frequency
26 - } 27 + public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1);
27 28
28 // O band (original): 1260 to 1360 nm 29 // O band (original): 1260 to 1360 nm
29 public static final Frequency O_BAND_MIN = Frequency.ofTHz(220.436); 30 public static final Frequency O_BAND_MIN = Frequency.ofTHz(220.436);
...@@ -48,4 +49,7 @@ public final class Spectrum { ...@@ -48,4 +49,7 @@ public final class Spectrum {
48 // U band (ultra-long wavelength): 1625 to 1675 nm 49 // U band (ultra-long wavelength): 1625 to 1675 nm
49 public static final Frequency U_BAND_MIN = Frequency.ofTHz(178.981); 50 public static final Frequency U_BAND_MIN = Frequency.ofTHz(178.981);
50 public static final Frequency U_BAND_MAX = Frequency.ofTHz(184.488); 51 public static final Frequency U_BAND_MAX = Frequency.ofTHz(184.488);
52 +
53 + private Spectrum() {
54 + }
51 } 55 }
......