Marc De Leenheer
Committed by Gerrit Code Review

Deprecate IndexedLambda and remove from optical intent compiler.

Allow drivers to report any spectral grid. Bugfixes.

ONOS-3495

Change-Id: Ied946660d48e482c1746d1e87735498b1637bb4b
...@@ -15,11 +15,6 @@ ...@@ -15,11 +15,6 @@
15 */ 15 */
16 package org.onosproject.optical.testapp; 16 package org.onosproject.optical.testapp;
17 17
18 -import static org.slf4j.LoggerFactory.getLogger;
19 -
20 -import java.util.HashMap;
21 -import java.util.Map;
22 -
23 import org.apache.felix.scr.annotations.Activate; 18 import org.apache.felix.scr.annotations.Activate;
24 import org.apache.felix.scr.annotations.Deactivate; 19 import org.apache.felix.scr.annotations.Deactivate;
25 import org.apache.felix.scr.annotations.Reference; 20 import org.apache.felix.scr.annotations.Reference;
...@@ -44,9 +39,17 @@ import org.onosproject.net.flow.criteria.Criteria; ...@@ -44,9 +39,17 @@ import org.onosproject.net.flow.criteria.Criteria;
44 import org.onosproject.net.flow.instructions.Instructions; 39 import org.onosproject.net.flow.instructions.Instructions;
45 import org.slf4j.Logger; 40 import org.slf4j.Logger;
46 41
42 +import java.util.HashMap;
43 +import java.util.Map;
44 +
45 +import static org.slf4j.LoggerFactory.getLogger;
46 +
47 /** 47 /**
48 * Sample reactive forwarding application. 48 * Sample reactive forwarding application.
49 + *
50 + * @deprecated in Emu (ONOS 1.4).
49 */ 51 */
52 +@Deprecated
50 //@Component(immediate = true) 53 //@Component(immediate = true)
51 public class LambdaForwarding { 54 public class LambdaForwarding {
52 55
......
...@@ -25,7 +25,7 @@ public enum ChannelSpacing { ...@@ -25,7 +25,7 @@ public enum ChannelSpacing {
25 CHL_50GHZ(50), // 50 GHz 25 CHL_50GHZ(50), // 50 GHz
26 CHL_25GHZ(25), // 25 GHz 26 CHL_25GHZ(25), // 25 GHz
27 CHL_12P5GHZ(12.5), // 12.5 GHz 27 CHL_12P5GHZ(12.5), // 12.5 GHz
28 - CHL_6P25GHZ(6.5); // 6.25 GHz 28 + CHL_6P25GHZ(6.25); // 6.25 GHz
29 29
30 private final Frequency frequency; 30 private final Frequency frequency;
31 31
......
...@@ -19,7 +19,10 @@ import com.google.common.base.MoreObjects; ...@@ -19,7 +19,10 @@ import com.google.common.base.MoreObjects;
19 19
20 /** 20 /**
21 * Implementation of Lambda simply designated by an index number of wavelength. 21 * Implementation of Lambda simply designated by an index number of wavelength.
22 + *
23 + * @deprecated in Emu (ONOS 1.4).
22 */ 24 */
25 +@Deprecated
23 public class IndexedLambda implements Lambda { 26 public class IndexedLambda implements Lambda {
24 27
25 private final long index; 28 private final long index;
......
...@@ -16,10 +16,18 @@ ...@@ -16,10 +16,18 @@
16 package org.onosproject.net; 16 package org.onosproject.net;
17 17
18 import com.google.common.base.MoreObjects; 18 import com.google.common.base.MoreObjects;
19 +import com.google.common.collect.ImmutableSet;
19 import org.onlab.util.Frequency; 20 import org.onlab.util.Frequency;
20 import org.onlab.util.Spectrum; 21 import org.onlab.util.Spectrum;
21 22
23 +import java.util.List;
22 import java.util.Objects; 24 import java.util.Objects;
25 +import java.util.Set;
26 +import java.util.SortedSet;
27 +import java.util.TreeSet;
28 +import java.util.function.Supplier;
29 +import java.util.stream.Collectors;
30 +import java.util.stream.IntStream;
23 31
24 import static com.google.common.base.Preconditions.checkArgument; 32 import static com.google.common.base.Preconditions.checkArgument;
25 import static com.google.common.base.Preconditions.checkNotNull; 33 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -33,14 +41,13 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -33,14 +41,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
33 */ 41 */
34 public class OchSignal implements Lambda { 42 public class OchSignal implements Lambda {
35 43
36 - public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5); 44 + public static final Set<Integer> FIXED_GRID_SLOT_GRANULARITIES = ImmutableSet.of(1, 2, 4, 8);
37 private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM; 45 private static final GridType DEFAULT_OCH_GRIDTYPE = GridType.DWDM;
38 private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ; 46 private static final ChannelSpacing DEFAULT_CHANNEL_SPACING = ChannelSpacing.CHL_50GHZ;
39 47
40 -
41 private final GridType gridType; 48 private final GridType gridType;
42 private final ChannelSpacing channelSpacing; 49 private final ChannelSpacing channelSpacing;
43 - // Frequency = 193.1 THz + spacingMultiplier * channelSpacing 50 + // Nominal central frequency = 193.1 THz + spacingMultiplier * channelSpacing
44 private final int spacingMultiplier; 51 private final int spacingMultiplier;
45 // Slot width = slotGranularity * 12.5 GHz 52 // Slot width = slotGranularity * 12.5 GHz
46 private final int slotGranularity; 53 private final int slotGranularity;
...@@ -118,9 +125,9 @@ public class OchSignal implements Lambda { ...@@ -118,9 +125,9 @@ public class OchSignal implements Lambda {
118 } 125 }
119 126
120 /** 127 /**
121 - * Returns slow width granularity. 128 + * Returns slot width granularity.
122 * 129 *
123 - * @return slow width granularity 130 + * @return slot width granularity
124 */ 131 */
125 public int slotGranularity() { 132 public int slotGranularity() {
126 return slotGranularity; 133 return slotGranularity;
...@@ -141,7 +148,56 @@ public class OchSignal implements Lambda { ...@@ -141,7 +148,56 @@ public class OchSignal implements Lambda {
141 * @return slot width 148 * @return slot width
142 */ 149 */
143 public Frequency slotWidth() { 150 public Frequency slotWidth() {
144 - return FLEX_GRID_SLOT.multiply(slotGranularity); 151 + return ChannelSpacing.CHL_12P5GHZ.frequency().multiply(slotGranularity);
152 + }
153 +
154 + /**
155 + * Convert fixed grid OCh signal to sorted set of flex grid slots with 6.25 GHz spacing and 12.5 GHz slot width.
156 + *
157 + * @param ochSignal fixed grid lambda
158 + * @return sorted set of flex grid OCh lambdas
159 + */
160 + public static SortedSet<OchSignal> toFlexGrid(OchSignal ochSignal) {
161 + checkArgument(ochSignal.gridType() != GridType.FLEX);
162 + checkArgument(ochSignal.channelSpacing() != ChannelSpacing.CHL_6P25GHZ);
163 + checkArgument(FIXED_GRID_SLOT_GRANULARITIES.contains(ochSignal.slotGranularity()));
164 +
165 + int startMultiplier = (int) (1 - ochSignal.slotGranularity() +
166 + ochSignal.spacingMultiplier() * ochSignal.channelSpacing().frequency().asHz() /
167 + ChannelSpacing.CHL_6P25GHZ.frequency().asHz());
168 +
169 + Supplier<SortedSet<OchSignal>> supplier = () -> new TreeSet<>(new DefaultOchSignalComparator());
170 + return IntStream.range(0, ochSignal.slotGranularity())
171 + .mapToObj(i -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_6P25GHZ, startMultiplier + 2 * i, 1))
172 + .collect(Collectors.toCollection(supplier));
173 + }
174 +
175 + /**
176 + * Convert list of lambdas with flex grid 6.25 GHz spacing and 12.5 GHz width into fixed grid OCh signal.
177 + *
178 + * @param lambdas list of flex grid lambdas in sorted order
179 + * @param spacing desired fixed grid spacing
180 + * @return fixed grid lambda
181 + */
182 + public static OchSignal toFixedGrid(List<OchSignal> lambdas, ChannelSpacing spacing) {
183 + // Number of slots of 12.5 GHz that fit into requested spacing
184 + int ratio = (int) (spacing.frequency().asHz() / ChannelSpacing.CHL_12P5GHZ.frequency().asHz());
185 + checkArgument(lambdas.size() == ratio);
186 + lambdas.forEach(x -> checkArgument(x.gridType() == GridType.FLEX));
187 + lambdas.forEach(x -> checkArgument(x.channelSpacing() == ChannelSpacing.CHL_6P25GHZ));
188 + lambdas.forEach(x -> checkArgument(x.slotGranularity() == 1));
189 + // Consecutive lambdas (multiplier increments by 2 because spacing is 6.25 GHz but slot width is 12.5 GHz)
190 + IntStream.range(1, lambdas.size())
191 + .forEach(i -> checkArgument(
192 + lambdas.get(i).spacingMultiplier() == lambdas.get(i - 1).spacingMultiplier() + 2));
193 + // Is center frequency compatible with requested spacing
194 + Frequency center = lambdas.get(ratio / 2).centralFrequency().subtract(ChannelSpacing.CHL_6P25GHZ.frequency());
195 + checkArgument(Spectrum.CENTER_FREQUENCY.subtract(center).asHz() % spacing.frequency().asHz() == 0);
196 +
197 + // Multiplier sits in middle of given lambdas, then convert from 6.25 to requested spacing
198 + int spacingMultiplier = (lambdas.get(ratio / 2).spacingMultiplier() + 1) / (ratio * 2);
199 +
200 + return new OchSignal(GridType.DWDM, spacing, spacingMultiplier, lambdas.size());
145 } 201 }
146 202
147 @Override 203 @Override
......
...@@ -25,6 +25,7 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -25,6 +25,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
25 /** 25 /**
26 * Implementation of indexed lambda criterion. 26 * Implementation of indexed lambda criterion.
27 */ 27 */
28 +@Deprecated
28 public class IndexedLambdaCriterion implements Criterion { 29 public class IndexedLambdaCriterion implements Criterion {
29 30
30 private final IndexedLambda lambda; 31 private final IndexedLambda lambda;
......
...@@ -26,14 +26,14 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -26,14 +26,14 @@ import org.apache.felix.scr.annotations.Reference;
26 import org.apache.felix.scr.annotations.ReferenceCardinality; 26 import org.apache.felix.scr.annotations.ReferenceCardinality;
27 import org.onlab.util.Frequency; 27 import org.onlab.util.Frequency;
28 import org.onosproject.net.AnnotationKeys; 28 import org.onosproject.net.AnnotationKeys;
29 +import org.onosproject.net.ChannelSpacing;
29 import org.onosproject.net.ConnectPoint; 30 import org.onosproject.net.ConnectPoint;
31 +import org.onosproject.net.DefaultOchSignalComparator;
30 import org.onosproject.net.DeviceId; 32 import org.onosproject.net.DeviceId;
31 -import org.onosproject.net.IndexedLambda;
32 import org.onosproject.net.Link; 33 import org.onosproject.net.Link;
33 import org.onosproject.net.OchPort; 34 import org.onosproject.net.OchPort;
34 import org.onosproject.net.OchSignal; 35 import org.onosproject.net.OchSignal;
35 import org.onosproject.net.OchSignalType; 36 import org.onosproject.net.OchSignalType;
36 -import org.onosproject.net.OmsPort;
37 import org.onosproject.net.Path; 37 import org.onosproject.net.Path;
38 import org.onosproject.net.Port; 38 import org.onosproject.net.Port;
39 import org.onosproject.net.device.DeviceService; 39 import org.onosproject.net.device.DeviceService;
...@@ -53,6 +53,7 @@ import org.onosproject.net.topology.TopologyService; ...@@ -53,6 +53,7 @@ import org.onosproject.net.topology.TopologyService;
53 import org.slf4j.Logger; 53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory; 54 import org.slf4j.LoggerFactory;
55 55
56 +import java.util.ArrayList;
56 import java.util.Collections; 57 import java.util.Collections;
57 import java.util.List; 58 import java.util.List;
58 import java.util.Set; 59 import java.util.Set;
...@@ -64,11 +65,12 @@ import static com.google.common.base.Preconditions.checkArgument; ...@@ -64,11 +65,12 @@ import static com.google.common.base.Preconditions.checkArgument;
64 /** 65 /**
65 * An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}. 66 * An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}.
66 */ 67 */
67 -// For now, remove component designation until dependency on the new resource manager is available.
68 @Component(immediate = true) 68 @Component(immediate = true)
69 public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> { 69 public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
70 70
71 protected static final Logger log = LoggerFactory.getLogger(OpticalConnectivityIntentCompiler.class); 71 protected static final Logger log = LoggerFactory.getLogger(OpticalConnectivityIntentCompiler.class);
72 + // By default, allocate 50 GHz lambdas (4 slots of 12.5 GHz) for each intent.
73 + private static final int SLOT_COUNT = 4;
72 74
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected IntentExtensionService intentManager; 76 protected IntentExtensionService intentManager;
...@@ -133,16 +135,15 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical ...@@ -133,16 +135,15 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
133 srcOchPort.lambda().channelSpacing(), 135 srcOchPort.lambda().channelSpacing(),
134 srcOchPort.lambda().slotGranularity()); 136 srcOchPort.lambda().slotGranularity());
135 } else if (!srcOchPort.isTunable() || !dstOchPort.isTunable()) { 137 } else if (!srcOchPort.isTunable() || !dstOchPort.isTunable()) {
136 - // FIXME: also check OCh port 138 + // FIXME: also check destination OCh port
137 ochSignal = srcOchPort.lambda(); 139 ochSignal = srcOchPort.lambda();
138 } else { 140 } else {
139 // Request and reserve lambda on path 141 // Request and reserve lambda on path
140 - IndexedLambda lambda = assignWavelength(intent, path); 142 + List<OchSignal> lambdas = assignWavelength(intent, path);
141 - if (lambda == null) { 143 + if (lambdas.isEmpty()) {
142 continue; 144 continue;
143 } 145 }
144 - OmsPort omsPort = (OmsPort) deviceService.getPort(path.src().deviceId(), path.src().port()); 146 + ochSignal = OchSignal.toFixedGrid(lambdas, ChannelSpacing.CHL_50GHZ);
145 - ochSignal = new OchSignal((int) lambda.index(), omsPort.maxFrequency(), omsPort.grid());
146 } 147 }
147 148
148 // Create installable optical path intent 149 // Create installable optical path intent
...@@ -174,48 +175,77 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical ...@@ -174,48 +175,77 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
174 * @param path path in WDM topology 175 * @param path path in WDM topology
175 * @return first available lambda allocated 176 * @return first available lambda allocated
176 */ 177 */
177 - private IndexedLambda assignWavelength(Intent intent, Path path) { 178 + private List<OchSignal> assignWavelength(Intent intent, Path path) {
178 - Set<IndexedLambda> lambdas = findCommonLambdasOverLinks(path.links()); 179 + Set<OchSignal> lambdas = findCommonLambdasOverLinks(path.links());
179 if (lambdas.isEmpty()) { 180 if (lambdas.isEmpty()) {
180 - return null; 181 + return Collections.emptyList();
181 } 182 }
182 183
183 - IndexedLambda minLambda = findFirstLambda(lambdas); 184 + List<OchSignal> minLambda = findFirstLambda(lambdas, slotCount());
184 List<ResourcePath> lambdaResources = path.links().stream() 185 List<ResourcePath> lambdaResources = path.links().stream()
185 .flatMap(x -> Stream.of( 186 .flatMap(x -> Stream.of(
186 ResourcePath.discrete(x.src().deviceId(), x.src().port()), 187 ResourcePath.discrete(x.src().deviceId(), x.src().port()),
187 ResourcePath.discrete(x.dst().deviceId(), x.dst().port()) 188 ResourcePath.discrete(x.dst().deviceId(), x.dst().port())
188 )) 189 ))
189 - .map(x -> x.child(minLambda)) 190 + .flatMap(x -> minLambda.stream().map(l -> x.child(l)))
190 .collect(Collectors.toList()); 191 .collect(Collectors.toList());
191 192
192 List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), lambdaResources); 193 List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), lambdaResources);
193 if (allocations.isEmpty()) { 194 if (allocations.isEmpty()) {
194 log.info("Resource allocation for {} failed (resource request: {})", intent, lambdaResources); 195 log.info("Resource allocation for {} failed (resource request: {})", intent, lambdaResources);
195 - return null; 196 + return Collections.emptyList();
196 } 197 }
197 198
198 return minLambda; 199 return minLambda;
199 } 200 }
200 201
201 - private Set<IndexedLambda> findCommonLambdasOverLinks(List<Link> links) { 202 + /**
203 + * Get the number of 12.5 GHz slots required for the path.
204 + *
205 + * For now this returns a constant value of 4 (i.e., fixed grid 50 GHz slot),
206 + * but in the future can depend on optical reach, line rate, transponder port capabilities, etc.
207 + *
208 + * @return number of slots
209 + */
210 + private int slotCount() {
211 + return SLOT_COUNT;
212 + }
213 +
214 + private Set<OchSignal> findCommonLambdasOverLinks(List<Link> links) {
202 return links.stream() 215 return links.stream()
203 .flatMap(x -> Stream.of( 216 .flatMap(x -> Stream.of(
204 ResourcePath.discrete(x.src().deviceId(), x.src().port()), 217 ResourcePath.discrete(x.src().deviceId(), x.src().port()),
205 ResourcePath.discrete(x.dst().deviceId(), x.dst().port()) 218 ResourcePath.discrete(x.dst().deviceId(), x.dst().port())
206 )) 219 ))
207 .map(resourceService::getAvailableResources) 220 .map(resourceService::getAvailableResources)
208 - .map(x -> Iterables.filter(x, r -> r.last() instanceof IndexedLambda)) 221 + .map(x -> Iterables.filter(x, r -> r.last() instanceof OchSignal))
209 - .map(x -> Iterables.transform(x, r -> (IndexedLambda) r.last())) 222 + .map(x -> Iterables.transform(x, r -> (OchSignal) r.last()))
210 - .map(x -> (Set<IndexedLambda>) ImmutableSet.copyOf(x)) 223 + .map(x -> (Set<OchSignal>) ImmutableSet.copyOf(x))
211 .reduce(Sets::intersection) 224 .reduce(Sets::intersection)
212 .orElse(Collections.emptySet()); 225 .orElse(Collections.emptySet());
213 } 226 }
214 227
215 - private IndexedLambda findFirstLambda(Set<IndexedLambda> lambdas) { 228 + /**
216 - return lambdas.stream() 229 + * Returns list of consecutive resources in given set of lambdas.
217 - .findFirst() 230 + *
218 - .get(); 231 + * @param lambdas list of lambdas
232 + * @param count number of consecutive lambdas to return
233 + * @return list of consecutive lambdas
234 + */
235 + private List<OchSignal> findFirstLambda(Set<OchSignal> lambdas, int count) {
236 + // Sort available lambdas
237 + List<OchSignal> lambdaList = new ArrayList<>(lambdas);
238 + lambdaList.sort(new DefaultOchSignalComparator());
239 +
240 + // Look ahead by count and ensure spacing multiplier is as expected (i.e., no gaps)
241 + for (int i = 0; i < lambdaList.size() - count; i++) {
242 + if (lambdaList.get(i).spacingMultiplier() + 2 * count ==
243 + lambdaList.get(i + count).spacingMultiplier()) {
244 + return lambdaList.subList(i, i + count);
245 + }
246 + }
247 +
248 + return Collections.emptyList();
219 } 249 }
220 250
221 private ConnectPoint staticPort(ConnectPoint connectPoint) { 251 private ConnectPoint staticPort(ConnectPoint connectPoint) {
......
...@@ -19,6 +19,7 @@ import com.google.common.collect.Lists; ...@@ -19,6 +19,7 @@ import com.google.common.collect.Lists;
19 import org.onlab.packet.MplsLabel; 19 import org.onlab.packet.MplsLabel;
20 import org.onlab.packet.VlanId; 20 import org.onlab.packet.VlanId;
21 import org.onlab.util.ItemNotFoundException; 21 import org.onlab.util.ItemNotFoundException;
22 +import org.onosproject.net.DefaultOchSignalComparator;
22 import org.onosproject.net.Device; 23 import org.onosproject.net.Device;
23 import org.onosproject.net.DeviceId; 24 import org.onosproject.net.DeviceId;
24 import org.onosproject.net.Port; 25 import org.onosproject.net.Port;
...@@ -44,7 +45,9 @@ import org.slf4j.LoggerFactory; ...@@ -44,7 +45,9 @@ import org.slf4j.LoggerFactory;
44 import java.util.Collections; 45 import java.util.Collections;
45 import java.util.List; 46 import java.util.List;
46 import java.util.SortedSet; 47 import java.util.SortedSet;
48 +import java.util.TreeSet;
47 import java.util.concurrent.ExecutorService; 49 import java.util.concurrent.ExecutorService;
50 +import java.util.function.Supplier;
48 import java.util.stream.Collectors; 51 import java.util.stream.Collectors;
49 import java.util.stream.IntStream; 52 import java.util.stream.IntStream;
50 53
...@@ -199,7 +202,10 @@ final class ResourceDeviceListener implements DeviceListener { ...@@ -199,7 +202,10 @@ final class ResourceDeviceListener implements DeviceListener {
199 } 202 }
200 LambdaQuery query = handler.behaviour(LambdaQuery.class); 203 LambdaQuery query = handler.behaviour(LambdaQuery.class);
201 if (query != null) { 204 if (query != null) {
202 - return query.queryLambdas(port); 205 + Supplier<SortedSet<OchSignal>> supplier = () -> new TreeSet<>(new DefaultOchSignalComparator());
206 + return query.queryLambdas(port).stream()
207 + .flatMap(x -> OchSignal.toFlexGrid(x).stream())
208 + .collect(Collectors.toCollection(supplier));
203 } else { 209 } else {
204 return Collections.emptySortedSet(); 210 return Collections.emptySortedSet();
205 } 211 }
......
...@@ -51,6 +51,7 @@ import java.util.Set; ...@@ -51,6 +51,7 @@ import java.util.Set;
51 import java.util.SortedSet; 51 import java.util.SortedSet;
52 import java.util.TreeSet; 52 import java.util.TreeSet;
53 import java.util.concurrent.atomic.AtomicBoolean; 53 import java.util.concurrent.atomic.AtomicBoolean;
54 +import java.util.function.Supplier;
54 import java.util.stream.Collectors; 55 import java.util.stream.Collectors;
55 import java.util.stream.IntStream; 56 import java.util.stream.IntStream;
56 57
...@@ -209,13 +210,12 @@ public class CalientFiberSwitchHandshaker ...@@ -209,13 +210,12 @@ public class CalientFiberSwitchHandshaker
209 ChannelSpacing.CHL_12P5GHZ.frequency().asHz(); 210 ChannelSpacing.CHL_12P5GHZ.frequency().asHz();
210 long stopSpacingMultiplier = Spectrum.O_BAND_MAX.subtract(Spectrum.CENTER_FREQUENCY).asHz() / 211 long stopSpacingMultiplier = Spectrum.O_BAND_MAX.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
211 ChannelSpacing.CHL_12P5GHZ.frequency().asHz(); 212 ChannelSpacing.CHL_12P5GHZ.frequency().asHz();
212 - List<OchSignal> lambdas = IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier) 213 + Supplier<SortedSet<OchSignal>> supplier = () -> new TreeSet<>(new DefaultOchSignalComparator());
213 - .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x, 1))
214 - .collect(Collectors.toList());
215 214
216 - SortedSet<OchSignal> result = new TreeSet<>(new DefaultOchSignalComparator()); 215 + // Only consider odd values for the multiplier (for easy mapping to fixed grid)
217 - result.addAll(lambdas); 216 + return IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier)
218 - 217 + .filter(i -> i % 2 == 1)
219 - return result; 218 + .mapToObj(i -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_6P25GHZ, i, 1))
219 + .collect(Collectors.toCollection(supplier));
220 } 220 }
221 } 221 }
......
...@@ -59,6 +59,7 @@ import java.util.Set; ...@@ -59,6 +59,7 @@ import java.util.Set;
59 import java.util.SortedSet; 59 import java.util.SortedSet;
60 import java.util.TreeSet; 60 import java.util.TreeSet;
61 import java.util.concurrent.atomic.AtomicBoolean; 61 import java.util.concurrent.atomic.AtomicBoolean;
62 +import java.util.function.Supplier;
62 import java.util.stream.Collectors; 63 import java.util.stream.Collectors;
63 import java.util.stream.IntStream; 64 import java.util.stream.IntStream;
64 65
...@@ -74,7 +75,7 @@ import java.util.stream.IntStream; ...@@ -74,7 +75,7 @@ import java.util.stream.IntStream;
74 * As LINC implements custom OF optical extensions (in contrast to the final standard as specified in 75 * As LINC implements custom OF optical extensions (in contrast to the final standard as specified in
75 * ONF TS-022 (March 15, 2015), we need to rewrite flow stat requests and flow mods in {@link #sendMsg(OFMessage)}. 76 * ONF TS-022 (March 15, 2015), we need to rewrite flow stat requests and flow mods in {@link #sendMsg(OFMessage)}.
76 * 77 *
77 - * LINC exposes OchSignal resources: 80 lambdas of 50 GHz around ITU-T G.694.1 center frequency 193.1 GHz. 78 + * LINC exposes OchSignal resources: 80 lambdas of 50 GHz (fixed grid) around ITU-T G.694.1 center frequency 193.1 GHz.
78 * 79 *
79 */ 80 */
80 public class OfOpticalSwitchImplLinc13 81 public class OfOpticalSwitchImplLinc13
...@@ -224,8 +225,9 @@ public class OfOpticalSwitchImplLinc13 ...@@ -224,8 +225,9 @@ public class OfOpticalSwitchImplLinc13
224 } 225 }
225 226
226 OFActionSetField sf = (OFActionSetField) action; 227 OFActionSetField sf = (OFActionSetField) action;
227 - if (!(sf instanceof OFOxmExpOchSigId)) { 228 + if (!(sf.getField() instanceof OFOxmExpOchSigId)) {
228 newActions.add(action); 229 newActions.add(action);
230 + continue;
229 } 231 }
230 232
231 OFOxmExpOchSigId oxm = (OFOxmExpOchSigId) sf.getField(); 233 OFOxmExpOchSigId oxm = (OFOxmExpOchSigId) sf.getField();
...@@ -259,7 +261,6 @@ public class OfOpticalSwitchImplLinc13 ...@@ -259,7 +261,6 @@ public class OfOpticalSwitchImplLinc13
259 OFFlowMod fm = (OFFlowMod) msg; 261 OFFlowMod fm = (OFFlowMod) msg;
260 newMatch = rewriteMatch(fm.getMatch()); 262 newMatch = rewriteMatch(fm.getMatch());
261 List<OFAction> actions = rewriteActions(fm.getActions()); 263 List<OFAction> actions = rewriteActions(fm.getActions());
262 -
263 newMsg = fm.createBuilder().setMatch(newMatch).setActions(actions).build(); 264 newMsg = fm.createBuilder().setMatch(newMatch).setActions(actions).build();
264 } 265 }
265 266
...@@ -371,15 +372,10 @@ public class OfOpticalSwitchImplLinc13 ...@@ -371,15 +372,10 @@ public class OfOpticalSwitchImplLinc13
371 return Collections.emptySortedSet(); 372 return Collections.emptySortedSet();
372 } 373 }
373 374
374 - // OMS ports expose 80 lambdas of 50GHz width, centered around the ITU-T center frequency. 375 + // OMS ports expose 80 fixed grid lambdas of 50GHz width, centered around the ITU-T center frequency 193.1 THz.
375 - // We report these with a spacing of 12.5 GHz. 376 + Supplier<SortedSet<OchSignal>> supplier = () -> new TreeSet<>(new DefaultOchSignalComparator());
376 - List<OchSignal> lambdas = IntStream.range(0, LAMBDA_COUNT) 377 + return IntStream.range(0, LAMBDA_COUNT)
377 - .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x - (LAMBDA_COUNT / 2), 1)) 378 + .mapToObj(x -> new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, x - (LAMBDA_COUNT / 2), 4))
378 - .collect(Collectors.toList()); 379 + .collect(Collectors.toCollection(supplier));
379 -
380 - SortedSet<OchSignal> result = new TreeSet<>(new DefaultOchSignalComparator());
381 - result.addAll(lambdas);
382 -
383 - return result;
384 } 380 }
385 } 381 }
......
...@@ -536,7 +536,9 @@ class LINCSwitch(OpticalSwitch): ...@@ -536,7 +536,9 @@ class LINCSwitch(OpticalSwitch):
536 for link in LINCSwitch.opticalJSON[ 'links' ]: 536 for link in LINCSwitch.opticalJSON[ 'links' ]:
537 linkDict = {} 537 linkDict = {}
538 linkDict[ 'type' ] = link[ 'type' ] 538 linkDict[ 'type' ] = link[ 'type' ]
539 - linkDict.update(link[ 'annotations' ]) 539 + # FIXME: Clean up unnecessary link/device attributes, then re-enable annotations
540 + linkDict['durable'] = True
541 + # linkDict.update(link[ 'annotations' ])
540 542
541 linkSubj = link[ 'src' ] + '-' + link[ 'dst' ] 543 linkSubj = link[ 'src' ] + '-' + link[ 'dst' ]
542 links[ linkSubj ] = { 'basic': linkDict } 544 links[ linkSubj ] = { 'basic': linkDict }
......