HIGUCHI Yuta
Committed by Gerrit Code Review

ONOS-3206 refactoring LLDP link provider.

- refactoring to unify LinkDiscovery helper instantiation
- Support suppression rule update at runtime

Change-Id: I2a6db6e82fcb90ee5635f0ac09564efd55276ebf
...@@ -27,6 +27,7 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -27,6 +27,7 @@ import org.apache.felix.scr.annotations.Reference;
27 import org.apache.felix.scr.annotations.ReferenceCardinality; 27 import org.apache.felix.scr.annotations.ReferenceCardinality;
28 import org.onlab.packet.Ethernet; 28 import org.onlab.packet.Ethernet;
29 import org.onosproject.cfg.ComponentConfigService; 29 import org.onosproject.cfg.ComponentConfigService;
30 +import org.onosproject.cluster.ClusterService;
30 import org.onosproject.core.ApplicationId; 31 import org.onosproject.core.ApplicationId;
31 import org.onosproject.core.CoreService; 32 import org.onosproject.core.CoreService;
32 import org.onosproject.mastership.MastershipEvent; 33 import org.onosproject.mastership.MastershipEvent;
...@@ -37,6 +38,7 @@ import org.onosproject.net.Device; ...@@ -37,6 +38,7 @@ import org.onosproject.net.Device;
37 import org.onosproject.net.DeviceId; 38 import org.onosproject.net.DeviceId;
38 import org.onosproject.net.LinkKey; 39 import org.onosproject.net.LinkKey;
39 import org.onosproject.net.Port; 40 import org.onosproject.net.Port;
41 +import org.onosproject.net.config.NetworkConfigRegistry;
40 import org.onosproject.net.device.DeviceEvent; 42 import org.onosproject.net.device.DeviceEvent;
41 import org.onosproject.net.device.DeviceListener; 43 import org.onosproject.net.device.DeviceListener;
42 import org.onosproject.net.device.DeviceService; 44 import org.onosproject.net.device.DeviceService;
...@@ -60,6 +62,7 @@ import java.io.IOException; ...@@ -60,6 +62,7 @@ import java.io.IOException;
60 import java.util.Dictionary; 62 import java.util.Dictionary;
61 import java.util.EnumSet; 63 import java.util.EnumSet;
62 import java.util.Map; 64 import java.util.Map;
65 +import java.util.Optional;
63 import java.util.Properties; 66 import java.util.Properties;
64 import java.util.concurrent.ConcurrentHashMap; 67 import java.util.concurrent.ConcurrentHashMap;
65 import java.util.concurrent.ScheduledExecutorService; 68 import java.util.concurrent.ScheduledExecutorService;
...@@ -86,6 +89,10 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -86,6 +89,10 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
86 "Settings: enabled={}, useBDDP={}, probeRate={}, " + 89 "Settings: enabled={}, useBDDP={}, probeRate={}, " +
87 "staleLinkAge={}, lldpSuppression={}"; 90 "staleLinkAge={}, lldpSuppression={}";
88 91
92 + // When a Device/Port has this annotation, do not send out LLDP/BDDP
93 + public static final String NO_LLDP = "no-lldp";
94 +
95 +
89 private final Logger log = getLogger(getClass()); 96 private final Logger log = getLogger(getClass());
90 97
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -109,6 +116,12 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -109,6 +116,12 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected ComponentConfigService cfgService; 117 protected ComponentConfigService cfgService;
111 118
119 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 + protected ClusterService clusterService;
121 +
122 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 + protected NetworkConfigRegistry cfgRegistry;
124 +
112 private LinkProviderService providerService; 125 private LinkProviderService providerService;
113 126
114 private ScheduledExecutorService executor; 127 private ScheduledExecutorService executor;
...@@ -207,7 +220,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -207,7 +220,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
207 newLldpSuppression = isNullOrEmpty(s) ? DEFAULT_LLDP_SUPPRESSION_CONFIG : s; 220 newLldpSuppression = isNullOrEmpty(s) ? DEFAULT_LLDP_SUPPRESSION_CONFIG : s;
208 221
209 } catch (NumberFormatException e) { 222 } catch (NumberFormatException e) {
210 - log.warn(e.getMessage()); 223 + log.warn("Component configuration had invalid values", e);
211 newEnabled = enabled; 224 newEnabled = enabled;
212 newUseBddp = useBDDP; 225 newUseBddp = useBDDP;
213 newProbeRate = probeRate; 226 newProbeRate = probeRate;
...@@ -227,6 +240,14 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -227,6 +240,14 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
227 enable(); 240 enable();
228 } else if (wasEnabled && !enabled) { 241 } else if (wasEnabled && !enabled) {
229 disable(); 242 disable();
243 + } else {
244 + // reflect changes in suppression rules to discovery helpers
245 + // FIXME: After migrating to Network Configuration Subsystem,
246 + // it should be possible to update only changed subset
247 + if (enabled) {
248 + // update all discovery helper state
249 + loadDevices();
250 + }
230 } 251 }
231 252
232 log.info(FORMAT, enabled, useBDDP, probeRate, staleLinkAge, lldpSuppression); 253 log.info(FORMAT, enabled, useBDDP, probeRate, staleLinkAge, lldpSuppression);
...@@ -277,31 +298,96 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -277,31 +298,96 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
277 * Loads available devices and registers their ports to be probed. 298 * Loads available devices and registers their ports to be probed.
278 */ 299 */
279 private void loadDevices() { 300 private void loadDevices() {
280 - for (Device device : deviceService.getAvailableDevices()) { 301 + deviceService.getAvailableDevices()
302 + .forEach(d -> updateDevice(d)
303 + .ifPresent(ld -> updatePorts(ld, d.id())));
304 + }
305 +
306 + /**
307 + * Updates discovery helper for specified device.
308 + *
309 + * Adds and starts a discovery helper for specified device if enabled,
310 + * calls {@link #removeDevice(DeviceId)} otherwise.
311 + *
312 + * @param device device to add
313 + * @return discovery helper if discovery is enabled for the device
314 + */
315 + private Optional<LinkDiscovery> updateDevice(Device device) {
281 if (rules.isSuppressed(device)) { 316 if (rules.isSuppressed(device)) {
282 - log.debug("LinkDiscovery from {} disabled by configuration", device.id()); 317 + log.trace("LinkDiscovery from {} disabled by configuration", device.id());
283 - continue; 318 + removeDevice(device.id());
319 + return Optional.empty();
284 } 320 }
285 - LinkDiscovery ld = new LinkDiscovery(device, context); 321 + LinkDiscovery ld = discoverers.computeIfAbsent(device.id(),
286 - discoverers.put(device.id(), ld); 322 + did -> new LinkDiscovery(device, context));
287 - addPorts(ld, device.id()); 323 + if (ld.isStopped()) {
324 + ld.start();
325 + }
326 + return Optional.of(ld);
327 + }
328 +
329 + /**
330 + * Removes after stopping discovery helper for specified device.
331 + * @param deviceId device to remove
332 + */
333 + private void removeDevice(final DeviceId deviceId) {
334 + discoverers.computeIfPresent(deviceId, (did, ld) -> {
335 + ld.stop();
336 + providerService.linksVanished(deviceId);
337 + return null;
338 + });
339 +
288 } 340 }
341 +
342 + /**
343 + * Updates ports of the specified device to the specified discovery helper.
344 + */
345 + private void updatePorts(LinkDiscovery discoverer, DeviceId deviceId) {
346 + deviceService.getPorts(deviceId).forEach(p -> updatePort(discoverer, p));
289 } 347 }
290 348
291 /** 349 /**
292 - * Adds ports of the specified device to the specified discovery helper. 350 + * Updates discovery helper state of the specified port.
351 + *
352 + * Adds a port to the discovery helper if up and discovery is enabled,
353 + * or calls {@link #removePort(Port)} otherwise.
293 */ 354 */
294 - private void addPorts(LinkDiscovery discoverer, DeviceId deviceId) { 355 + private void updatePort(LinkDiscovery discoverer, Port port) {
295 - for (Port p : deviceService.getPorts(deviceId)) { 356 + if (rules.isSuppressed(port)) {
296 - if (rules.isSuppressed(p)) { 357 + log.trace("LinkDiscovery from {} disabled by configuration", port);
297 - continue; 358 + removePort(port);
359 + return;
298 } 360 }
299 - if (!p.number().isLogical()) { 361 +
300 - discoverer.addPort(p); 362 + // check if enabled and turn off discovery?
363 + if (!port.isEnabled()) {
364 + removePort(port);
365 + return;
366 + }
367 +
368 + if (!port.number().isLogical()) {
369 + discoverer.addPort(port);
301 } 370 }
302 } 371 }
372 +
373 + /**
374 + * Removes a port from the specified discovery helper.
375 + * @param port the port
376 + */
377 + private void removePort(Port port) {
378 + if (port.element() instanceof Device) {
379 + Device d = (Device) port.element();
380 + LinkDiscovery ld = discoverers.get(d.id());
381 + if (ld != null) {
382 + ld.removePort(port.number());
303 } 383 }
304 384
385 + ConnectPoint point = new ConnectPoint(d.id(), port.number());
386 + providerService.linksVanished(point);
387 + } else {
388 + log.warn("Attempted to remove non-Device port", port);
389 + }
390 + }
305 391
306 /** 392 /**
307 * Loads LLDP suppression rules. 393 * Loads LLDP suppression rules.
...@@ -317,7 +403,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -317,7 +403,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
317 // default rule to suppress ROADM to maintain compatibility 403 // default rule to suppress ROADM to maintain compatibility
318 rules = new SuppressionRules(ImmutableSet.of(), 404 rules = new SuppressionRules(ImmutableSet.of(),
319 EnumSet.of(Device.Type.ROADM), 405 EnumSet.of(Device.Type.ROADM),
320 - ImmutableMap.of()); 406 + ImmutableMap.of(NO_LLDP, SuppressionRules.ANY_VALUE));
321 } 407 }
322 408
323 // should refresh discoverers when we need dynamic reconfiguration 409 // should refresh discoverers when we need dynamic reconfiguration
...@@ -367,10 +453,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -367,10 +453,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
367 log.debug("Device {} doesn't exist, or isn't there yet", deviceId); 453 log.debug("Device {} doesn't exist, or isn't there yet", deviceId);
368 return; 454 return;
369 } 455 }
370 - if (rules.isSuppressed(device)) { 456 + if (clusterService.getLocalNode().id().equals(event.roleInfo().master())) {
371 - return; 457 + updateDevice(device).ifPresent(ld -> updatePorts(ld, device.id()));
372 } 458 }
373 - discoverers.computeIfAbsent(deviceId, k -> new LinkDiscovery(device, context));
374 } 459 }
375 460
376 } 461 }
...@@ -381,7 +466,6 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -381,7 +466,6 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
381 private class InternalDeviceListener implements DeviceListener { 466 private class InternalDeviceListener implements DeviceListener {
382 @Override 467 @Override
383 public void event(DeviceEvent event) { 468 public void event(DeviceEvent event) {
384 - LinkDiscovery ld;
385 Device device = event.subject(); 469 Device device = event.subject();
386 Port port = event.port(); 470 Port port = event.port();
387 if (device == null) { 471 if (device == null) {
...@@ -393,73 +477,33 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -393,73 +477,33 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
393 switch (event.type()) { 477 switch (event.type()) {
394 case DEVICE_ADDED: 478 case DEVICE_ADDED:
395 case DEVICE_UPDATED: 479 case DEVICE_UPDATED:
396 - synchronized (discoverers) { 480 + updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId));
397 - ld = discoverers.get(deviceId);
398 - if (ld == null) {
399 - if (rules != null && rules.isSuppressed(device)) {
400 - log.debug("LinkDiscovery from {} disabled by configuration", device.id());
401 - return;
402 - }
403 - log.debug("Device added ({}) {}", event.type(), deviceId);
404 - discoverers.put(deviceId, new LinkDiscovery(device, context));
405 - } else {
406 - if (ld.isStopped()) {
407 - log.debug("Device restarted ({}) {}", event.type(), deviceId);
408 - ld.start();
409 - }
410 - }
411 - }
412 break; 481 break;
413 case PORT_ADDED: 482 case PORT_ADDED:
414 case PORT_UPDATED: 483 case PORT_UPDATED:
415 if (port.isEnabled()) { 484 if (port.isEnabled()) {
416 - ld = discoverers.get(deviceId); 485 + updateDevice(device).ifPresent(ld -> updatePort(ld, port));
417 - if (ld == null) {
418 - return;
419 - }
420 - if (rules.isSuppressed(port)) {
421 - log.debug("LinkDiscovery from {}@{} disabled by configuration",
422 - port.number(), device.id());
423 - return;
424 - }
425 - if (!port.number().isLogical()) {
426 - log.debug("Port added {}", port);
427 - ld.addPort(port);
428 - }
429 } else { 486 } else {
430 log.debug("Port down {}", port); 487 log.debug("Port down {}", port);
431 - ConnectPoint point = new ConnectPoint(deviceId, port.number()); 488 + removePort(port);
432 - providerService.linksVanished(point);
433 } 489 }
434 break; 490 break;
435 case PORT_REMOVED: 491 case PORT_REMOVED:
436 log.debug("Port removed {}", port); 492 log.debug("Port removed {}", port);
437 - ConnectPoint point = new ConnectPoint(deviceId, port.number()); 493 + removePort(port);
438 - providerService.linksVanished(point);
439 -
440 break; 494 break;
441 case DEVICE_REMOVED: 495 case DEVICE_REMOVED:
442 case DEVICE_SUSPENDED: 496 case DEVICE_SUSPENDED:
443 log.debug("Device removed {}", deviceId); 497 log.debug("Device removed {}", deviceId);
444 - ld = discoverers.get(deviceId); 498 + removeDevice(deviceId);
445 - if (ld == null) {
446 - return;
447 - }
448 - ld.stop();
449 - providerService.linksVanished(deviceId);
450 break; 499 break;
451 case DEVICE_AVAILABILITY_CHANGED: 500 case DEVICE_AVAILABILITY_CHANGED:
452 - ld = discoverers.get(deviceId);
453 - if (ld == null) {
454 - return;
455 - }
456 if (deviceService.isAvailable(deviceId)) { 501 if (deviceService.isAvailable(deviceId)) {
457 log.debug("Device up {}", deviceId); 502 log.debug("Device up {}", deviceId);
458 - ld.start(); 503 + updateDevice(device);
459 } else { 504 } else {
460 - providerService.linksVanished(deviceId);
461 log.debug("Device down {}", deviceId); 505 log.debug("Device down {}", deviceId);
462 - ld.stop(); 506 + removeDevice(deviceId);
463 } 507 }
464 break; 508 break;
465 case PORT_STATS_UPDATED: 509 case PORT_STATS_UPDATED:
...@@ -508,17 +552,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -508,17 +552,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
508 } 552 }
509 // check what deviceService sees, to see if we are missing anything 553 // check what deviceService sees, to see if we are missing anything
510 try { 554 try {
511 - for (Device dev : deviceService.getDevices()) { 555 + loadDevices();
512 - if (rules.isSuppressed(dev)) {
513 - continue;
514 - }
515 - DeviceId did = dev.id();
516 - synchronized (discoverers) {
517 - LinkDiscovery ld = discoverers
518 - .computeIfAbsent(did, k -> new LinkDiscovery(dev, context));
519 - addPorts(ld, did);
520 - }
521 - }
522 } catch (Exception e) { 556 } catch (Exception e) {
523 // Catch all exceptions to avoid task being suppressed 557 // Catch all exceptions to avoid task being suppressed
524 log.error("Exception thrown during synchronization process", e); 558 log.error("Exception thrown during synchronization process", e);
......
...@@ -61,7 +61,7 @@ class LinkDiscovery implements TimerTask { ...@@ -61,7 +61,7 @@ class LinkDiscovery implements TimerTask {
61 61
62 private final ONOSLLDP lldpPacket; 62 private final ONOSLLDP lldpPacket;
63 private final Ethernet ethPacket; 63 private final Ethernet ethPacket;
64 - private Ethernet bddpEth; 64 + private final Ethernet bddpEth;
65 65
66 private Timeout timeout; 66 private Timeout timeout;
67 private volatile boolean isStopped; 67 private volatile boolean isStopped;
...@@ -126,7 +126,7 @@ class LinkDiscovery implements TimerTask { ...@@ -126,7 +126,7 @@ class LinkDiscovery implements TimerTask {
126 } 126 }
127 127
128 /** 128 /**
129 - * Add physical port port to discovery process. 129 + * Add physical port to discovery process.
130 * Send out initial LLDP and label it as slow port. 130 * Send out initial LLDP and label it as slow port.
131 * 131 *
132 * @param port the port 132 * @param port the port
...@@ -141,6 +141,14 @@ class LinkDiscovery implements TimerTask { ...@@ -141,6 +141,14 @@ class LinkDiscovery implements TimerTask {
141 } 141 }
142 142
143 /** 143 /**
144 + * removed physical port from discovery process.
145 + * @param port the port number
146 + */
147 + void removePort(PortNumber port) {
148 + ports.remove(port.toLong());
149 + }
150 +
151 + /**
144 * Handles an incoming LLDP packet. Creates link in topology and adds the 152 * Handles an incoming LLDP packet. Creates link in topology and adds the
145 * link for staleness tracking. 153 * link for staleness tracking.
146 * 154 *
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.provider.lldp.impl; 16 package org.onosproject.provider.lldp.impl;
17 17
18 import com.google.common.collect.ArrayListMultimap; 18 import com.google.common.collect.ArrayListMultimap;
19 +import com.google.common.collect.ImmutableList;
19 import com.google.common.collect.Lists; 20 import com.google.common.collect.Lists;
20 import com.google.common.collect.Maps; 21 import com.google.common.collect.Maps;
21 import org.junit.After; 22 import org.junit.After;
...@@ -32,7 +33,9 @@ import org.onosproject.core.CoreService; ...@@ -32,7 +33,9 @@ import org.onosproject.core.CoreService;
32 import org.onosproject.core.DefaultApplicationId; 33 import org.onosproject.core.DefaultApplicationId;
33 import org.onosproject.mastership.MastershipListener; 34 import org.onosproject.mastership.MastershipListener;
34 import org.onosproject.mastership.MastershipService; 35 import org.onosproject.mastership.MastershipService;
36 +import org.onosproject.net.Annotations;
35 import org.onosproject.net.ConnectPoint; 37 import org.onosproject.net.ConnectPoint;
38 +import org.onosproject.net.DefaultAnnotations;
36 import org.onosproject.net.DefaultDevice; 39 import org.onosproject.net.DefaultDevice;
37 import org.onosproject.net.DefaultPort; 40 import org.onosproject.net.DefaultPort;
38 import org.onosproject.net.Device; 41 import org.onosproject.net.Device;
...@@ -73,6 +76,7 @@ public class LLDPLinkProviderTest { ...@@ -73,6 +76,7 @@ public class LLDPLinkProviderTest {
73 76
74 private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001"); 77 private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
75 private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002"); 78 private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002");
79 + private static final DeviceId DID3 = DeviceId.deviceId("of:0000000000000003");
76 80
77 private static Port pd1; 81 private static Port pd1;
78 private static Port pd2; 82 private static Port pd2;
...@@ -133,10 +137,35 @@ public class LLDPLinkProviderTest { ...@@ -133,10 +137,35 @@ public class LLDPLinkProviderTest {
133 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); 137 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
134 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_REMOVED, DID1)); 138 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_REMOVED, DID1));
135 139
136 - assertTrue("Discoverer is not gone", provider.discoverers.get(DID1).isStopped()); 140 + final LinkDiscovery linkDiscovery = provider.discoverers.get(DID1);
141 + if (linkDiscovery != null) {
142 + // If LinkDiscovery helper is there after DEVICE_REMOVED,
143 + // it should be stopped
144 + assertTrue("Discoverer is not stopped", linkDiscovery.isStopped());
145 + }
137 assertTrue("Device is not gone.", vanishedDpid(DID1)); 146 assertTrue("Device is not gone.", vanishedDpid(DID1));
138 } 147 }
139 148
149 + /**
150 + * Checks that links on a reconfigured switch are properly removed.
151 + */
152 + @Test
153 + public void switchSuppressed() {
154 + // add device to stub DeviceService
155 + deviceService.putDevice(device(DID3));
156 + deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
157 +
158 + assertFalse("Device not added", provider.discoverers.isEmpty());
159 +
160 + // update device in stub DeviceService with suppression config
161 + deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
162 + .set(LLDPLinkProvider.NO_LLDP, "true")
163 + .build()));
164 + deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
165 +
166 + assertTrue("Links on suppressed Device was expected to vanish.", vanishedDpid(DID3));
167 + }
168 +
140 @Test 169 @Test
141 public void portUp() { 170 public void portUp() {
142 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); 171 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
...@@ -152,27 +181,101 @@ public class LLDPLinkProviderTest { ...@@ -152,27 +181,101 @@ public class LLDPLinkProviderTest {
152 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); 181 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
153 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 1, false))); 182 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 1, false)));
154 183
155 -
156 -
157 assertFalse("Port added to discoverer", 184 assertFalse("Port added to discoverer",
158 provider.discoverers.get(DID1).containsPort(1L)); 185 provider.discoverers.get(DID1).containsPort(1L));
159 assertTrue("Port is not gone.", vanishedPort(1L)); 186 assertTrue("Port is not gone.", vanishedPort(1L));
160 } 187 }
161 188
162 @Test 189 @Test
190 + public void portRemoved() {
191 + deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
192 + deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
193 + deviceListener.event(portEvent(DeviceEvent.Type.PORT_REMOVED, DID1, port(DID1, 3, true)));
194 +
195 + assertTrue("Port is not gone.", vanishedPort(3L));
196 + assertFalse("Port was not removed from discoverer",
197 + provider.discoverers.get(DID1).containsPort(3L));
198 + }
199 +
200 + /**
201 + * Checks that discovery on reconfigured switch are properly restarted.
202 + */
203 + @Test
204 + public void portSuppressedByDeviceConfig() {
205 +
206 + /// When Device is configured with suppression:ON, Port also is same
207 +
208 + // add device in stub DeviceService with suppression configured
209 + deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
210 + .set(LLDPLinkProvider.NO_LLDP, "true")
211 + .build()));
212 + deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
213 +
214 + // non-suppressed port added to suppressed device
215 + final long portno3 = 3L;
216 + deviceService.putPorts(DID3, port(DID3, portno3, true));
217 + deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));
218 +
219 + // discovery on device is expected to be stopped
220 + LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
221 + if (linkDiscovery != null) {
222 + assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
223 + }
224 +
225 + /// When Device is reconfigured without suppression:OFF,
226 + /// Port should be included for discovery
227 +
228 + // update device in stub DeviceService without suppression configured
229 + deviceService.putDevice(device(DID3));
230 + // update the Port in stub DeviceService. (Port has reference to Device)
231 + deviceService.putPorts(DID3, port(DID3, portno3, true));
232 + deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
233 +
234 + // discovery should come back on
235 + assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
236 + assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
237 + }
238 +
239 + /**
240 + * Checks that discovery on reconfigured port are properly restarted.
241 + */
242 + @Test
243 + public void portSuppressedByPortConfig() {
244 + // add device in stub DeviceService without suppression configured
245 + deviceService.putDevice(device(DID3));
246 + deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
247 +
248 + // suppressed port added to non-suppressed device
249 + final long portno3 = 3L;
250 + final Port port3 = port(DID3, portno3, true,
251 + DefaultAnnotations.builder()
252 + .set(LLDPLinkProvider.NO_LLDP, "true")
253 + .build());
254 + deviceService.putPorts(DID3, port3);
255 + deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));
256 +
257 + // discovery helper should be there turned on
258 + assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
259 + assertFalse("Discoverer should not contain the port there",
260 + provider.discoverers.get(DID3).containsPort(portno3));
261 + }
262 +
263 + @Test
163 public void portUnknown() { 264 public void portUnknown() {
164 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); 265 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
165 - deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID2, port(DID2, 1, false))); 266 + // Note: DID3 hasn't been added to TestDeviceService, but only port is added
267 + deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, 1, false)));
166 268
167 269
168 assertNull("DeviceId exists", 270 assertNull("DeviceId exists",
169 - provider.discoverers.get(DID2)); 271 + provider.discoverers.get(DID3));
170 } 272 }
171 273
172 @Test 274 @Test
173 public void unknownPktCtx() { 275 public void unknownPktCtx() {
174 276
175 - PacketContext pktCtx = new TestPacketContext(deviceService.getDevice(DID2)); 277 + // Note: DID3 hasn't been added to TestDeviceService
278 + PacketContext pktCtx = new TestPacketContext(device(DID3));
176 279
177 testProcessor.process(pktCtx); 280 testProcessor.process(pktCtx);
178 assertFalse("Context should still be free", pktCtx.isHandled()); 281 assertFalse("Context should still be free", pktCtx.isHandled());
...@@ -206,6 +309,16 @@ public class LLDPLinkProviderTest { ...@@ -206,6 +309,16 @@ public class LLDPLinkProviderTest {
206 309
207 } 310 }
208 311
312 + private DefaultDevice device(DeviceId did) {
313 + return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
314 + "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
315 + }
316 +
317 + private DefaultDevice device(DeviceId did, Annotations annotations) {
318 + return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
319 + "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId(), annotations);
320 + }
321 +
209 @SuppressWarnings(value = { "unused" }) 322 @SuppressWarnings(value = { "unused" })
210 private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, PortNumber port) { 323 private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, PortNumber port) {
211 return new DeviceEvent(type, deviceService.getDevice(did), 324 return new DeviceEvent(type, deviceService.getDevice(did),
...@@ -221,6 +334,10 @@ public class LLDPLinkProviderTest { ...@@ -221,6 +334,10 @@ public class LLDPLinkProviderTest {
221 PortNumber.portNumber(port), enabled); 334 PortNumber.portNumber(port), enabled);
222 } 335 }
223 336
337 + private Port port(DeviceId did, long port, boolean enabled, Annotations annotations) {
338 + return new DefaultPort(deviceService.getDevice(did),
339 + PortNumber.portNumber(port), enabled, annotations);
340 + }
224 341
225 private boolean vanishedDpid(DeviceId... dids) { 342 private boolean vanishedDpid(DeviceId... dids) {
226 for (int i = 0; i < dids.length; i++) { 343 for (int i = 0; i < dids.length; i++) {
...@@ -384,10 +501,9 @@ public class LLDPLinkProviderTest { ...@@ -384,10 +501,9 @@ public class LLDPLinkProviderTest {
384 501
385 private class TestDeviceService extends DeviceServiceAdapter { 502 private class TestDeviceService extends DeviceServiceAdapter {
386 503
387 - private Map<DeviceId, Device> devices = new HashMap<>(); 504 + private final Map<DeviceId, Device> devices = new HashMap<>();
388 private final ArrayListMultimap<DeviceId, Port> ports = 505 private final ArrayListMultimap<DeviceId, Port> ports =
389 ArrayListMultimap.create(); 506 ArrayListMultimap.create();
390 -
391 public TestDeviceService() { 507 public TestDeviceService() {
392 Device d1 = new DefaultDevice(ProviderId.NONE, DID1, Device.Type.SWITCH, 508 Device d1 = new DefaultDevice(ProviderId.NONE, DID1, Device.Type.SWITCH,
393 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId()); 509 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
...@@ -395,7 +511,6 @@ public class LLDPLinkProviderTest { ...@@ -395,7 +511,6 @@ public class LLDPLinkProviderTest {
395 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId()); 511 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
396 devices.put(DID1, d1); 512 devices.put(DID1, d1);
397 devices.put(DID2, d2); 513 devices.put(DID2, d2);
398 -
399 pd1 = new DefaultPort(d1, PortNumber.portNumber(1), true); 514 pd1 = new DefaultPort(d1, PortNumber.portNumber(1), true);
400 pd2 = new DefaultPort(d1, PortNumber.portNumber(2), true); 515 pd2 = new DefaultPort(d1, PortNumber.portNumber(2), true);
401 pd3 = new DefaultPort(d2, PortNumber.portNumber(1), true); 516 pd3 = new DefaultPort(d2, PortNumber.portNumber(1), true);
...@@ -405,6 +520,15 @@ public class LLDPLinkProviderTest { ...@@ -405,6 +520,15 @@ public class LLDPLinkProviderTest {
405 ports.putAll(DID2, Lists.newArrayList(pd3, pd4)); 520 ports.putAll(DID2, Lists.newArrayList(pd3, pd4));
406 } 521 }
407 522
523 + private void putDevice(Device device) {
524 + DeviceId deviceId = device.id();
525 + devices.put(deviceId, device);
526 + }
527 +
528 + private void putPorts(DeviceId did, Port...ports) {
529 + this.ports.putAll(did, Lists.newArrayList(ports));
530 + }
531 +
408 @Override 532 @Override
409 public int getDeviceCount() { 533 public int getDeviceCount() {
410 return devices.values().size(); 534 return devices.values().size();
...@@ -412,7 +536,7 @@ public class LLDPLinkProviderTest { ...@@ -412,7 +536,7 @@ public class LLDPLinkProviderTest {
412 536
413 @Override 537 @Override
414 public Iterable<Device> getDevices() { 538 public Iterable<Device> getDevices() {
415 - return Collections.emptyList(); 539 + return ImmutableList.copyOf(devices.values());
416 } 540 }
417 541
418 @Override 542 @Override
......