Committed by
Yuta Higuchi
Configuration to suppress LLDP discovery
Change-Id: I3b14df6682839f14694b69330a0943facd4f3a6f
Showing
8 changed files
with
613 additions
and
3 deletions
... | @@ -34,6 +34,11 @@ | ... | @@ -34,6 +34,11 @@ |
34 | 34 | ||
35 | <dependencies> | 35 | <dependencies> |
36 | <dependency> | 36 | <dependency> |
37 | + <groupId>org.osgi</groupId> | ||
38 | + <artifactId>org.osgi.compendium</artifactId> | ||
39 | + </dependency> | ||
40 | + | ||
41 | + <dependency> | ||
37 | <groupId>org.onosproject</groupId> | 42 | <groupId>org.onosproject</groupId> |
38 | <artifactId>onos-api</artifactId> | 43 | <artifactId>onos-api</artifactId> |
39 | <classifier>tests</classifier> | 44 | <classifier>tests</classifier> | ... | ... |
... | @@ -18,6 +18,8 @@ package org.onosproject.provider.lldp.impl; | ... | @@ -18,6 +18,8 @@ package org.onosproject.provider.lldp.impl; |
18 | import org.apache.felix.scr.annotations.Activate; | 18 | import org.apache.felix.scr.annotations.Activate; |
19 | import org.apache.felix.scr.annotations.Component; | 19 | import org.apache.felix.scr.annotations.Component; |
20 | import org.apache.felix.scr.annotations.Deactivate; | 20 | import org.apache.felix.scr.annotations.Deactivate; |
21 | +import org.apache.felix.scr.annotations.Modified; | ||
22 | +import org.apache.felix.scr.annotations.Property; | ||
21 | import org.apache.felix.scr.annotations.Reference; | 23 | import org.apache.felix.scr.annotations.Reference; |
22 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 24 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
23 | import org.onosproject.mastership.MastershipEvent; | 25 | import org.onosproject.mastership.MastershipEvent; |
... | @@ -38,8 +40,16 @@ import org.onosproject.net.packet.PacketProcessor; | ... | @@ -38,8 +40,16 @@ import org.onosproject.net.packet.PacketProcessor; |
38 | import org.onosproject.net.packet.PacketService; | 40 | import org.onosproject.net.packet.PacketService; |
39 | import org.onosproject.net.provider.AbstractProvider; | 41 | import org.onosproject.net.provider.AbstractProvider; |
40 | import org.onosproject.net.provider.ProviderId; | 42 | import org.onosproject.net.provider.ProviderId; |
43 | +import org.osgi.service.component.ComponentContext; | ||
41 | import org.slf4j.Logger; | 44 | import org.slf4j.Logger; |
42 | 45 | ||
46 | +import com.google.common.base.Strings; | ||
47 | +import com.google.common.collect.ImmutableMap; | ||
48 | +import com.google.common.collect.ImmutableSet; | ||
49 | + | ||
50 | +import java.io.IOException; | ||
51 | +import java.util.Dictionary; | ||
52 | +import java.util.EnumSet; | ||
43 | import java.util.Map; | 53 | import java.util.Map; |
44 | import java.util.concurrent.ConcurrentHashMap; | 54 | import java.util.concurrent.ConcurrentHashMap; |
45 | import java.util.concurrent.ScheduledExecutorService; | 55 | import java.util.concurrent.ScheduledExecutorService; |
... | @@ -57,6 +67,13 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -57,6 +67,13 @@ import static org.slf4j.LoggerFactory.getLogger; |
57 | @Component(immediate = true) | 67 | @Component(immediate = true) |
58 | public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | 68 | public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
59 | 69 | ||
70 | + | ||
71 | + private static final String PROP_USE_BDDP = "useBDDP"; | ||
72 | + | ||
73 | + private static final String PROP_LLDP_SUPPRESSION = "lldpSuppression"; | ||
74 | + | ||
75 | + private static final String DEFAULT_LLDP_SUPPRESSION_CONFIG = "../config/lldp_suppression.json"; | ||
76 | + | ||
60 | private final Logger log = getLogger(getClass()); | 77 | private final Logger log = getLogger(getClass()); |
61 | 78 | ||
62 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 79 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
... | @@ -75,17 +92,26 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -75,17 +92,26 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
75 | 92 | ||
76 | private ScheduledExecutorService executor; | 93 | private ScheduledExecutorService executor; |
77 | 94 | ||
78 | - private final boolean useBDDP = true; | 95 | + @Property(name = PROP_USE_BDDP, boolValue = true, |
96 | + label = "use BDDP for link discovery") | ||
97 | + private boolean useBDDP = true; | ||
79 | 98 | ||
80 | private static final long INIT_DELAY = 5; | 99 | private static final long INIT_DELAY = 5; |
81 | private static final long DELAY = 5; | 100 | private static final long DELAY = 5; |
82 | 101 | ||
102 | + @Property(name = PROP_LLDP_SUPPRESSION, value = DEFAULT_LLDP_SUPPRESSION_CONFIG, | ||
103 | + label = "Path to LLDP suppression configuration file") | ||
104 | + private String filePath = DEFAULT_LLDP_SUPPRESSION_CONFIG; | ||
105 | + | ||
106 | + | ||
83 | private final InternalLinkProvider listener = new InternalLinkProvider(); | 107 | private final InternalLinkProvider listener = new InternalLinkProvider(); |
84 | 108 | ||
85 | private final InternalRoleListener roleListener = new InternalRoleListener(); | 109 | private final InternalRoleListener roleListener = new InternalRoleListener(); |
86 | 110 | ||
87 | protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>(); | 111 | protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>(); |
88 | 112 | ||
113 | + private SuppressionRules rules; | ||
114 | + | ||
89 | /** | 115 | /** |
90 | * Creates an OpenFlow link provider. | 116 | * Creates an OpenFlow link provider. |
91 | */ | 117 | */ |
... | @@ -95,6 +121,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -95,6 +121,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
95 | 121 | ||
96 | @Activate | 122 | @Activate |
97 | public void activate() { | 123 | public void activate() { |
124 | + loadSuppressionRules(); | ||
125 | + | ||
98 | providerService = providerRegistry.register(this); | 126 | providerService = providerRegistry.register(this); |
99 | deviceService.addListener(listener); | 127 | deviceService.addListener(listener); |
100 | packetSevice.addProcessor(listener, 0); | 128 | packetSevice.addProcessor(listener, 0); |
... | @@ -102,10 +130,19 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -102,10 +130,19 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
102 | 130 | ||
103 | LinkDiscovery ld; | 131 | LinkDiscovery ld; |
104 | for (Device device : deviceService.getAvailableDevices()) { | 132 | for (Device device : deviceService.getAvailableDevices()) { |
133 | + if (rules.isSuppressed(device)) { | ||
134 | + log.debug("LinkDiscovery from {} disabled by configuration", device.id()); | ||
135 | + continue; | ||
136 | + } | ||
105 | ld = new LinkDiscovery(device, packetSevice, masterService, | 137 | ld = new LinkDiscovery(device, packetSevice, masterService, |
106 | providerService, useBDDP); | 138 | providerService, useBDDP); |
107 | discoverers.put(device.id(), ld); | 139 | discoverers.put(device.id(), ld); |
108 | for (Port p : deviceService.getPorts(device.id())) { | 140 | for (Port p : deviceService.getPorts(device.id())) { |
141 | + if (rules.isSuppressed(p)) { | ||
142 | + log.debug("LinkDiscovery from {}@{} disabled by configuration", | ||
143 | + p.number(), device.id()); | ||
144 | + continue; | ||
145 | + } | ||
109 | if (!p.number().isLogical()) { | 146 | if (!p.number().isLogical()) { |
110 | ld.addPort(p); | 147 | ld.addPort(p); |
111 | } | 148 | } |
... | @@ -134,6 +171,45 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -134,6 +171,45 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
134 | log.info("Stopped"); | 171 | log.info("Stopped"); |
135 | } | 172 | } |
136 | 173 | ||
174 | + @Modified | ||
175 | + public void modified(ComponentContext context) { | ||
176 | + if (context == null) { | ||
177 | + return; | ||
178 | + } | ||
179 | + @SuppressWarnings("rawtypes") | ||
180 | + Dictionary properties = context.getProperties(); | ||
181 | + | ||
182 | + String s = (String) properties.get(PROP_USE_BDDP); | ||
183 | + if (Strings.isNullOrEmpty(s)) { | ||
184 | + useBDDP = true; | ||
185 | + } else { | ||
186 | + useBDDP = Boolean.valueOf(s); | ||
187 | + } | ||
188 | + s = (String) properties.get(PROP_LLDP_SUPPRESSION); | ||
189 | + if (Strings.isNullOrEmpty(s)) { | ||
190 | + filePath = DEFAULT_LLDP_SUPPRESSION_CONFIG; | ||
191 | + } else { | ||
192 | + filePath = s; | ||
193 | + } | ||
194 | + | ||
195 | + loadSuppressionRules(); | ||
196 | + } | ||
197 | + | ||
198 | + private void loadSuppressionRules() { | ||
199 | + SuppressionRulesStore store = new SuppressionRulesStore(filePath); | ||
200 | + try { | ||
201 | + rules = store.read(); | ||
202 | + } catch (IOException e) { | ||
203 | + log.info("Failed to load {}, using built-in rules", filePath); | ||
204 | + // default rule to suppress ROADM to maintain compatibility | ||
205 | + rules = new SuppressionRules(ImmutableSet.of(), | ||
206 | + EnumSet.of(Device.Type.ROADM), | ||
207 | + ImmutableMap.of()); | ||
208 | + } | ||
209 | + | ||
210 | + // should refresh discoverers when we need dynamic reconfiguration | ||
211 | + } | ||
212 | + | ||
137 | private class InternalRoleListener implements MastershipListener { | 213 | private class InternalRoleListener implements MastershipListener { |
138 | 214 | ||
139 | @Override | 215 | @Override |
... | @@ -150,6 +226,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -150,6 +226,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
150 | log.warn("Device {} doesn't exist, or isn't there yet", deviceId); | 226 | log.warn("Device {} doesn't exist, or isn't there yet", deviceId); |
151 | return; | 227 | return; |
152 | } | 228 | } |
229 | + if (rules.isSuppressed(device)) { | ||
230 | + return; | ||
231 | + } | ||
153 | synchronized (discoverers) { | 232 | synchronized (discoverers) { |
154 | if (!discoverers.containsKey(deviceId)) { | 233 | if (!discoverers.containsKey(deviceId)) { |
155 | // ideally, should never reach here | 234 | // ideally, should never reach here |
... | @@ -183,6 +262,10 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -183,6 +262,10 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
183 | synchronized (discoverers) { | 262 | synchronized (discoverers) { |
184 | ld = discoverers.get(deviceId); | 263 | ld = discoverers.get(deviceId); |
185 | if (ld == null) { | 264 | if (ld == null) { |
265 | + if (rules.isSuppressed(device)) { | ||
266 | + log.debug("LinkDiscovery from {} disabled by configuration", device.id()); | ||
267 | + return; | ||
268 | + } | ||
186 | log.debug("Device added ({}) {}", event.type(), | 269 | log.debug("Device added ({}) {}", event.type(), |
187 | deviceId); | 270 | deviceId); |
188 | discoverers.put(deviceId, new LinkDiscovery(device, | 271 | discoverers.put(deviceId, new LinkDiscovery(device, |
... | @@ -204,6 +287,11 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -204,6 +287,11 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
204 | if (ld == null) { | 287 | if (ld == null) { |
205 | return; | 288 | return; |
206 | } | 289 | } |
290 | + if (rules.isSuppressed(port)) { | ||
291 | + log.debug("LinkDiscovery from {}@{} disabled by configuration", | ||
292 | + port.number(), device.id()); | ||
293 | + return; | ||
294 | + } | ||
207 | if (!port.number().isLogical()) { | 295 | if (!port.number().isLogical()) { |
208 | log.debug("Port added {}", port); | 296 | log.debug("Port added {}", port); |
209 | ld.addPort(port); | 297 | ld.addPort(port); |
... | @@ -280,6 +368,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -280,6 +368,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
280 | try { | 368 | try { |
281 | LinkDiscovery ld = null; | 369 | LinkDiscovery ld = null; |
282 | for (Device dev : deviceService.getDevices()) { | 370 | for (Device dev : deviceService.getDevices()) { |
371 | + if (rules.isSuppressed(dev)) { | ||
372 | + continue; | ||
373 | + } | ||
283 | DeviceId did = dev.id(); | 374 | DeviceId did = dev.id(); |
284 | synchronized (discoverers) { | 375 | synchronized (discoverers) { |
285 | if (!discoverers.containsKey(did)) { | 376 | if (!discoverers.containsKey(did)) { |
... | @@ -287,6 +378,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -287,6 +378,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
287 | masterService, providerService, useBDDP); | 378 | masterService, providerService, useBDDP); |
288 | discoverers.put(did, ld); | 379 | discoverers.put(did, ld); |
289 | for (Port p : deviceService.getPorts(did)) { | 380 | for (Port p : deviceService.getPorts(did)) { |
381 | + if (rules.isSuppressed(p)) { | ||
382 | + continue; | ||
383 | + } | ||
290 | if (!p.number().isLogical()) { | 384 | if (!p.number().isLogical()) { |
291 | ld.addPort(p); | 385 | ld.addPort(p); |
292 | } | 386 | } | ... | ... |
... | @@ -344,7 +344,6 @@ public class LinkDiscovery implements TimerTask { | ... | @@ -344,7 +344,6 @@ public class LinkDiscovery implements TimerTask { |
344 | } | 344 | } |
345 | 345 | ||
346 | private void sendProbes(Long portNumber) { | 346 | private void sendProbes(Long portNumber) { |
347 | - if (device.type() != Device.Type.ROADM) { | ||
348 | log.trace("Sending probes out to {}@{}", portNumber, device.id()); | 347 | log.trace("Sending probes out to {}@{}", portNumber, device.id()); |
349 | OutboundPacket pkt = this.createOutBoundLLDP(portNumber); | 348 | OutboundPacket pkt = this.createOutBoundLLDP(portNumber); |
350 | pktService.emit(pkt); | 349 | pktService.emit(pkt); |
... | @@ -353,7 +352,6 @@ public class LinkDiscovery implements TimerTask { | ... | @@ -353,7 +352,6 @@ public class LinkDiscovery implements TimerTask { |
353 | pktService.emit(bpkt); | 352 | pktService.emit(bpkt); |
354 | } | 353 | } |
355 | } | 354 | } |
356 | - } | ||
357 | 355 | ||
358 | public boolean containsPort(Long portNumber) { | 356 | public boolean containsPort(Long portNumber) { |
359 | return slowPorts.contains(portNumber) || fastPorts.contains(portNumber); | 357 | return slowPorts.contains(portNumber) || fastPorts.contains(portNumber); | ... | ... |
1 | +/* | ||
2 | + * Copyright 2014 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 | + | ||
17 | +package org.onosproject.provider.lldp.impl; | ||
18 | + | ||
19 | +import java.util.Map; | ||
20 | +import java.util.Map.Entry; | ||
21 | +import java.util.Set; | ||
22 | + | ||
23 | +import org.onosproject.net.Annotations; | ||
24 | +import org.onosproject.net.Device; | ||
25 | +import org.onosproject.net.DeviceId; | ||
26 | +import org.onosproject.net.Element; | ||
27 | +import org.onosproject.net.Port; | ||
28 | + | ||
29 | +import com.google.common.collect.ImmutableMap; | ||
30 | +import com.google.common.collect.ImmutableSet; | ||
31 | + | ||
32 | +public class SuppressionRules { | ||
33 | + | ||
34 | + public static final String ANY_VALUE = "(any)"; | ||
35 | + | ||
36 | + private final Set<DeviceId> suppressedDevice; | ||
37 | + private final Set<Device.Type> suppressedDeviceType; | ||
38 | + private final Map<String, String> suppressedAnnotation; | ||
39 | + | ||
40 | + public SuppressionRules(Set<DeviceId> suppressedDevice, | ||
41 | + Set<Device.Type> suppressedType, | ||
42 | + Map<String, String> suppressedAnnotation) { | ||
43 | + | ||
44 | + this.suppressedDevice = ImmutableSet.copyOf(suppressedDevice); | ||
45 | + this.suppressedDeviceType = ImmutableSet.copyOf(suppressedType); | ||
46 | + this.suppressedAnnotation = ImmutableMap.copyOf(suppressedAnnotation); | ||
47 | + } | ||
48 | + | ||
49 | + public boolean isSuppressed(Device device) { | ||
50 | + if (suppressedDevice.contains(device.id())) { | ||
51 | + return true; | ||
52 | + } | ||
53 | + if (suppressedDeviceType.contains(device.type())) { | ||
54 | + return true; | ||
55 | + } | ||
56 | + final Annotations annotations = device.annotations(); | ||
57 | + if (containsSuppressionAnnotation(annotations)) { | ||
58 | + return true; | ||
59 | + } | ||
60 | + return false; | ||
61 | + } | ||
62 | + | ||
63 | + public boolean isSuppressed(Port port) { | ||
64 | + Element parent = port.element(); | ||
65 | + if (parent instanceof Device) { | ||
66 | + if (isSuppressed((Device) parent)) { | ||
67 | + return true; | ||
68 | + } | ||
69 | + } | ||
70 | + | ||
71 | + final Annotations annotations = port.annotations(); | ||
72 | + if (containsSuppressionAnnotation(annotations)) { | ||
73 | + return true; | ||
74 | + } | ||
75 | + return false; | ||
76 | + } | ||
77 | + | ||
78 | + private boolean containsSuppressionAnnotation(final Annotations annotations) { | ||
79 | + for (Entry<String, String> entry : suppressedAnnotation.entrySet()) { | ||
80 | + final String suppValue = entry.getValue(); | ||
81 | + final String suppKey = entry.getKey(); | ||
82 | + if (suppValue == ANY_VALUE) { | ||
83 | + if (annotations.keys().contains(suppKey)) { | ||
84 | + return true; | ||
85 | + } | ||
86 | + } else { | ||
87 | + if (suppValue.equals(annotations.value(suppKey))) { | ||
88 | + return true; | ||
89 | + } | ||
90 | + } | ||
91 | + } | ||
92 | + return false; | ||
93 | + } | ||
94 | + | ||
95 | + Set<DeviceId> getSuppressedDevice() { | ||
96 | + return suppressedDevice; | ||
97 | + } | ||
98 | + | ||
99 | + Set<Device.Type> getSuppressedDeviceType() { | ||
100 | + return suppressedDeviceType; | ||
101 | + } | ||
102 | + | ||
103 | + Map<String, String> getSuppressedAnnotation() { | ||
104 | + return suppressedAnnotation; | ||
105 | + } | ||
106 | +} |
providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/SuppressionRulesStore.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2014 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 static com.google.common.base.Preconditions.checkNotNull; | ||
19 | +import static org.slf4j.LoggerFactory.getLogger; | ||
20 | + | ||
21 | +import com.fasterxml.jackson.core.JsonEncoding; | ||
22 | +import com.fasterxml.jackson.core.JsonFactory; | ||
23 | +import com.fasterxml.jackson.databind.JsonNode; | ||
24 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
25 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
26 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
27 | + | ||
28 | +import org.onosproject.net.Device; | ||
29 | +import org.onosproject.net.DeviceId; | ||
30 | +import org.slf4j.Logger; | ||
31 | + | ||
32 | +import java.io.File; | ||
33 | +import java.io.IOException; | ||
34 | +import java.util.EnumSet; | ||
35 | +import java.util.HashMap; | ||
36 | +import java.util.HashSet; | ||
37 | +import java.util.Iterator; | ||
38 | +import java.util.Map; | ||
39 | +import java.util.Map.Entry; | ||
40 | +import java.util.Set; | ||
41 | + | ||
42 | +/* | ||
43 | + * JSON file example | ||
44 | + * | ||
45 | + | ||
46 | +{ | ||
47 | + "deviceId" : [ "of:2222000000000000" ], | ||
48 | + "deviceType" : [ "ROADM" ], | ||
49 | + "annotation" : { "no-lldp" : null, "sendLLDP" : "false" } | ||
50 | +} | ||
51 | + */ | ||
52 | + | ||
53 | +/** | ||
54 | + * Allows for reading and writing LLDP suppression definition as a JSON file. | ||
55 | + */ | ||
56 | +public class SuppressionRulesStore { | ||
57 | + | ||
58 | + private static final String DEVICE_ID = "deviceId"; | ||
59 | + private static final String DEVICE_TYPE = "deviceType"; | ||
60 | + private static final String ANNOTATION = "annotation"; | ||
61 | + | ||
62 | + private final Logger log = getLogger(getClass()); | ||
63 | + | ||
64 | + private final File file; | ||
65 | + | ||
66 | + /** | ||
67 | + * Creates a reader/writer of the LLDP suppression definition file. | ||
68 | + * | ||
69 | + * @param filePath location of the definition file | ||
70 | + */ | ||
71 | + public SuppressionRulesStore(String filePath) { | ||
72 | + file = new File(filePath); | ||
73 | + } | ||
74 | + | ||
75 | + /** | ||
76 | + * Creates a reader/writer of the LLDP suppression definition file. | ||
77 | + * | ||
78 | + * @param file definition file | ||
79 | + */ | ||
80 | + public SuppressionRulesStore(File file) { | ||
81 | + this.file = checkNotNull(file); | ||
82 | + } | ||
83 | + | ||
84 | + /** | ||
85 | + * Returns SuppressionRules. | ||
86 | + * | ||
87 | + * @return SuppressionRules | ||
88 | + * @throws IOException | ||
89 | + */ | ||
90 | + public SuppressionRules read() throws IOException { | ||
91 | + final Set<DeviceId> suppressedDevice = new HashSet<>(); | ||
92 | + final EnumSet<Device.Type> suppressedDeviceType = EnumSet.noneOf(Device.Type.class); | ||
93 | + final Map<String, String> suppressedAnnotation = new HashMap<>(); | ||
94 | + | ||
95 | + ObjectMapper mapper = new ObjectMapper(); | ||
96 | + ObjectNode root = (ObjectNode) mapper.readTree(file); | ||
97 | + | ||
98 | + for (JsonNode deviceId : root.get(DEVICE_ID)) { | ||
99 | + if (deviceId.isTextual()) { | ||
100 | + suppressedDevice.add(DeviceId.deviceId(deviceId.asText())); | ||
101 | + } else { | ||
102 | + log.warn("Encountered unexpected JSONNode {} for deviceId", deviceId); | ||
103 | + } | ||
104 | + } | ||
105 | + | ||
106 | + for (JsonNode deviceType : root.get(DEVICE_TYPE)) { | ||
107 | + if (deviceType.isTextual()) { | ||
108 | + suppressedDeviceType.add(Device.Type.valueOf(deviceType.asText())); | ||
109 | + } else { | ||
110 | + log.warn("Encountered unexpected JSONNode {} for deviceType", deviceType); | ||
111 | + } | ||
112 | + } | ||
113 | + | ||
114 | + JsonNode annotation = root.get(ANNOTATION); | ||
115 | + if (annotation.isObject()) { | ||
116 | + ObjectNode obj = (ObjectNode) annotation; | ||
117 | + Iterator<Entry<String, JsonNode>> it = obj.fields(); | ||
118 | + while (it.hasNext()) { | ||
119 | + Entry<String, JsonNode> entry = it.next(); | ||
120 | + final String key = entry.getKey(); | ||
121 | + final JsonNode value = entry.getValue(); | ||
122 | + | ||
123 | + if (value.isValueNode()) { | ||
124 | + if (value.isNull()) { | ||
125 | + suppressedAnnotation.put(key, SuppressionRules.ANY_VALUE); | ||
126 | + } else { | ||
127 | + suppressedAnnotation.put(key, value.asText()); | ||
128 | + } | ||
129 | + } else { | ||
130 | + log.warn("Encountered unexpected JSON field {} for annotation", entry); | ||
131 | + } | ||
132 | + } | ||
133 | + } else { | ||
134 | + log.warn("Encountered unexpected JSONNode {} for annotation", annotation); | ||
135 | + } | ||
136 | + | ||
137 | + return new SuppressionRules(suppressedDevice, | ||
138 | + suppressedDeviceType, | ||
139 | + suppressedAnnotation); | ||
140 | + } | ||
141 | + | ||
142 | + /** | ||
143 | + * Writes the given SuppressionRules. | ||
144 | + * | ||
145 | + * @param rules SuppressionRules | ||
146 | + * @throws IOException | ||
147 | + */ | ||
148 | + public void write(SuppressionRules rules) throws IOException { | ||
149 | + ObjectMapper mapper = new ObjectMapper(); | ||
150 | + ObjectNode root = mapper.createObjectNode(); | ||
151 | + ArrayNode deviceIds = mapper.createArrayNode(); | ||
152 | + ArrayNode deviceTypes = mapper.createArrayNode(); | ||
153 | + ObjectNode annotations = mapper.createObjectNode(); | ||
154 | + root.set(DEVICE_ID, deviceIds); | ||
155 | + root.set(DEVICE_TYPE, deviceTypes); | ||
156 | + root.set(ANNOTATION, annotations); | ||
157 | + | ||
158 | + rules.getSuppressedDevice() | ||
159 | + .forEach(deviceId -> deviceIds.add(deviceId.toString())); | ||
160 | + | ||
161 | + rules.getSuppressedDeviceType() | ||
162 | + .forEach(type -> deviceTypes.add(type.toString())); | ||
163 | + | ||
164 | + rules.getSuppressedAnnotation().forEach((key, value) -> { | ||
165 | + if (value == SuppressionRules.ANY_VALUE) { | ||
166 | + annotations.putNull(key); | ||
167 | + } else { | ||
168 | + annotations.put(key, value); | ||
169 | + } | ||
170 | + }); | ||
171 | + mapper.writeTree(new JsonFactory().createGenerator(file, JsonEncoding.UTF8), | ||
172 | + root); | ||
173 | + } | ||
174 | +} |
providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/SuppressionRulesStoreTest.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2014 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 | + | ||
17 | +package org.onosproject.provider.lldp.impl; | ||
18 | + | ||
19 | +import static org.junit.Assert.*; | ||
20 | +import static org.onosproject.net.DeviceId.deviceId; | ||
21 | + | ||
22 | +import java.io.File; | ||
23 | +import java.io.IOException; | ||
24 | +import java.net.URISyntaxException; | ||
25 | +import java.nio.file.Path; | ||
26 | +import java.nio.file.Paths; | ||
27 | + | ||
28 | +import org.junit.Rule; | ||
29 | +import org.junit.Test; | ||
30 | +import org.junit.rules.TemporaryFolder; | ||
31 | +import org.onosproject.net.Device; | ||
32 | + | ||
33 | +import com.google.common.collect.ImmutableMap; | ||
34 | +import com.google.common.collect.ImmutableSet; | ||
35 | +import com.google.common.io.Resources; | ||
36 | + | ||
37 | +public class SuppressionRulesStoreTest { | ||
38 | + | ||
39 | + @Rule | ||
40 | + public TemporaryFolder tempFolder = new TemporaryFolder(); | ||
41 | + | ||
42 | + // "lldp_suppression.json" | ||
43 | + SuppressionRules testData | ||
44 | + = new SuppressionRules(ImmutableSet.of(deviceId("of:2222000000000000")), | ||
45 | + ImmutableSet.of(Device.Type.ROADM), | ||
46 | + ImmutableMap.of("no-lldp", SuppressionRules.ANY_VALUE, | ||
47 | + "sendLLDP", "false")); | ||
48 | + | ||
49 | + private static void assertRulesEqual(SuppressionRules expected, SuppressionRules actual) { | ||
50 | + assertEquals(expected.getSuppressedDevice(), | ||
51 | + actual.getSuppressedDevice()); | ||
52 | + assertEquals(expected.getSuppressedDeviceType(), | ||
53 | + actual.getSuppressedDeviceType()); | ||
54 | + assertEquals(expected.getSuppressedAnnotation(), | ||
55 | + actual.getSuppressedAnnotation()); | ||
56 | + } | ||
57 | + | ||
58 | + @Test | ||
59 | + public void testRead() throws URISyntaxException, IOException { | ||
60 | + Path path = Paths.get(Resources.getResource("lldp_suppression.json").toURI()); | ||
61 | + | ||
62 | + SuppressionRulesStore store = new SuppressionRulesStore(path.toString()); | ||
63 | + | ||
64 | + SuppressionRules rules = store.read(); | ||
65 | + | ||
66 | + assertRulesEqual(testData, rules); | ||
67 | + } | ||
68 | + | ||
69 | + @Test | ||
70 | + public void testWrite() throws IOException { | ||
71 | + File newFile = tempFolder.newFile(); | ||
72 | + SuppressionRulesStore store = new SuppressionRulesStore(newFile); | ||
73 | + store.write(testData); | ||
74 | + | ||
75 | + SuppressionRulesStore reload = new SuppressionRulesStore(newFile); | ||
76 | + SuppressionRules rules = reload.read(); | ||
77 | + | ||
78 | + assertRulesEqual(testData, rules); | ||
79 | + } | ||
80 | +} |
providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/SuppressionRulesTest.java
0 → 100644
1 | +package org.onosproject.provider.lldp.impl; | ||
2 | + | ||
3 | +import static org.junit.Assert.*; | ||
4 | +import static org.onosproject.net.DeviceId.deviceId; | ||
5 | + | ||
6 | +import org.junit.Before; | ||
7 | +import org.junit.Test; | ||
8 | +import org.onlab.packet.ChassisId; | ||
9 | +import org.onosproject.net.Annotations; | ||
10 | +import org.onosproject.net.DefaultAnnotations; | ||
11 | +import org.onosproject.net.DefaultDevice; | ||
12 | +import org.onosproject.net.DefaultPort; | ||
13 | +import org.onosproject.net.Device; | ||
14 | +import org.onosproject.net.DeviceId; | ||
15 | +import org.onosproject.net.Port; | ||
16 | +import org.onosproject.net.PortNumber; | ||
17 | +import org.onosproject.net.provider.ProviderId; | ||
18 | + | ||
19 | +import com.google.common.collect.ImmutableMap; | ||
20 | +import com.google.common.collect.ImmutableSet; | ||
21 | + | ||
22 | +public class SuppressionRulesTest { | ||
23 | + | ||
24 | + private static final DeviceId NON_SUPPRESSED_DID = deviceId("of:1111000000000000"); | ||
25 | + private static final DeviceId SUPPRESSED_DID = deviceId("of:2222000000000000"); | ||
26 | + private static final ProviderId PID = new ProviderId("of", "foo"); | ||
27 | + private static final String MFR = "whitebox"; | ||
28 | + private static final String HW = "1.1.x"; | ||
29 | + private static final String SW1 = "3.8.1"; | ||
30 | + private static final String SN = "43311-12345"; | ||
31 | + private static final ChassisId CID = new ChassisId(); | ||
32 | + | ||
33 | + private static final PortNumber P1 = PortNumber.portNumber(1); | ||
34 | + | ||
35 | + private SuppressionRules rules; | ||
36 | + | ||
37 | + @Before | ||
38 | + public void setUp() throws Exception { | ||
39 | + rules = new SuppressionRules(ImmutableSet.of(SUPPRESSED_DID), | ||
40 | + ImmutableSet.of(Device.Type.ROADM), | ||
41 | + ImmutableMap.of("no-lldp", SuppressionRules.ANY_VALUE, | ||
42 | + "sendLLDP", "false")); | ||
43 | + } | ||
44 | + | ||
45 | + @Test | ||
46 | + public void testSuppressedDeviceId() { | ||
47 | + Device device = new DefaultDevice(PID, | ||
48 | + SUPPRESSED_DID, | ||
49 | + Device.Type.SWITCH, | ||
50 | + MFR, HW, SW1, SN, CID); | ||
51 | + assertTrue(rules.isSuppressed(device)); | ||
52 | + } | ||
53 | + | ||
54 | + @Test | ||
55 | + public void testSuppressedDeviceType() { | ||
56 | + Device device = new DefaultDevice(PID, | ||
57 | + NON_SUPPRESSED_DID, | ||
58 | + Device.Type.ROADM, | ||
59 | + MFR, HW, SW1, SN, CID); | ||
60 | + assertTrue(rules.isSuppressed(device)); | ||
61 | + } | ||
62 | + | ||
63 | + @Test | ||
64 | + public void testSuppressedDeviceAnnotation() { | ||
65 | + Annotations annotation = DefaultAnnotations.builder() | ||
66 | + .set("no-lldp", "random") | ||
67 | + .build(); | ||
68 | + | ||
69 | + Device device = new DefaultDevice(PID, | ||
70 | + NON_SUPPRESSED_DID, | ||
71 | + Device.Type.SWITCH, | ||
72 | + MFR, HW, SW1, SN, CID, annotation); | ||
73 | + assertTrue(rules.isSuppressed(device)); | ||
74 | + } | ||
75 | + | ||
76 | + @Test | ||
77 | + public void testSuppressedDeviceAnnotationExact() { | ||
78 | + Annotations annotation = DefaultAnnotations.builder() | ||
79 | + .set("sendLLDP", "false") | ||
80 | + .build(); | ||
81 | + | ||
82 | + Device device = new DefaultDevice(PID, | ||
83 | + NON_SUPPRESSED_DID, | ||
84 | + Device.Type.SWITCH, | ||
85 | + MFR, HW, SW1, SN, CID, annotation); | ||
86 | + assertTrue(rules.isSuppressed(device)); | ||
87 | + } | ||
88 | + | ||
89 | + @Test | ||
90 | + public void testNotSuppressedDevice() { | ||
91 | + Device device = new DefaultDevice(PID, | ||
92 | + NON_SUPPRESSED_DID, | ||
93 | + Device.Type.SWITCH, | ||
94 | + MFR, HW, SW1, SN, CID); | ||
95 | + assertFalse(rules.isSuppressed(device)); | ||
96 | + } | ||
97 | + | ||
98 | + @Test | ||
99 | + public void testSuppressedPortOnSuppressedDevice() { | ||
100 | + Device device = new DefaultDevice(PID, | ||
101 | + SUPPRESSED_DID, | ||
102 | + Device.Type.SWITCH, | ||
103 | + MFR, HW, SW1, SN, CID); | ||
104 | + Port port = new DefaultPort(device, P1, true); | ||
105 | + | ||
106 | + assertTrue(rules.isSuppressed(port)); | ||
107 | + } | ||
108 | + | ||
109 | + @Test | ||
110 | + public void testSuppressedPortAnnotation() { | ||
111 | + Annotations annotation = DefaultAnnotations.builder() | ||
112 | + .set("no-lldp", "random") | ||
113 | + .build(); | ||
114 | + Device device = new DefaultDevice(PID, | ||
115 | + NON_SUPPRESSED_DID, | ||
116 | + Device.Type.SWITCH, | ||
117 | + MFR, HW, SW1, SN, CID); | ||
118 | + Port port = new DefaultPort(device, P1, true, annotation); | ||
119 | + | ||
120 | + assertTrue(rules.isSuppressed(port)); | ||
121 | + } | ||
122 | + | ||
123 | + @Test | ||
124 | + public void testSuppressedPortAnnotationExact() { | ||
125 | + Annotations annotation = DefaultAnnotations.builder() | ||
126 | + .set("sendLLDP", "false") | ||
127 | + .build(); | ||
128 | + Device device = new DefaultDevice(PID, | ||
129 | + NON_SUPPRESSED_DID, | ||
130 | + Device.Type.SWITCH, | ||
131 | + MFR, HW, SW1, SN, CID); | ||
132 | + Port port = new DefaultPort(device, P1, true, annotation); | ||
133 | + | ||
134 | + assertTrue(rules.isSuppressed(port)); | ||
135 | + } | ||
136 | + | ||
137 | + @Test | ||
138 | + public void testNotSuppressedPort() { | ||
139 | + Device device = new DefaultDevice(PID, | ||
140 | + NON_SUPPRESSED_DID, | ||
141 | + Device.Type.SWITCH, | ||
142 | + MFR, HW, SW1, SN, CID); | ||
143 | + Port port = new DefaultPort(device, P1, true); | ||
144 | + | ||
145 | + assertFalse(rules.isSuppressed(port)); | ||
146 | + } | ||
147 | +} |
-
Please register or login to post a comment