HIGUCHI Yuta
Committed by Gerrit Code Review

ONOS-3461 Disable LinkDiscovery on specific device/port.

- Configuration moved from "apps" -> "devices", "ports"
  in network configuration tree

Change-Id: I030bab489939ce5326a6ebea14f246726ca024f0
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.config.basics;
17 +
18 +import org.onosproject.net.config.Config;
19 +
20 +/**
21 + * Base abstraction for configuring feature on subject.
22 + *
23 + * @param <S> Subject type
24 + */
25 +public abstract class BasicFeatureConfig<S> extends Config<S> {
26 +
27 + private static final String ENABLED = "enabled";
28 +
29 + private final boolean defaultValue;
30 +
31 + protected BasicFeatureConfig(boolean defaultValue) {
32 + this.defaultValue = defaultValue;
33 + }
34 +
35 + /**
36 + * Indicates whether the feature for the subject is enabled.
37 + *
38 + * @return true if feature is enabled
39 + */
40 + public boolean enabled() {
41 + return get(ENABLED, defaultValue);
42 + }
43 +
44 + /**
45 + * Specifies whether the feature for the subject is to be enabled.
46 + *
47 + * @param enabled true to enable; false to disable; null to clear
48 + * @return self
49 + */
50 + public BasicFeatureConfig<S> enabled(Boolean enabled) {
51 + return (BasicFeatureConfig<S>) setOrClear(ENABLED, enabled);
52 + }
53 +
54 +}
...@@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.node.DoubleNode; ...@@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.node.DoubleNode;
23 import com.fasterxml.jackson.databind.node.IntNode; 23 import com.fasterxml.jackson.databind.node.IntNode;
24 import com.fasterxml.jackson.databind.node.JsonNodeFactory; 24 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
25 import com.fasterxml.jackson.databind.node.LongNode; 25 import com.fasterxml.jackson.databind.node.LongNode;
26 +import com.fasterxml.jackson.databind.node.NullNode;
26 import com.fasterxml.jackson.databind.node.ObjectNode; 27 import com.fasterxml.jackson.databind.node.ObjectNode;
27 import com.fasterxml.jackson.databind.node.ShortNode; 28 import com.fasterxml.jackson.databind.node.ShortNode;
28 import com.fasterxml.jackson.databind.node.TextNode; 29 import com.fasterxml.jackson.databind.node.TextNode;
...@@ -95,7 +96,8 @@ public class DistributedNetworkConfigStore ...@@ -95,7 +96,8 @@ public class DistributedNetworkConfigStore
95 .register(ConfigKey.class, ObjectNode.class, ArrayNode.class, 96 .register(ConfigKey.class, ObjectNode.class, ArrayNode.class,
96 JsonNodeFactory.class, LinkedHashMap.class, 97 JsonNodeFactory.class, LinkedHashMap.class,
97 TextNode.class, BooleanNode.class, 98 TextNode.class, BooleanNode.class,
98 - LongNode.class, DoubleNode.class, ShortNode.class, IntNode.class); 99 + LongNode.class, DoubleNode.class, ShortNode.class, IntNode.class,
100 + NullNode.class);
99 101
100 configs = storageService.<ConfigKey, JsonNode>consistentMapBuilder() 102 configs = storageService.<ConfigKey, JsonNode>consistentMapBuilder()
101 .withSerializer(Serializer.using(kryoBuilder.build())) 103 .withSerializer(Serializer.using(kryoBuilder.build()))
......
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.provider.lldp.impl;
17 +
18 +import org.onosproject.net.DeviceId;
19 +import org.onosproject.net.config.basics.BasicFeatureConfig;
20 +
21 +/**
22 + * Configuration to see LinkDiscovery should be enabled on Device.
23 + */
24 +public class LinkDiscoveryFromDevice extends BasicFeatureConfig<DeviceId> {
25 +
26 + public LinkDiscoveryFromDevice() {
27 + // default: enabled
28 + super(true);
29 + }
30 +
31 +}
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.provider.lldp.impl;
17 +
18 +import org.onosproject.net.ConnectPoint;
19 +import org.onosproject.net.config.basics.BasicFeatureConfig;
20 +
21 +/**
22 + * Configuration to see LinkDiscovery should be enabled on a Port.
23 + */
24 +public class LinkDiscoveryFromPort extends BasicFeatureConfig<ConnectPoint> {
25 +
26 + public LinkDiscoveryFromPort() {
27 + // default: enabled
28 + super(true);
29 + }
30 +
31 +}
...@@ -15,9 +15,28 @@ ...@@ -15,9 +15,28 @@
15 */ 15 */
16 package org.onosproject.provider.lldp.impl; 16 package org.onosproject.provider.lldp.impl;
17 17
18 -import com.google.common.collect.ImmutableMap; 18 +import static com.google.common.base.Strings.isNullOrEmpty;
19 -import com.google.common.collect.ImmutableSet; 19 +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
20 -import com.google.common.collect.Maps; 20 +import static java.util.concurrent.TimeUnit.SECONDS;
21 +import static org.onlab.packet.Ethernet.TYPE_BSN;
22 +import static org.onlab.packet.Ethernet.TYPE_LLDP;
23 +import static org.onlab.util.Tools.get;
24 +import static org.onlab.util.Tools.groupedThreads;
25 +import static org.onosproject.net.Link.Type.DIRECT;
26 +import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
27 +import static org.onosproject.net.config.basics.SubjectFactories.CONNECT_POINT_SUBJECT_FACTORY;
28 +import static org.onosproject.net.config.basics.SubjectFactories.DEVICE_SUBJECT_FACTORY;
29 +import static org.slf4j.LoggerFactory.getLogger;
30 +
31 +import java.util.Dictionary;
32 +import java.util.EnumSet;
33 +import java.util.Map;
34 +import java.util.Optional;
35 +import java.util.Properties;
36 +import java.util.Set;
37 +import java.util.concurrent.ConcurrentHashMap;
38 +import java.util.concurrent.ScheduledExecutorService;
39 +
21 import org.apache.felix.scr.annotations.Activate; 40 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 41 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 42 import org.apache.felix.scr.annotations.Deactivate;
...@@ -61,25 +80,9 @@ import org.onosproject.net.provider.ProviderId; ...@@ -61,25 +80,9 @@ import org.onosproject.net.provider.ProviderId;
61 import org.osgi.service.component.ComponentContext; 80 import org.osgi.service.component.ComponentContext;
62 import org.slf4j.Logger; 81 import org.slf4j.Logger;
63 82
64 -import java.util.Dictionary; 83 +import com.google.common.collect.ImmutableMap;
65 -import java.util.EnumSet; 84 +import com.google.common.collect.ImmutableSet;
66 -import java.util.Map; 85 +import com.google.common.collect.Maps;
67 -import java.util.Optional;
68 -import java.util.Properties;
69 -import java.util.Set;
70 -import java.util.concurrent.ConcurrentHashMap;
71 -import java.util.concurrent.ScheduledExecutorService;
72 -
73 -import static com.google.common.base.Strings.isNullOrEmpty;
74 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
75 -import static java.util.concurrent.TimeUnit.SECONDS;
76 -import static org.onlab.packet.Ethernet.TYPE_BSN;
77 -import static org.onlab.packet.Ethernet.TYPE_LLDP;
78 -import static org.onlab.util.Tools.get;
79 -import static org.onlab.util.Tools.groupedThreads;
80 -import static org.onosproject.net.Link.Type.DIRECT;
81 -import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
82 -import static org.slf4j.LoggerFactory.getLogger;
83 86
84 /** 87 /**
85 * Provider which uses LLDP and BDDP packets to detect network infrastructure links. 88 * Provider which uses LLDP and BDDP packets to detect network infrastructure links.
...@@ -170,15 +173,15 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -170,15 +173,15 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
170 private ApplicationId appId; 173 private ApplicationId appId;
171 174
172 static final SuppressionRules DEFAULT_RULES 175 static final SuppressionRules DEFAULT_RULES
173 - = new SuppressionRules(ImmutableSet.of(), 176 + = new SuppressionRules(EnumSet.of(Device.Type.ROADM),
174 - EnumSet.of(Device.Type.ROADM),
175 ImmutableMap.of(NO_LLDP, SuppressionRules.ANY_VALUE)); 177 ImmutableMap.of(NO_LLDP, SuppressionRules.ANY_VALUE));
176 178
177 private SuppressionRules rules = LldpLinkProvider.DEFAULT_RULES; 179 private SuppressionRules rules = LldpLinkProvider.DEFAULT_RULES;
178 180
179 public static final String CONFIG_KEY = "suppression"; 181 public static final String CONFIG_KEY = "suppression";
182 + public static final String FEATURE_NAME = "linkDiscovery";
180 183
181 - private final Set<ConfigFactory> factories = ImmutableSet.of( 184 + private final Set<ConfigFactory<?, ?>> factories = ImmutableSet.of(
182 new ConfigFactory<ApplicationId, SuppressionConfig>(APP_SUBJECT_FACTORY, 185 new ConfigFactory<ApplicationId, SuppressionConfig>(APP_SUBJECT_FACTORY,
183 SuppressionConfig.class, 186 SuppressionConfig.class,
184 CONFIG_KEY) { 187 CONFIG_KEY) {
...@@ -186,6 +189,20 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -186,6 +189,20 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
186 public SuppressionConfig createConfig() { 189 public SuppressionConfig createConfig() {
187 return new SuppressionConfig(); 190 return new SuppressionConfig();
188 } 191 }
192 + },
193 + new ConfigFactory<DeviceId, LinkDiscoveryFromDevice>(DEVICE_SUBJECT_FACTORY,
194 + LinkDiscoveryFromDevice.class, FEATURE_NAME) {
195 + @Override
196 + public LinkDiscoveryFromDevice createConfig() {
197 + return new LinkDiscoveryFromDevice();
198 + }
199 + },
200 + new ConfigFactory<ConnectPoint, LinkDiscoveryFromPort>(CONNECT_POINT_SUBJECT_FACTORY,
201 + LinkDiscoveryFromPort.class, FEATURE_NAME) {
202 + @Override
203 + public LinkDiscoveryFromPort createConfig() {
204 + return new LinkDiscoveryFromPort();
205 + }
189 } 206 }
190 ); 207 );
191 208
...@@ -211,8 +228,7 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -211,8 +228,7 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
211 if (cfg == null) { 228 if (cfg == null) {
212 // If no configuration is found, register default. 229 // If no configuration is found, register default.
213 cfg = cfgRegistry.addConfig(appId, SuppressionConfig.class); 230 cfg = cfgRegistry.addConfig(appId, SuppressionConfig.class);
214 - cfg.deviceIds(DEFAULT_RULES.getSuppressedDevice()) 231 + cfg.deviceTypes(DEFAULT_RULES.getSuppressedDeviceType())
215 - .deviceTypes(DEFAULT_RULES.getSuppressedDeviceType())
216 .annotation(DEFAULT_RULES.getSuppressedAnnotation()) 232 .annotation(DEFAULT_RULES.getSuppressedAnnotation())
217 .apply(); 233 .apply();
218 } 234 }
...@@ -333,6 +349,30 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -333,6 +349,30 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
333 .ifPresent(ld -> updatePorts(ld, d.id()))); 349 .ifPresent(ld -> updatePorts(ld, d.id())));
334 } 350 }
335 351
352 + private boolean isBlacklisted(DeviceId did) {
353 + LinkDiscoveryFromDevice cfg = cfgRegistry.getConfig(did, LinkDiscoveryFromDevice.class);
354 + if (cfg == null) {
355 + return false;
356 + }
357 + return !cfg.enabled();
358 + }
359 +
360 + private boolean isBlacklisted(ConnectPoint cp) {
361 + // if parent device is blacklisted, so is the port
362 + if (isBlacklisted(cp.deviceId())) {
363 + return true;
364 + }
365 + LinkDiscoveryFromPort cfg = cfgRegistry.getConfig(cp, LinkDiscoveryFromPort.class);
366 + if (cfg == null) {
367 + return false;
368 + }
369 + return !cfg.enabled();
370 + }
371 +
372 + private boolean isBlacklisted(Port port) {
373 + return isBlacklisted(new ConnectPoint(port.element().id(), port.number()));
374 + }
375 +
336 /** 376 /**
337 * Updates discovery helper for specified device. 377 * Updates discovery helper for specified device.
338 * 378 *
...@@ -343,7 +383,10 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -343,7 +383,10 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
343 * @return discovery helper if discovery is enabled for the device 383 * @return discovery helper if discovery is enabled for the device
344 */ 384 */
345 private Optional<LinkDiscovery> updateDevice(Device device) { 385 private Optional<LinkDiscovery> updateDevice(Device device) {
346 - if (rules.isSuppressed(device)) { 386 + if (device == null) {
387 + return Optional.empty();
388 + }
389 + if (rules.isSuppressed(device) || isBlacklisted(device.id())) {
347 log.trace("LinkDiscovery from {} disabled by configuration", device.id()); 390 log.trace("LinkDiscovery from {} disabled by configuration", device.id());
348 removeDevice(device.id()); 391 removeDevice(device.id());
349 return Optional.empty(); 392 return Optional.empty();
...@@ -382,12 +425,15 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -382,12 +425,15 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
382 * or calls {@link #removePort(Port)} otherwise. 425 * or calls {@link #removePort(Port)} otherwise.
383 */ 426 */
384 private void updatePort(LinkDiscovery discoverer, Port port) { 427 private void updatePort(LinkDiscovery discoverer, Port port) {
428 + if (port == null) {
429 + return;
430 + }
385 if (port.number().isLogical()) { 431 if (port.number().isLogical()) {
386 // silently ignore logical ports 432 // silently ignore logical ports
387 return; 433 return;
388 } 434 }
389 435
390 - if (rules.isSuppressed(port)) { 436 + if (rules.isSuppressed(port) || isBlacklisted(port)) {
391 log.trace("LinkDiscovery from {} disabled by configuration", port); 437 log.trace("LinkDiscovery from {} disabled by configuration", port);
392 removePort(port); 438 removePort(port);
393 return; 439 return;
...@@ -659,6 +705,11 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -659,6 +705,11 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
659 } 705 }
660 } 706 }
661 707
708 + static final EnumSet<NetworkConfigEvent.Type> CONFIG_CHANGED
709 + = EnumSet.of(NetworkConfigEvent.Type.CONFIG_ADDED,
710 + NetworkConfigEvent.Type.CONFIG_UPDATED,
711 + NetworkConfigEvent.Type.CONFIG_REMOVED);
712 +
662 private class InternalConfigListener implements NetworkConfigListener { 713 private class InternalConfigListener implements NetworkConfigListener {
663 714
664 private synchronized void reconfigureSuppressionRules(SuppressionConfig cfg) { 715 private synchronized void reconfigureSuppressionRules(SuppressionConfig cfg) {
...@@ -667,8 +718,7 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -667,8 +718,7 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
667 return; 718 return;
668 } 719 }
669 720
670 - SuppressionRules newRules = new SuppressionRules(cfg.deviceIds(), 721 + SuppressionRules newRules = new SuppressionRules(cfg.deviceTypes(),
671 - cfg.deviceTypes(),
672 cfg.annotation()); 722 cfg.annotation());
673 723
674 updateRules(newRules); 724 updateRules(newRules);
...@@ -676,7 +726,29 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -676,7 +726,29 @@ public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
676 726
677 @Override 727 @Override
678 public void event(NetworkConfigEvent event) { 728 public void event(NetworkConfigEvent event) {
679 - if (event.configClass().equals(SuppressionConfig.class) && 729 + if (event.configClass() == LinkDiscoveryFromDevice.class &&
730 + CONFIG_CHANGED.contains(event.type())) {
731 +
732 + if (event.subject() instanceof DeviceId) {
733 + final DeviceId did = (DeviceId) event.subject();
734 + Device device = deviceService.getDevice(did);
735 + updateDevice(device).ifPresent(ld -> updatePorts(ld, did));
736 + }
737 +
738 + } else if (event.configClass() == LinkDiscoveryFromPort.class &&
739 + CONFIG_CHANGED.contains(event.type())) {
740 +
741 + if (event.subject() instanceof ConnectPoint) {
742 + ConnectPoint cp = (ConnectPoint) event.subject();
743 + if (cp.elementId() instanceof DeviceId) {
744 + final DeviceId did = (DeviceId) cp.elementId();
745 + Device device = deviceService.getDevice(did);
746 + Port port = deviceService.getPort(did, cp.port());
747 + updateDevice(device).ifPresent(ld -> updatePort(ld, port));
748 + }
749 + }
750 +
751 + } else if (event.configClass().equals(SuppressionConfig.class) &&
680 (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED || 752 (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
681 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) { 753 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) {
682 SuppressionConfig cfg = cfgRegistry.getConfig(appId, SuppressionConfig.class); 754 SuppressionConfig cfg = cfgRegistry.getConfig(appId, SuppressionConfig.class);
......
...@@ -26,7 +26,6 @@ import com.google.common.collect.Maps; ...@@ -26,7 +26,6 @@ import com.google.common.collect.Maps;
26 26
27 import org.onosproject.core.ApplicationId; 27 import org.onosproject.core.ApplicationId;
28 import org.onosproject.net.Device; 28 import org.onosproject.net.Device;
29 -import org.onosproject.net.DeviceId;
30 import org.onosproject.net.config.Config; 29 import org.onosproject.net.config.Config;
31 import org.slf4j.Logger; 30 import org.slf4j.Logger;
32 31
...@@ -39,44 +38,22 @@ import static org.onosproject.provider.lldp.impl.LldpLinkProvider.DEFAULT_RULES; ...@@ -39,44 +38,22 @@ import static org.onosproject.provider.lldp.impl.LldpLinkProvider.DEFAULT_RULES;
39 import static org.slf4j.LoggerFactory.getLogger; 38 import static org.slf4j.LoggerFactory.getLogger;
40 39
41 /** 40 /**
42 - * LLDP suppression config class. 41 + * LinkDiscovery suppression config class.
43 */ 42 */
44 public class SuppressionConfig extends Config<ApplicationId> { 43 public class SuppressionConfig extends Config<ApplicationId> {
45 - private static final String DEVICE_IDS = "deviceIds"; 44 +
46 private static final String DEVICE_TYPES = "deviceTypes"; 45 private static final String DEVICE_TYPES = "deviceTypes";
47 private static final String ANNOTATION = "annotation"; 46 private static final String ANNOTATION = "annotation";
48 47
49 private static final ObjectMapper MAPPER = new ObjectMapper(); 48 private static final ObjectMapper MAPPER = new ObjectMapper();
50 - private static final List<DeviceId> DEFAULT_DEVICE_IDS 49 +
51 - = ImmutableList.copyOf(DEFAULT_RULES.getSuppressedDevice());
52 private static final List<Device.Type> DEFAULT_DEVICE_TYPES 50 private static final List<Device.Type> DEFAULT_DEVICE_TYPES
53 = ImmutableList.copyOf(DEFAULT_RULES.getSuppressedDeviceType()); 51 = ImmutableList.copyOf(DEFAULT_RULES.getSuppressedDeviceType());
54 52
55 private final Logger log = getLogger(getClass()); 53 private final Logger log = getLogger(getClass());
56 54
57 /** 55 /**
58 - * Returns device IDs on which LLDP is suppressed. 56 + * Returns types of devices on which LinkDiscovery is suppressed.
59 - *
60 - * @return Set of DeviceId objects
61 - */
62 - @Deprecated
63 - public Set<DeviceId> deviceIds() {
64 - return ImmutableSet.copyOf(getList(DEVICE_IDS, DeviceId::deviceId, DEFAULT_DEVICE_IDS));
65 - }
66 -
67 - /**
68 - * Sets device IDs on which LLDP is suppressed.
69 - *
70 - * @param deviceIds new set of device IDs; null to clear
71 - * @return self
72 - */
73 - @Deprecated
74 - public SuppressionConfig deviceIds(Set<DeviceId> deviceIds) {
75 - return (SuppressionConfig) setOrClear(DEVICE_IDS, deviceIds);
76 - }
77 -
78 - /**
79 - * Returns types of devices on which LLDP is suppressed.
80 * 57 *
81 * @return set of device types 58 * @return set of device types
82 */ 59 */
...@@ -85,7 +62,7 @@ public class SuppressionConfig extends Config<ApplicationId> { ...@@ -85,7 +62,7 @@ public class SuppressionConfig extends Config<ApplicationId> {
85 } 62 }
86 63
87 /** 64 /**
88 - * Sets types of devices on which LLDP is suppressed. 65 + * Sets types of devices on which LinkDiscovery is suppressed.
89 * 66 *
90 * @param deviceTypes new set of device types; null to clear 67 * @param deviceTypes new set of device types; null to clear
91 * @return self 68 * @return self
...@@ -95,7 +72,7 @@ public class SuppressionConfig extends Config<ApplicationId> { ...@@ -95,7 +72,7 @@ public class SuppressionConfig extends Config<ApplicationId> {
95 } 72 }
96 73
97 /** 74 /**
98 - * Returns annotation of Ports on which LLDP is suppressed. 75 + * Returns annotation of Ports on which LinkDiscovery is suppressed.
99 * 76 *
100 * @return key-value pairs of annotation 77 * @return key-value pairs of annotation
101 */ 78 */
...@@ -142,7 +119,7 @@ public class SuppressionConfig extends Config<ApplicationId> { ...@@ -142,7 +119,7 @@ public class SuppressionConfig extends Config<ApplicationId> {
142 } 119 }
143 120
144 /** 121 /**
145 - * Sets annotation of Ports on which LLDP is suppressed. 122 + * Sets annotation of Ports on which LinkDiscovery is suppressed.
146 * 123 *
147 * @param annotation new key-value pair of annotation; null to clear 124 * @param annotation new key-value pair of annotation; null to clear
148 * @return self 125 * @return self
......
...@@ -23,7 +23,6 @@ import java.util.Set; ...@@ -23,7 +23,6 @@ import java.util.Set;
23 23
24 import org.onosproject.net.Annotations; 24 import org.onosproject.net.Annotations;
25 import org.onosproject.net.Device; 25 import org.onosproject.net.Device;
26 -import org.onosproject.net.DeviceId;
27 import org.onosproject.net.Element; 26 import org.onosproject.net.Element;
28 import org.onosproject.net.Port; 27 import org.onosproject.net.Port;
29 28
...@@ -35,23 +34,17 @@ public class SuppressionRules { ...@@ -35,23 +34,17 @@ public class SuppressionRules {
35 34
36 public static final String ANY_VALUE = "(any)"; 35 public static final String ANY_VALUE = "(any)";
37 36
38 - private final Set<DeviceId> suppressedDevice;
39 private final Set<Device.Type> suppressedDeviceType; 37 private final Set<Device.Type> suppressedDeviceType;
40 private final Map<String, String> suppressedAnnotation; 38 private final Map<String, String> suppressedAnnotation;
41 39
42 - public SuppressionRules(Set<DeviceId> suppressedDevice, 40 + public SuppressionRules(Set<Device.Type> suppressedType,
43 - Set<Device.Type> suppressedType, 41 + Map<String, String> suppressedAnnotation) {
44 - Map<String, String> suppressedAnnotation) {
45 42
46 - this.suppressedDevice = ImmutableSet.copyOf(suppressedDevice);
47 this.suppressedDeviceType = ImmutableSet.copyOf(suppressedType); 43 this.suppressedDeviceType = ImmutableSet.copyOf(suppressedType);
48 this.suppressedAnnotation = ImmutableMap.copyOf(suppressedAnnotation); 44 this.suppressedAnnotation = ImmutableMap.copyOf(suppressedAnnotation);
49 } 45 }
50 46
51 public boolean isSuppressed(Device device) { 47 public boolean isSuppressed(Device device) {
52 - if (suppressedDevice.contains(device.id())) {
53 - return true;
54 - }
55 if (suppressedDeviceType.contains(device.type())) { 48 if (suppressedDeviceType.contains(device.type())) {
56 return true; 49 return true;
57 } 50 }
...@@ -94,10 +87,6 @@ public class SuppressionRules { ...@@ -94,10 +87,6 @@ public class SuppressionRules {
94 return false; 87 return false;
95 } 88 }
96 89
97 - Set<DeviceId> getSuppressedDevice() {
98 - return suppressedDevice;
99 - }
100 -
101 Set<Device.Type> getSuppressedDeviceType() { 90 Set<Device.Type> getSuppressedDeviceType() {
102 return suppressedDeviceType; 91 return suppressedDeviceType;
103 } 92 }
...@@ -108,8 +97,7 @@ public class SuppressionRules { ...@@ -108,8 +97,7 @@ public class SuppressionRules {
108 97
109 @Override 98 @Override
110 public int hashCode() { 99 public int hashCode() {
111 - return Objects.hash(suppressedDevice, 100 + return Objects.hash(suppressedDeviceType,
112 - suppressedDeviceType,
113 suppressedAnnotation); 101 suppressedAnnotation);
114 } 102 }
115 103
...@@ -117,9 +105,7 @@ public class SuppressionRules { ...@@ -117,9 +105,7 @@ public class SuppressionRules {
117 public boolean equals(Object object) { 105 public boolean equals(Object object) {
118 if (object != null && getClass() == object.getClass()) { 106 if (object != null && getClass() == object.getClass()) {
119 SuppressionRules that = (SuppressionRules) object; 107 SuppressionRules that = (SuppressionRules) object;
120 - return Objects.equals(this.suppressedDevice, 108 + return Objects.equals(this.suppressedDeviceType,
121 - that.suppressedDevice)
122 - && Objects.equals(this.suppressedDeviceType,
123 that.suppressedDeviceType) 109 that.suppressedDeviceType)
124 && Objects.equals(this.suppressedAnnotation, 110 && Objects.equals(this.suppressedAnnotation,
125 that.suppressedAnnotation); 111 that.suppressedAnnotation);
...@@ -130,7 +116,6 @@ public class SuppressionRules { ...@@ -130,7 +116,6 @@ public class SuppressionRules {
130 @Override 116 @Override
131 public String toString() { 117 public String toString() {
132 return MoreObjects.toStringHelper(this) 118 return MoreObjects.toStringHelper(this)
133 - .add("suppressedDevice", suppressedDevice)
134 .add("suppressedDeviceType", suppressedDeviceType) 119 .add("suppressedDeviceType", suppressedDeviceType)
135 .add("suppressedAnnotation", suppressedAnnotation) 120 .add("suppressedAnnotation", suppressedAnnotation)
136 .toString(); 121 .toString();
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
15 */ 15 */
16 package org.onosproject.provider.lldp.impl; 16 package org.onosproject.provider.lldp.impl;
17 17
18 -import com.fasterxml.jackson.databind.ObjectMapper;
19 import com.google.common.collect.ArrayListMultimap; 18 import com.google.common.collect.ArrayListMultimap;
20 import com.google.common.collect.ImmutableList; 19 import com.google.common.collect.ImmutableList;
21 import com.google.common.collect.ImmutableMap; 20 import com.google.common.collect.ImmutableMap;
...@@ -47,8 +46,8 @@ import org.onosproject.net.MastershipRole; ...@@ -47,8 +46,8 @@ import org.onosproject.net.MastershipRole;
47 import org.onosproject.net.Port; 46 import org.onosproject.net.Port;
48 import org.onosproject.net.PortNumber; 47 import org.onosproject.net.PortNumber;
49 import org.onosproject.net.config.Config; 48 import org.onosproject.net.config.Config;
50 -import org.onosproject.net.config.ConfigApplyDelegate;
51 import org.onosproject.net.config.NetworkConfigEvent; 49 import org.onosproject.net.config.NetworkConfigEvent;
50 +import org.onosproject.net.config.NetworkConfigEvent.Type;
52 import org.onosproject.net.config.NetworkConfigListener; 51 import org.onosproject.net.config.NetworkConfigListener;
53 import org.onosproject.net.config.NetworkConfigRegistryAdapter; 52 import org.onosproject.net.config.NetworkConfigRegistryAdapter;
54 import org.onosproject.net.device.DeviceEvent; 53 import org.onosproject.net.device.DeviceEvent;
...@@ -121,8 +120,14 @@ public class LldpLinkProviderTest { ...@@ -121,8 +120,14 @@ public class LldpLinkProviderTest {
121 120
122 private TestSuppressionConfig cfg; 121 private TestSuppressionConfig cfg;
123 122
123 + private Set<DeviceId> deviceBlacklist;
124 +
125 + private Set<ConnectPoint> portBlacklist;
126 +
124 @Before 127 @Before
125 public void setUp() { 128 public void setUp() {
129 + deviceBlacklist = new HashSet<>();
130 + portBlacklist = new HashSet<>();
126 cfg = new TestSuppressionConfig(); 131 cfg = new TestSuppressionConfig();
127 coreService = createMock(CoreService.class); 132 coreService = createMock(CoreService.class);
128 expect(coreService.registerApplication(appId.name())) 133 expect(coreService.registerApplication(appId.name()))
...@@ -174,7 +179,7 @@ public class LldpLinkProviderTest { ...@@ -174,7 +179,7 @@ public class LldpLinkProviderTest {
174 * Checks that links on a reconfigured switch are properly removed. 179 * Checks that links on a reconfigured switch are properly removed.
175 */ 180 */
176 @Test 181 @Test
177 - public void switchSuppressed() { 182 + public void switchSuppressedByAnnotation() {
178 183
179 // add device to stub DeviceService 184 // add device to stub DeviceService
180 deviceService.putDevice(device(DID3)); 185 deviceService.putDevice(device(DID3));
...@@ -196,6 +201,26 @@ public class LldpLinkProviderTest { ...@@ -196,6 +201,26 @@ public class LldpLinkProviderTest {
196 } 201 }
197 202
198 @Test 203 @Test
204 + public void switchSuppressByBlacklist() {
205 + // add device in stub DeviceService
206 + deviceService.putDevice(device(DID3));
207 + deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
208 +
209 + // add deviveId to device blacklist
210 + deviceBlacklist.add(DID3);
211 + configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
212 + DID3,
213 + LinkDiscoveryFromDevice.class));
214 +
215 + // discovery helper for device is expected to be gone or stopped
216 + LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
217 + if (linkDiscovery != null) {
218 + assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
219 + }
220 +
221 + }
222 +
223 + @Test
199 public void portUp() { 224 public void portUp() {
200 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); 225 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
201 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true))); 226 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
...@@ -269,7 +294,7 @@ public class LldpLinkProviderTest { ...@@ -269,7 +294,7 @@ public class LldpLinkProviderTest {
269 * Checks that discovery on reconfigured switch are properly restarted. 294 * Checks that discovery on reconfigured switch are properly restarted.
270 */ 295 */
271 @Test 296 @Test
272 - public void portSuppressedByDeviceIdConfig() { 297 + public void portSuppressedByParentDeviceIdBlacklist() {
273 298
274 /// When Device is configured without suppression:OFF, 299 /// When Device is configured without suppression:OFF,
275 /// Port should be included for discovery 300 /// Port should be included for discovery
...@@ -288,9 +313,11 @@ public class LldpLinkProviderTest { ...@@ -288,9 +313,11 @@ public class LldpLinkProviderTest {
288 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3)); 313 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
289 314
290 // add suppression rule for "deviceId: "of:0000000000000003"" 315 // add suppression rule for "deviceId: "of:0000000000000003""
291 - provider.updateRules(new SuppressionRules(ImmutableSet.of(DID3), 316 + deviceBlacklist.add(DID3);
292 - ImmutableSet.of(), 317 + configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
293 - ImmutableMap.of())); 318 + DID3,
319 + LinkDiscoveryFromDevice.class));
320 +
294 321
295 /// When Device is reconfigured with suppression:ON, Port also is same 322 /// When Device is reconfigured with suppression:ON, Port also is same
296 323
...@@ -300,7 +327,7 @@ public class LldpLinkProviderTest { ...@@ -300,7 +327,7 @@ public class LldpLinkProviderTest {
300 deviceService.putPorts(DID3, port(DID3, portno3, true)); 327 deviceService.putPorts(DID3, port(DID3, portno3, true));
301 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3)); 328 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
302 329
303 - // discovery on device is expected to be stopped 330 + // discovery helper for device is expected to be gone or stopped
304 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3); 331 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
305 if (linkDiscovery != null) { 332 if (linkDiscovery != null) {
306 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped()); 333 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
...@@ -371,6 +398,34 @@ public class LldpLinkProviderTest { ...@@ -371,6 +398,34 @@ public class LldpLinkProviderTest {
371 } 398 }
372 399
373 @Test 400 @Test
401 + public void portSuppressedByPortBlacklist() {
402 +
403 + // add device in stub DeviceService without suppression configured
404 + deviceService.putDevice(device(DID3));
405 + deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
406 +
407 + final long portno3 = 3L;
408 + final Port port3 = port(DID3, portno3, true);
409 +
410 + final ConnectPoint cpDid3no3 = new ConnectPoint(DID3, PortNumber.portNumber(portno3));
411 + portBlacklist.add(cpDid3no3);
412 +
413 + // suppressed port added to non-suppressed device
414 + deviceService.putPorts(DID3, port3);
415 + deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));
416 +
417 + configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
418 + cpDid3no3,
419 + LinkDiscoveryFromPort.class));
420 +
421 + // discovery helper should be there turned on
422 + assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
423 + // but port is not a discovery target
424 + assertFalse("Discoverer should not contain the port there",
425 + provider.discoverers.get(DID3).containsPort(portno3));
426 + }
427 +
428 + @Test
374 public void portUnknown() { 429 public void portUnknown() {
375 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); 430 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
376 // Note: DID3 hasn't been added to TestDeviceService, but only port is added 431 // Note: DID3 hasn't been added to TestDeviceService, but only port is added
...@@ -481,42 +536,6 @@ public class LldpLinkProviderTest { ...@@ -481,42 +536,6 @@ public class LldpLinkProviderTest {
481 return false; 536 return false;
482 } 537 }
483 538
484 -
485 - @Test
486 - public void addDeviceIdRule() {
487 - DeviceId deviceId1 = DeviceId.deviceId("of:0000000000000001");
488 - DeviceId deviceId2 = DeviceId.deviceId("of:0000000000000002");
489 - Set<DeviceId> deviceIds = new HashSet<>();
490 -
491 - deviceIds.add(deviceId1);
492 - cfg.deviceIds(deviceIds);
493 -
494 - configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
495 -
496 - assertTrue(provider.rules().getSuppressedDevice().contains(deviceId1));
497 - assertFalse(provider.rules().getSuppressedDevice().contains(deviceId2));
498 - }
499 -
500 - @Test
501 - public void updateDeviceIdRule() {
502 - DeviceId deviceId1 = DeviceId.deviceId("of:0000000000000001");
503 - DeviceId deviceId2 = DeviceId.deviceId("of:0000000000000002");
504 - Set<DeviceId> deviceIds = new HashSet<>();
505 -
506 - deviceIds.add(deviceId1);
507 - cfg.deviceIds(deviceIds);
508 -
509 - configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
510 -
511 - deviceIds.add(deviceId2);
512 - cfg.deviceIds(deviceIds);
513 -
514 - configEvent(NetworkConfigEvent.Type.CONFIG_UPDATED);
515 -
516 - assertTrue(provider.rules().getSuppressedDevice().contains(deviceId1));
517 - assertTrue(provider.rules().getSuppressedDevice().contains(deviceId2));
518 - }
519 -
520 @Test 539 @Test
521 public void addDeviceTypeRule() { 540 public void addDeviceTypeRule() {
522 Device.Type deviceType1 = Device.Type.ROADM; 541 Device.Type deviceType1 = Device.Type.ROADM;
...@@ -866,11 +885,28 @@ public class LldpLinkProviderTest { ...@@ -866,11 +885,28 @@ public class LldpLinkProviderTest {
866 885
867 private final class TestNetworkConfigRegistry 886 private final class TestNetworkConfigRegistry
868 extends NetworkConfigRegistryAdapter { 887 extends NetworkConfigRegistryAdapter {
869 - @Override 888 + @SuppressWarnings("unchecked")
870 - public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) { 889 + @Override
871 - ConfigApplyDelegate delegate = config -> { }; 890 + public <S, C extends Config<S>> C getConfig(S subj, Class<C> configClass) {
872 - ObjectMapper mapper = new ObjectMapper(); 891 + if (configClass == SuppressionConfig.class) {
873 - return (C) cfg; 892 + return (C) cfg;
893 + } else if (configClass == LinkDiscoveryFromDevice.class) {
894 + return (C) new LinkDiscoveryFromDevice() {
895 + @Override
896 + public boolean enabled() {
897 + return !deviceBlacklist.contains(subj);
898 + }
899 + };
900 + } else if (configClass == LinkDiscoveryFromPort.class) {
901 + return (C) new LinkDiscoveryFromPort() {
902 + @Override
903 + public boolean enabled() {
904 + return !portBlacklist.contains(subj);
905 + }
906 + };
907 + } else {
908 + return null;
909 + }
874 } 910 }
875 911
876 @Override 912 @Override
...@@ -880,22 +916,10 @@ public class LldpLinkProviderTest { ...@@ -880,22 +916,10 @@ public class LldpLinkProviderTest {
880 } 916 }
881 917
882 private final class TestSuppressionConfig extends SuppressionConfig { 918 private final class TestSuppressionConfig extends SuppressionConfig {
883 - private Set<DeviceId> deviceIds = new HashSet<>(DEFAULT_RULES.getSuppressedDevice());
884 private Set<Device.Type> deviceTypes = new HashSet<>(DEFAULT_RULES.getSuppressedDeviceType()); 919 private Set<Device.Type> deviceTypes = new HashSet<>(DEFAULT_RULES.getSuppressedDeviceType());
885 private Map<String, String> annotation = new HashMap<>(DEFAULT_RULES.getSuppressedAnnotation()); 920 private Map<String, String> annotation = new HashMap<>(DEFAULT_RULES.getSuppressedAnnotation());
886 921
887 @Override 922 @Override
888 - public Set<DeviceId> deviceIds() {
889 - return ImmutableSet.copyOf(deviceIds);
890 - }
891 -
892 - @Override
893 - public SuppressionConfig deviceIds(Set<DeviceId> deviceIds) {
894 - this.deviceIds = ImmutableSet.copyOf(deviceIds);
895 - return this;
896 - }
897 -
898 - @Override
899 public Set<Device.Type> deviceTypes() { 923 public Set<Device.Type> deviceTypes() {
900 return ImmutableSet.copyOf(deviceTypes); 924 return ImmutableSet.copyOf(deviceTypes);
901 } 925 }
......
...@@ -39,21 +39,6 @@ public class SuppressionConfigTest { ...@@ -39,21 +39,6 @@ public class SuppressionConfigTest {
39 } 39 }
40 40
41 @Test 41 @Test
42 - public void testDeviceIds() {
43 - Set<DeviceId> inputIds = new HashSet<DeviceId>() { {
44 - add(DEVICE_ID_1);
45 - add(DEVICE_ID_2);
46 - } };
47 -
48 - assertNotNull(cfg.deviceIds(inputIds));
49 -
50 - Set<DeviceId> outputIds = cfg.deviceIds();
51 - assertTrue(outputIds.contains(DEVICE_ID_1));
52 - assertTrue(outputIds.contains(DEVICE_ID_2));
53 - assertEquals(outputIds.size(), 2);
54 - }
55 -
56 - @Test
57 public void testDeviceTypes() { 42 public void testDeviceTypes() {
58 Set<Device.Type> inputTypes = new HashSet<Device.Type>() { { 43 Set<Device.Type> inputTypes = new HashSet<Device.Type>() { {
59 add(DEVICE_TYPE_1); 44 add(DEVICE_TYPE_1);
......
...@@ -51,22 +51,12 @@ public class SuppressionRulesTest { ...@@ -51,22 +51,12 @@ public class SuppressionRulesTest {
51 51
52 @Before 52 @Before
53 public void setUp() throws Exception { 53 public void setUp() throws Exception {
54 - rules = new SuppressionRules(ImmutableSet.of(SUPPRESSED_DID), 54 + rules = new SuppressionRules(ImmutableSet.of(Device.Type.ROADM),
55 - ImmutableSet.of(Device.Type.ROADM),
56 ImmutableMap.of("no-lldp", SuppressionRules.ANY_VALUE, 55 ImmutableMap.of("no-lldp", SuppressionRules.ANY_VALUE,
57 "sendLLDP", "false")); 56 "sendLLDP", "false"));
58 } 57 }
59 58
60 @Test 59 @Test
61 - public void testSuppressedDeviceId() {
62 - Device device = new DefaultDevice(PID,
63 - SUPPRESSED_DID,
64 - Device.Type.SWITCH,
65 - MFR, HW, SW1, SN, CID);
66 - assertTrue(rules.isSuppressed(device));
67 - }
68 -
69 - @Test
70 public void testSuppressedDeviceType() { 60 public void testSuppressedDeviceType() {
71 Device device = new DefaultDevice(PID, 61 Device device = new DefaultDevice(PID,
72 NON_SUPPRESSED_DID, 62 NON_SUPPRESSED_DID,
...@@ -111,17 +101,6 @@ public class SuppressionRulesTest { ...@@ -111,17 +101,6 @@ public class SuppressionRulesTest {
111 } 101 }
112 102
113 @Test 103 @Test
114 - public void testSuppressedPortOnSuppressedDevice() {
115 - Device device = new DefaultDevice(PID,
116 - SUPPRESSED_DID,
117 - Device.Type.SWITCH,
118 - MFR, HW, SW1, SN, CID);
119 - Port port = new DefaultPort(device, P1, true);
120 -
121 - assertTrue(rules.isSuppressed(port));
122 - }
123 -
124 - @Test
125 public void testSuppressedPortAnnotation() { 104 public void testSuppressedPortAnnotation() {
126 Annotations annotation = DefaultAnnotations.builder() 105 Annotations annotation = DefaultAnnotations.builder()
127 .set("no-lldp", "random") 106 .set("no-lldp", "random")
......
1 +{
2 + "ports": {
3 + "of:0000000000000002/3": {
4 + "linkDiscovery": {
5 + "enabled": false
6 + }
7 + },
8 + "of:0000000000000002/2": {
9 + "linkDiscovery": {
10 + "enabled": false
11 + }
12 + }
13 + },
14 + "devices": {
15 + "of:0000000000000001": {
16 + "linkDiscovery": {
17 + "enabled": false
18 + }
19 + }
20 + },
21 + "apps": {
22 + "org.onosproject.provider.lldp": {
23 + "suppression": {
24 + "deviceTypes": [
25 + "ROADM"
26 + ],
27 + "annotation": {
28 + "no-lldp": null,
29 + "sendLLDP": "false"
30 + }
31 + }
32 + }
33 + }
34 +}
35 +
...@@ -62,12 +62,6 @@ ...@@ -62,12 +62,6 @@
62 ] 62 ]
63 } 63 }
64 } 64 }
65 - "org.onosproject.provider.lldp": {
66 - "suppression": {
67 - "deviceIds": [ "of:2222000000000000" ],
68 - "deviceTypes": [ "ROADM" ],
69 - "annotation": { "no-lldp": null, "sendLLDP" : "false" }
70 - }
71 - }
72 } 65 }
73 } 66 }
67 +
......