blob: 2c6407f147e77048f24db785c7741364804b9162 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.optical;
weibitf32383b2014-10-22 10:17:31 -070017
weibitf32383b2014-10-22 10:17:31 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
Marc De Leenheer16f857b2015-05-05 20:50:24 -070020import org.apache.felix.scr.annotations.Deactivate;
weibitf32383b2014-10-22 10:17:31 -070021import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -080023import org.onosproject.cluster.ClusterService;
24import org.onosproject.cluster.NodeId;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -080027import org.onosproject.mastership.MastershipService;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.net.ConnectPoint;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070029import org.onosproject.net.Device;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.Host;
31import org.onosproject.net.Link;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070032import org.onosproject.net.OchPort;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070033import org.onosproject.net.OduCltPort;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070034import org.onosproject.net.OduSignalType;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.Path;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070036import org.onosproject.net.Port;
37import org.onosproject.net.device.DeviceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.host.HostService;
39import org.onosproject.net.intent.HostToHostIntent;
40import org.onosproject.net.intent.Intent;
41import org.onosproject.net.intent.IntentEvent;
42import org.onosproject.net.intent.IntentListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.net.intent.IntentService;
44import org.onosproject.net.intent.IntentState;
Marc De Leenheer8c2caac2015-05-28 16:37:33 -070045import org.onosproject.net.intent.OpticalCircuitIntent;
Brian O'Connorabafb502014-12-02 22:26:20 -080046import org.onosproject.net.intent.OpticalConnectivityIntent;
47import org.onosproject.net.intent.PointToPointIntent;
Sho SHIMIZU5c16df82015-09-29 12:52:07 -070048import org.onosproject.net.newresource.ResourceService;
Sho SHIMIZUa6426cb2015-10-01 15:46:48 -070049import org.onosproject.net.resource.device.DeviceResourceStore;
Ayaka Koshibebcb02372015-06-01 10:56:42 -070050import org.onosproject.net.resource.link.LinkResourceAllocations;
Brian O'Connor6de2e202015-05-21 14:30:41 -070051import org.onosproject.net.resource.link.LinkResourceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.net.topology.LinkWeight;
53import org.onosproject.net.topology.PathService;
54import org.onosproject.net.topology.TopologyEdge;
weibitf32383b2014-10-22 10:17:31 -070055import org.slf4j.Logger;
56import org.slf4j.LoggerFactory;
57
Marc De Leenheer16f857b2015-05-05 20:50:24 -070058import java.util.Collections;
Brian O'Connor772852a2014-11-17 15:51:19 -080059import java.util.Iterator;
Marc De Leenheer16f857b2015-05-05 20:50:24 -070060import java.util.LinkedList;
Brian O'Connor772852a2014-11-17 15:51:19 -080061import java.util.List;
62import java.util.Set;
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -080063
Marc De Leenheer16f857b2015-05-05 20:50:24 -070064import static com.google.common.base.Preconditions.checkArgument;
Marc De Leenheer16f857b2015-05-05 20:50:24 -070065import static com.google.common.base.Preconditions.checkNotNull;
66
weibitf32383b2014-10-22 10:17:31 -070067/**
Marc De Leenheer16f857b2015-05-05 20:50:24 -070068 * OpticalPathProvisioner listens for event notifications from the Intent F/W.
weibitf32383b2014-10-22 10:17:31 -070069 * It generates one or more opticalConnectivityIntent(s) and submits (or withdraws) to Intent F/W
70 * for adding/releasing capacity at the packet layer.
weibitf32383b2014-10-22 10:17:31 -070071 */
72
73@Component(immediate = true)
74public class OpticalPathProvisioner {
75
76 protected static final Logger log = LoggerFactory
77 .getLogger(OpticalPathProvisioner.class);
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 private IntentService intentService;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Brian O'Connor772852a2014-11-17 15:51:19 -080083 protected PathService pathService;
weibitf32383b2014-10-22 10:17:31 -070084
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected CoreService coreService;
87
weibit7e583462014-10-23 10:14:05 -070088 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Praseed Balakrishnanc0029652014-11-14 13:38:49 -080089 protected HostService hostService;
90
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -080091 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected MastershipService mastershipService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected ClusterService clusterService;
96
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070097 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Marc De Leenheer1afa2a02015-05-13 09:18:07 -070098 protected DeviceService deviceService;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sho SHIMIZUa6426cb2015-10-01 15:46:48 -0700101 protected DeviceResourceStore deviceResourceStore;
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected LinkResourceService linkResourceService;
105
Sho SHIMIZU5c16df82015-09-29 12:52:07 -0700106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected ResourceService resourceService;
108
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700109 private ApplicationId appId;
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800110
weibitf32383b2014-10-22 10:17:31 -0700111 private final InternalOpticalPathProvisioner pathProvisioner = new InternalOpticalPathProvisioner();
112
113 @Activate
114 protected void activate() {
115 intentService.addListener(pathProvisioner);
Brian O'Connorabafb502014-12-02 22:26:20 -0800116 appId = coreService.registerApplication("org.onosproject.optical");
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700117 initOpticalPorts();
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700118 log.info("Started");
119 }
120
121 @Deactivate
122 protected void deactivate() {
123 intentService.removeListener(pathProvisioner);
124 log.info("Stopped");
weibitf32383b2014-10-22 10:17:31 -0700125 }
126
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700127 /**
128 * Initialize availability of optical ports.
129 */
130 private void initOpticalPorts() {
131 // TODO: check for existing optical intents
132 return;
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800133 }
134
weibitf32383b2014-10-22 10:17:31 -0700135 public class InternalOpticalPathProvisioner implements IntentListener {
136 @Override
137 public void event(IntentEvent event) {
138 switch (event.type()) {
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800139 case INSTALL_REQ:
weibitf32383b2014-10-22 10:17:31 -0700140 break;
141 case INSTALLED:
142 break;
143 case FAILED:
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700144 log.info("Intent {} failed, calling optical path provisioning app.", event.subject());
Brian O'Connor772852a2014-11-17 15:51:19 -0800145 setupLightpath(event.subject());
weibitf32383b2014-10-22 10:17:31 -0700146 break;
147 case WITHDRAWN:
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700148 log.info("Intent {} withdrawn.", event.subject());
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700149 releaseResources(event.subject());
weibitf32383b2014-10-22 10:17:31 -0700150 break;
151 default:
152 break;
153 }
154 }
155
Brian O'Connor772852a2014-11-17 15:51:19 -0800156 private void setupLightpath(Intent intent) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700157 checkNotNull(intent);
158
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800159 // TODO change the coordination approach between packet intents and optical intents
160 // Low speed LLDP may cause multiple calls which are not expected
161
Sho SHIMIZU0a9c9c42015-07-01 15:29:16 -0700162 if (intentService.getIntentState(intent.key()) != IntentState.FAILED) {
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800163 return;
Marc De Leenheerb473b9d2015-02-06 15:21:03 -0800164 }
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800165
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700166 // Get source and destination based on intent type
167 ConnectPoint src;
168 ConnectPoint dst;
Brian O'Connor772852a2014-11-17 15:51:19 -0800169 if (intent instanceof HostToHostIntent) {
170 HostToHostIntent hostToHostIntent = (HostToHostIntent) intent;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800171
Brian O'Connor772852a2014-11-17 15:51:19 -0800172 Host one = hostService.getHost(hostToHostIntent.one());
173 Host two = hostService.getHost(hostToHostIntent.two());
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800174
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700175 checkNotNull(one);
176 checkNotNull(two);
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800177
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700178 src = one.location();
179 dst = two.location();
Brian O'Connor772852a2014-11-17 15:51:19 -0800180 } else if (intent instanceof PointToPointIntent) {
181 PointToPointIntent p2pIntent = (PointToPointIntent) intent;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800182
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700183 src = p2pIntent.ingressPoint();
184 dst = p2pIntent.egressPoint();
Brian O'Connor772852a2014-11-17 15:51:19 -0800185 } else {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700186 return;
Brian O'Connor772852a2014-11-17 15:51:19 -0800187 }
Praseed Balakrishnanc0029652014-11-14 13:38:49 -0800188
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700189 if (src == null || dst == null) {
190 return;
191 }
192
193 // Ignore if we're not the master for the intent's origin device
194 NodeId localNode = clusterService.getLocalNode().id();
195 NodeId sourceMaster = mastershipService.getMasterFor(src.deviceId());
196 if (!localNode.equals(sourceMaster)) {
197 return;
198 }
199
200 // Generate optical connectivity intents
Sho SHIMIZUfb446fe2015-05-21 14:45:23 -0700201 List<Intent> intents = getOpticalIntents(src, dst);
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700202
203 // Submit the intents
Brian O'Connor772852a2014-11-17 15:51:19 -0800204 for (Intent i : intents) {
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700205 intentService.submit(i);
Sho SHIMIZUb5d38412015-05-21 11:12:58 -0700206 log.debug("Submitted an intent: {}", i);
Brian O'Connor772852a2014-11-17 15:51:19 -0800207 }
weibit7e583462014-10-23 10:14:05 -0700208 }
209
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700210 /**
211 * Returns list of cross connection points of missing optical path sections.
212 *
213 * Scans the given multi-layer path and looks for sections that use cross connect links.
214 * The ingress and egress points in the optical layer are returned in a list.
215 *
216 * @param path the multi-layer path
217 * @return list of cross connection points on the optical layer
218 */
219 private List<ConnectPoint> getCrossConnectPoints(Path path) {
220 boolean scanning = false;
Sho SHIMIZU819ee292015-07-01 09:36:21 -0700221 List<ConnectPoint> connectPoints = new LinkedList<>();
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700222
223 for (Link link : path.links()) {
224 if (!isCrossConnectLink(link)) {
225 continue;
226 }
227
228 if (scanning) {
229 connectPoints.add(checkNotNull(link.src()));
230 scanning = false;
231 } else {
232 connectPoints.add(checkNotNull(link.dst()));
233 scanning = true;
234 }
235 }
236
237 return connectPoints;
238 }
239
240 /**
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700241 * Checks if cross connect points are of same type.
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700242 *
243 * @param crossConnectPoints list of cross connection points
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700244 * @return true if cross connect point pairs are of same type, false otherwise
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700245 */
246 private boolean checkCrossConnectPoints(List<ConnectPoint> crossConnectPoints) {
247 checkArgument(crossConnectPoints.size() % 2 == 0);
248
249 Iterator<ConnectPoint> itr = crossConnectPoints.iterator();
250
251 while (itr.hasNext()) {
252 // checkArgument at start ensures we'll always have pairs of connect points
253 ConnectPoint src = itr.next();
254 ConnectPoint dst = itr.next();
255
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700256 Device.Type srcType = deviceService.getDevice(src.deviceId()).type();
257 Device.Type dstType = deviceService.getDevice(dst.deviceId()).type();
258
259 // Only support connections between identical port types
260 if (srcType != dstType) {
261 log.warn("Unsupported mix of cross connect points");
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700262 return false;
263 }
264 }
265
266 return true;
267 }
268
269 /**
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700270 * Scans the list of cross connection points and returns a list of optical connectivity intents.
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700271 *
272 * @param crossConnectPoints list of cross connection points
273 * @return list of optical connectivity intents
274 */
275 private List<Intent> getIntents(List<ConnectPoint> crossConnectPoints) {
276 checkArgument(crossConnectPoints.size() % 2 == 0);
277
Sho SHIMIZU79945e82015-05-20 17:20:47 -0700278 List<Intent> intents = new LinkedList<>();
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700279 Iterator<ConnectPoint> itr = crossConnectPoints.iterator();
280
281 while (itr.hasNext()) {
282 // checkArgument at start ensures we'll always have pairs of connect points
283 ConnectPoint src = itr.next();
284 ConnectPoint dst = itr.next();
285
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700286 Port srcPort = deviceService.getPort(src.deviceId(), src.port());
287 Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700288
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700289 if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) {
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700290 // Create OTN circuit
291 Intent circuitIntent = OpticalCircuitIntent.builder()
292 .appId(appId)
293 .src(src)
294 .dst(dst)
295 .signalType(OduCltPort.SignalType.CLT_10GBE)
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700296 .bidirectional(true)
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700297 .build();
298 intents.add(circuitIntent);
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700299 } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) {
300 // Create lightpath
301 // FIXME: hardcoded ODU signal type
302 Intent opticalIntent = OpticalConnectivityIntent.builder()
303 .appId(appId)
304 .src(src)
305 .dst(dst)
306 .signalType(OduSignalType.ODU4)
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700307 .bidirectional(true)
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700308 .build();
309 intents.add(opticalIntent);
Marc De Leenheer8c2caac2015-05-28 16:37:33 -0700310 } else {
311 log.warn("Unsupported cross connect point types {} {}", srcPort.type(), dstPort.type());
312 return Collections.emptyList();
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700313 }
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700314 }
315
316 return intents;
317 }
318
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700319 /**
320 * Returns list of optical connectivity intents needed to create connectivity
321 * between ingress and egress.
322 *
323 * @param ingress the ingress connect point
324 * @param egress the egress connect point
325 * @return list of optical connectivity intents, empty list if no path was found
326 */
327 private List<Intent> getOpticalIntents(ConnectPoint ingress, ConnectPoint egress) {
Brian O'Connor772852a2014-11-17 15:51:19 -0800328 Set<Path> paths = pathService.getPaths(ingress.deviceId(),
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700329 egress.deviceId(),
330 new OpticalLinkWeight());
Brian O'Connor772852a2014-11-17 15:51:19 -0800331
332 if (paths.isEmpty()) {
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700333 return Collections.emptyList();
weibit7e583462014-10-23 10:14:05 -0700334 }
Brian O'Connor772852a2014-11-17 15:51:19 -0800335
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700336 // Search path with available cross connect points
337 for (Path path : paths) {
338 List<ConnectPoint> crossConnectPoints = getCrossConnectPoints(path);
Brian O'Connor772852a2014-11-17 15:51:19 -0800339
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700340 // Skip to next path if cross connect points are mismatched
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700341 if (!checkCrossConnectPoints(crossConnectPoints)) {
342 continue;
Brian O'Connor772852a2014-11-17 15:51:19 -0800343 }
344
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700345 return getIntents(crossConnectPoints);
Brian O'Connor772852a2014-11-17 15:51:19 -0800346 }
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800347
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700348 return Collections.emptyList();
Brian O'Connor772852a2014-11-17 15:51:19 -0800349 }
350
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700351 /**
352 * Link weight function that emphasizes re-use of packet links.
353 */
354 private class OpticalLinkWeight implements LinkWeight {
355 @Override
356 public double weight(TopologyEdge edge) {
357 // Ignore inactive links
358 if (edge.link().state() == Link.State.INACTIVE) {
359 return -1;
360 }
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800361
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700362 // TODO: Ignore cross connect links with used ports
363
364 // Transport links have highest weight
365 if (edge.link().type() == Link.Type.OPTICAL) {
366 return 1000;
367 }
368
369 // Packet links
370 return 1;
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800371 }
weibitf32383b2014-10-22 10:17:31 -0700372 }
Brian O'Connorc7bdd8c2014-12-08 01:29:53 -0800373
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700374 /**
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700375 * Release resources associated to the given intent.
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700376 *
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700377 * @param intent the intent
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700378 */
Marc De Leenheer4a1c1fa2015-06-01 18:08:56 -0700379 private void releaseResources(Intent intent) {
Ayaka Koshibebcb02372015-06-01 10:56:42 -0700380 LinkResourceAllocations lra = linkResourceService.getAllocations(intent.id());
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700381 if (intent instanceof OpticalConnectivityIntent) {
Sho SHIMIZU5c16df82015-09-29 12:52:07 -0700382 resourceService.release(intent.id());
Marc De Leenheerc9733082015-06-04 12:22:38 -0700383 if (lra != null) {
384 linkResourceService.releaseResources(lra);
385 }
386 } else if (intent instanceof OpticalCircuitIntent) {
Sho SHIMIZU5c16df82015-09-29 12:52:07 -0700387 resourceService.release(intent.id());
Sho SHIMIZUa6426cb2015-10-01 15:46:48 -0700388 deviceResourceStore.releaseMapping(intent.id());
Ayaka Koshibebcb02372015-06-01 10:56:42 -0700389 if (lra != null) {
390 linkResourceService.releaseResources(lra);
391 }
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700392 }
Marc De Leenheer1afa2a02015-05-13 09:18:07 -0700393 }
Brian O'Connor772852a2014-11-17 15:51:19 -0800394 }
weibitf32383b2014-10-22 10:17:31 -0700395
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700396 /**
397 * Verifies if given link is cross-connect between packet and optical layer.
398 *
399 * @param link the link
400 * @return true if the link is a cross-connect link
401 */
402 public static boolean isCrossConnectLink(Link link) {
403 if (link.type() != Link.Type.OPTICAL) {
404 return false;
Praseed Balakrishnanc0029652014-11-14 13:38:49 -0800405 }
Marc De Leenheer16f857b2015-05-05 20:50:24 -0700406
407 checkNotNull(link.annotations());
408 checkNotNull(link.annotations().value("optical.type"));
409
Sho SHIMIZU6d283122015-05-21 11:07:02 -0700410 return link.annotations().value("optical.type").equals("cross-connect");
Brian O'Connor772852a2014-11-17 15:51:19 -0800411 }
Praseed Balakrishnanc0029652014-11-14 13:38:49 -0800412
weibitf32383b2014-10-22 10:17:31 -0700413}