blob: 6ff437a5402b646112cd86915ed0cd3492711878 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.lldp.impl;
alshabib7911a052014-10-16 17:49:37 -070017
Marc De Leenheer0bfc2a12016-02-02 22:46:27 -080018import com.google.common.collect.ImmutableMap;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Maps;
alshabib7911a052014-10-16 17:49:37 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
Yuta HIGUCHI41289382014-12-19 17:47:12 -080024import org.apache.felix.scr.annotations.Modified;
25import org.apache.felix.scr.annotations.Property;
alshabib7911a052014-10-16 17:49:37 -070026import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080028import org.onlab.packet.Ethernet;
Thomas Vachuska7a815ac2016-03-01 23:58:15 -080029import org.onlab.util.SharedExecutors;
Thomas Vachuskaaad8b1d2015-12-11 10:36:53 -080030import org.onlab.util.Tools;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070031import org.onosproject.cfg.ComponentConfigService;
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -080032import org.onosproject.cluster.ClusterMetadata;
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080033import org.onosproject.cluster.ClusterMetadataService;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070034import org.onosproject.cluster.ClusterService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080035import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.mastership.MastershipEvent;
38import org.onosproject.mastership.MastershipListener;
39import org.onosproject.mastership.MastershipService;
40import org.onosproject.net.ConnectPoint;
41import org.onosproject.net.Device;
42import org.onosproject.net.DeviceId;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -070043import org.onosproject.net.LinkKey;
Brian O'Connorabafb502014-12-02 22:26:20 -080044import org.onosproject.net.Port;
Naoki Shiota399a0b32015-11-15 20:36:13 -060045import org.onosproject.net.config.ConfigFactory;
46import org.onosproject.net.config.NetworkConfigEvent;
47import org.onosproject.net.config.NetworkConfigListener;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070048import org.onosproject.net.config.NetworkConfigRegistry;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.net.device.DeviceEvent;
HIGUCHI Yuta1979f552015-12-28 21:24:26 -080050import org.onosproject.net.device.DeviceEvent.Type;
Brian O'Connorabafb502014-12-02 22:26:20 -080051import org.onosproject.net.device.DeviceListener;
52import org.onosproject.net.device.DeviceService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080053import org.onosproject.net.flow.DefaultTrafficSelector;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080054import org.onosproject.net.flow.TrafficSelector;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -070055import org.onosproject.net.link.DefaultLinkDescription;
Brian O'Connorabafb502014-12-02 22:26:20 -080056import org.onosproject.net.link.LinkProvider;
57import org.onosproject.net.link.LinkProviderRegistry;
58import org.onosproject.net.link.LinkProviderService;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -070059import org.onosproject.net.link.LinkService;
Brian O'Connorabafb502014-12-02 22:26:20 -080060import org.onosproject.net.packet.PacketContext;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080061import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080062import org.onosproject.net.packet.PacketProcessor;
63import org.onosproject.net.packet.PacketService;
64import org.onosproject.net.provider.AbstractProvider;
65import org.onosproject.net.provider.ProviderId;
Ray Milkey957390e2016-02-09 10:02:46 -080066import org.onosproject.provider.lldpcommon.LinkDiscoveryContext;
67import org.onosproject.provider.lldpcommon.LinkDiscovery;
Thomas Vachuskaaad8b1d2015-12-11 10:36:53 -080068import org.onosproject.store.service.ConsistentMapException;
Yuta HIGUCHI41289382014-12-19 17:47:12 -080069import org.osgi.service.component.ComponentContext;
alshabib7911a052014-10-16 17:49:37 -070070import org.slf4j.Logger;
71
Marc De Leenheer0bfc2a12016-02-02 22:46:27 -080072import java.util.Dictionary;
73import java.util.EnumSet;
74import java.util.Map;
75import java.util.Optional;
76import java.util.Properties;
77import java.util.Set;
78import java.util.concurrent.ConcurrentHashMap;
79import java.util.concurrent.ScheduledExecutorService;
80
81import static com.google.common.base.Strings.isNullOrEmpty;
82import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
83import static java.util.concurrent.TimeUnit.SECONDS;
84import static org.onlab.packet.Ethernet.TYPE_BSN;
85import static org.onlab.packet.Ethernet.TYPE_LLDP;
86import static org.onlab.util.Tools.get;
87import static org.onlab.util.Tools.groupedThreads;
88import static org.onosproject.cluster.ClusterMetadata.NO_NAME;
89import static org.onosproject.net.Link.Type.DIRECT;
90import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
91import static org.onosproject.net.config.basics.SubjectFactories.CONNECT_POINT_SUBJECT_FACTORY;
92import static org.onosproject.net.config.basics.SubjectFactories.DEVICE_SUBJECT_FACTORY;
93import static org.slf4j.LoggerFactory.getLogger;
Yuta HIGUCHI41289382014-12-19 17:47:12 -080094
alshabib7911a052014-10-16 17:49:37 -070095/**
Thomas Vachuska05453c92015-09-09 14:40:49 -070096 * Provider which uses LLDP and BDDP packets to detect network infrastructure links.
alshabib7911a052014-10-16 17:49:37 -070097 */
98@Component(immediate = true)
Jonathan Hartb35540a2015-11-17 09:30:56 -080099public class LldpLinkProvider extends AbstractProvider implements LinkProvider {
alshabib7911a052014-10-16 17:49:37 -0700100
Thomas Vachuskafc52fec2015-05-18 19:13:56 -0700101 private static final String PROVIDER_NAME = "org.onosproject.provider.lldp";
102
Thomas Vachuska05453c92015-09-09 14:40:49 -0700103 private static final String FORMAT =
104 "Settings: enabled={}, useBDDP={}, probeRate={}, " +
Naoki Shiota399a0b32015-11-15 20:36:13 -0600105 "staleLinkAge={}";
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800106
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700107 // When a Device/Port has this annotation, do not send out LLDP/BDDP
108 public static final String NO_LLDP = "no-lldp";
109
Thomas Vachuskaaad8b1d2015-12-11 10:36:53 -0800110 private static final int MAX_RETRIES = 5;
111 private static final int RETRY_DELAY = 1_000; // millis
112
alshabib7911a052014-10-16 17:49:37 -0700113 private final Logger log = getLogger(getClass());
114
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected CoreService coreService;
117
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib7911a052014-10-16 17:49:37 -0700119 protected LinkProviderRegistry providerRegistry;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 protected DeviceService deviceService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700125 protected LinkService linkService;
126
127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800128 protected PacketService packetService;
alshabib7911a052014-10-16 17:49:37 -0700129
alshabib875d6262014-10-17 16:19:40 -0700130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
131 protected MastershipService masterService;
132
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
134 protected ComponentConfigService cfgService;
135
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
137 protected ClusterService clusterService;
138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
140 protected NetworkConfigRegistry cfgRegistry;
141
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
143 protected ClusterMetadataService clusterMetadataService;
144
alshabib7911a052014-10-16 17:49:37 -0700145 private LinkProviderService providerService;
146
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800147 private ScheduledExecutorService executor;
148
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700149 // TODO: Add sanity checking for the configurable params based on the delays
150 private static final long DEVICE_SYNC_DELAY = 5;
151 private static final long LINK_PRUNER_DELAY = 3;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700152
153 private static final String PROP_ENABLED = "enabled";
154 @Property(name = PROP_ENABLED, boolValue = true,
155 label = "If false, link discovery is disabled")
156 private boolean enabled = false;
157
158 private static final String PROP_USE_BDDP = "useBDDP";
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700159 @Property(name = PROP_USE_BDDP, boolValue = true,
160 label = "Use BDDP for link discovery")
Jonathan Hartb35540a2015-11-17 09:30:56 -0800161 private boolean useBddp = true;
alshabib7911a052014-10-16 17:49:37 -0700162
Thomas Vachuska05453c92015-09-09 14:40:49 -0700163 private static final String PROP_PROBE_RATE = "probeRate";
Thomas Vachuska9e51fd02016-01-04 16:51:28 -0800164 private static final int DEFAULT_PROBE_RATE = 3000;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700165 @Property(name = PROP_PROBE_RATE, intValue = DEFAULT_PROBE_RATE,
166 label = "LLDP and BDDP probe rate specified in millis")
167 private int probeRate = DEFAULT_PROBE_RATE;
Saurav Dasc313c402015-02-27 10:09:47 -0800168
Thomas Vachuska05453c92015-09-09 14:40:49 -0700169 private static final String PROP_STALE_LINK_AGE = "staleLinkAge";
Thomas Vachuska9e51fd02016-01-04 16:51:28 -0800170 private static final int DEFAULT_STALE_LINK_AGE = 10000;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700171 @Property(name = PROP_STALE_LINK_AGE, intValue = DEFAULT_STALE_LINK_AGE,
172 label = "Number of millis beyond which links will be considered stale")
173 private int staleLinkAge = DEFAULT_STALE_LINK_AGE;
alshabib7911a052014-10-16 17:49:37 -0700174
Ray Milkey957390e2016-02-09 10:02:46 -0800175 private final LinkDiscoveryContext context = new InternalDiscoveryContext();
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800176 private final InternalRoleListener roleListener = new InternalRoleListener();
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700177 private final InternalDeviceListener deviceListener = new InternalDeviceListener();
178 private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800179
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700180 // Device link discovery helpers.
alshabib7911a052014-10-16 17:49:37 -0700181 protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>();
182
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700183 // Most recent time a tracked link was seen; links are tracked if their
184 // destination connection point is mastered by this controller instance.
185 private final Map<LinkKey, Long> linkTimes = Maps.newConcurrentMap();
186
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800187 private ApplicationId appId;
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800188
Naoki Shiota399a0b32015-11-15 20:36:13 -0600189 static final SuppressionRules DEFAULT_RULES
Rimon Ashkenazy8ebfff02016-02-01 11:56:36 +0200190 = new SuppressionRules(EnumSet.of(Device.Type.ROADM, Device.Type.FIBER_SWITCH, Device.Type.OTN),
Naoki Shiota399a0b32015-11-15 20:36:13 -0600191 ImmutableMap.of(NO_LLDP, SuppressionRules.ANY_VALUE));
192
193 private SuppressionRules rules = LldpLinkProvider.DEFAULT_RULES;
194
195 public static final String CONFIG_KEY = "suppression";
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800196 public static final String FEATURE_NAME = "linkDiscovery";
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800197 public static final String FINGERPRINT_FEATURE_NAME = "fingerprint";
Naoki Shiota399a0b32015-11-15 20:36:13 -0600198
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800199 private final Set<ConfigFactory<?, ?>> factories = ImmutableSet.of(
Naoki Shiota399a0b32015-11-15 20:36:13 -0600200 new ConfigFactory<ApplicationId, SuppressionConfig>(APP_SUBJECT_FACTORY,
201 SuppressionConfig.class,
202 CONFIG_KEY) {
203 @Override
204 public SuppressionConfig createConfig() {
205 return new SuppressionConfig();
206 }
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800207 },
208 new ConfigFactory<DeviceId, LinkDiscoveryFromDevice>(DEVICE_SUBJECT_FACTORY,
209 LinkDiscoveryFromDevice.class, FEATURE_NAME) {
210 @Override
211 public LinkDiscoveryFromDevice createConfig() {
212 return new LinkDiscoveryFromDevice();
213 }
214 },
215 new ConfigFactory<ConnectPoint, LinkDiscoveryFromPort>(CONNECT_POINT_SUBJECT_FACTORY,
216 LinkDiscoveryFromPort.class, FEATURE_NAME) {
217 @Override
218 public LinkDiscoveryFromPort createConfig() {
219 return new LinkDiscoveryFromPort();
220 }
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800221 },
222 new ConfigFactory<DeviceId, FingerprintProbeFromDevice>(DEVICE_SUBJECT_FACTORY,
223 FingerprintProbeFromDevice.class, FINGERPRINT_FEATURE_NAME) {
224 @Override
225 public FingerprintProbeFromDevice createConfig() {
226 return new FingerprintProbeFromDevice();
227 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600228 }
229 );
230
231 private final InternalConfigListener cfgListener = new InternalConfigListener();
232
233
alshabib7911a052014-10-16 17:49:37 -0700234 /**
235 * Creates an OpenFlow link provider.
236 */
Jonathan Hartb35540a2015-11-17 09:30:56 -0800237 public LldpLinkProvider() {
Thomas Vachuskafc52fec2015-05-18 19:13:56 -0700238 super(new ProviderId("lldp", PROVIDER_NAME));
alshabib7911a052014-10-16 17:49:37 -0700239 }
240
241 @Activate
Saurav Dasc313c402015-02-27 10:09:47 -0800242 public void activate(ComponentContext context) {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700243 cfgService.registerProperties(getClass());
Thomas Vachuskafc52fec2015-05-18 19:13:56 -0700244 appId = coreService.registerApplication(PROVIDER_NAME);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600245
246 cfgRegistry.addListener(cfgListener);
247 factories.forEach(cfgRegistry::registerConfigFactory);
248
Thomas Vachuska762a2d82016-01-04 10:25:20 -0800249 SuppressionConfig cfg =
250 Tools.retryable(() -> cfgRegistry.getConfig(appId, SuppressionConfig.class),
251 ConsistentMapException.class, MAX_RETRIES, RETRY_DELAY).get();
Naoki Shiota399a0b32015-11-15 20:36:13 -0600252 if (cfg == null) {
253 // If no configuration is found, register default.
Thomas Vachuskaaad8b1d2015-12-11 10:36:53 -0800254 cfg = Tools.retryable(this::setDefaultSuppressionConfig,
255 ConsistentMapException.class,
256 MAX_RETRIES, RETRY_DELAY).get();
Naoki Shiota399a0b32015-11-15 20:36:13 -0600257 }
258 cfgListener.reconfigureSuppressionRules(cfg);
259
Saurav Dasc313c402015-02-27 10:09:47 -0800260 modified(context);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700261 log.info("Started");
262 }
263
Thomas Vachuskaaad8b1d2015-12-11 10:36:53 -0800264 private SuppressionConfig setDefaultSuppressionConfig() {
265 SuppressionConfig cfg = cfgRegistry.addConfig(appId, SuppressionConfig.class);
266 cfg.deviceTypes(DEFAULT_RULES.getSuppressedDeviceType())
267 .annotation(DEFAULT_RULES.getSuppressedAnnotation())
268 .apply();
269 return cfg;
270 }
271
Thomas Vachuska05453c92015-09-09 14:40:49 -0700272 @Deactivate
273 public void deactivate() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600274 cfgRegistry.removeListener(cfgListener);
275 factories.forEach(cfgRegistry::unregisterConfigFactory);
276
Thomas Vachuska05453c92015-09-09 14:40:49 -0700277 cfgService.unregisterProperties(getClass(), false);
278 disable();
279 log.info("Stopped");
280 }
281
282 @Modified
283 public void modified(ComponentContext context) {
284 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
285
286 boolean newEnabled, newUseBddp;
287 int newProbeRate, newStaleLinkAge;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700288 try {
289 String s = get(properties, PROP_ENABLED);
290 newEnabled = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim());
291
292 s = get(properties, PROP_USE_BDDP);
293 newUseBddp = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim());
294
295 s = get(properties, PROP_PROBE_RATE);
296 newProbeRate = isNullOrEmpty(s) ? probeRate : Integer.parseInt(s.trim());
297
298 s = get(properties, PROP_STALE_LINK_AGE);
299 newStaleLinkAge = isNullOrEmpty(s) ? staleLinkAge : Integer.parseInt(s.trim());
300
Thomas Vachuska05453c92015-09-09 14:40:49 -0700301 } catch (NumberFormatException e) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700302 log.warn("Component configuration had invalid values", e);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700303 newEnabled = enabled;
Jonathan Hartb35540a2015-11-17 09:30:56 -0800304 newUseBddp = useBddp;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700305 newProbeRate = probeRate;
306 newStaleLinkAge = staleLinkAge;
Saurav Dasc313c402015-02-27 10:09:47 -0800307 }
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800308
Thomas Vachuska05453c92015-09-09 14:40:49 -0700309 boolean wasEnabled = enabled;
310
311 enabled = newEnabled;
Jonathan Hartb35540a2015-11-17 09:30:56 -0800312 useBddp = newUseBddp;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700313 probeRate = newProbeRate;
314 staleLinkAge = newStaleLinkAge;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700315
316 if (!wasEnabled && enabled) {
317 enable();
318 } else if (wasEnabled && !enabled) {
319 disable();
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700320 } else {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700321 if (enabled) {
322 // update all discovery helper state
323 loadDevices();
324 }
Thomas Vachuska05453c92015-09-09 14:40:49 -0700325 }
326
Naoki Shiota399a0b32015-11-15 20:36:13 -0600327 log.info(FORMAT, enabled, useBddp, probeRate, staleLinkAge);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700328 }
329
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700330 /**
331 * Enables link discovery processing.
332 */
Thomas Vachuska05453c92015-09-09 14:40:49 -0700333 private void enable() {
alshabib7911a052014-10-16 17:49:37 -0700334 providerService = providerRegistry.register(this);
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800335 masterService.addListener(roleListener);
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700336 deviceService.addListener(deviceListener);
337 packetService.addProcessor(packetProcessor, PacketProcessor.advisor(0));
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800338
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700339 loadDevices();
Thomas Vachuska05453c92015-09-09 14:40:49 -0700340
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700341 executor = newSingleThreadScheduledExecutor(groupedThreads("onos/link", "discovery-%d", log));
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700342 executor.scheduleAtFixedRate(new SyncDeviceInfoTask(),
343 DEVICE_SYNC_DELAY, DEVICE_SYNC_DELAY, SECONDS);
344 executor.scheduleAtFixedRate(new LinkPrunerTask(),
345 LINK_PRUNER_DELAY, LINK_PRUNER_DELAY, SECONDS);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700346
Thomas Vachuska05453c92015-09-09 14:40:49 -0700347 requestIntercepts();
348 }
349
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700350 /**
351 * Disables link discovery processing.
352 */
Thomas Vachuska05453c92015-09-09 14:40:49 -0700353 private void disable() {
354 withdrawIntercepts();
355
356 providerRegistry.unregister(this);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700357 masterService.removeListener(roleListener);
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700358 deviceService.removeListener(deviceListener);
359 packetService.removeProcessor(packetProcessor);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700360
Naoki Shiota399a0b32015-11-15 20:36:13 -0600361
Thomas Vachuska05453c92015-09-09 14:40:49 -0700362 if (executor != null) {
363 executor.shutdownNow();
364 }
365 discoverers.values().forEach(LinkDiscovery::stop);
366 discoverers.clear();
367
368 providerService = null;
369 }
370
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700371 /**
372 * Loads available devices and registers their ports to be probed.
373 */
374 private void loadDevices() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600375 if (!enabled) {
376 return;
377 }
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700378 deviceService.getAvailableDevices()
379 .forEach(d -> updateDevice(d)
380 .ifPresent(ld -> updatePorts(ld, d.id())));
381 }
382
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800383 private boolean isBlacklisted(DeviceId did) {
384 LinkDiscoveryFromDevice cfg = cfgRegistry.getConfig(did, LinkDiscoveryFromDevice.class);
385 if (cfg == null) {
386 return false;
387 }
388 return !cfg.enabled();
389 }
390
391 private boolean isBlacklisted(ConnectPoint cp) {
392 // if parent device is blacklisted, so is the port
393 if (isBlacklisted(cp.deviceId())) {
394 return true;
395 }
396 LinkDiscoveryFromPort cfg = cfgRegistry.getConfig(cp, LinkDiscoveryFromPort.class);
397 if (cfg == null) {
398 return false;
399 }
400 return !cfg.enabled();
401 }
402
403 private boolean isBlacklisted(Port port) {
404 return isBlacklisted(new ConnectPoint(port.element().id(), port.number()));
405 }
406
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800407 private boolean isFingerprinted(DeviceId did) {
408 FingerprintProbeFromDevice cfg = cfgRegistry.getConfig(did, FingerprintProbeFromDevice.class);
409 if (cfg == null) {
410 return false;
411 }
412 return cfg.enabled();
413 }
414
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700415 /**
416 * Updates discovery helper for specified device.
417 *
418 * Adds and starts a discovery helper for specified device if enabled,
419 * calls {@link #removeDevice(DeviceId)} otherwise.
420 *
421 * @param device device to add
422 * @return discovery helper if discovery is enabled for the device
423 */
424 private Optional<LinkDiscovery> updateDevice(Device device) {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800425 if (device == null) {
426 return Optional.empty();
427 }
428 if (rules.isSuppressed(device) || isBlacklisted(device.id())) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700429 log.trace("LinkDiscovery from {} disabled by configuration", device.id());
430 removeDevice(device.id());
431 return Optional.empty();
432 }
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800433
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700434 LinkDiscovery ld = discoverers.computeIfAbsent(device.id(),
435 did -> new LinkDiscovery(device, context));
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800436 if (isFingerprinted(device.id())) {
437 ld.enableFingerprint();
438 } else {
439 ld.disableFingerprint();
440 }
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700441 if (ld.isStopped()) {
442 ld.start();
443 }
444 return Optional.of(ld);
445 }
446
447 /**
448 * Removes after stopping discovery helper for specified device.
449 * @param deviceId device to remove
450 */
451 private void removeDevice(final DeviceId deviceId) {
452 discoverers.computeIfPresent(deviceId, (did, ld) -> {
453 ld.stop();
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700454 return null;
455 });
456
457 }
458
459 /**
460 * Updates ports of the specified device to the specified discovery helper.
461 */
462 private void updatePorts(LinkDiscovery discoverer, DeviceId deviceId) {
463 deviceService.getPorts(deviceId).forEach(p -> updatePort(discoverer, p));
464 }
465
466 /**
467 * Updates discovery helper state of the specified port.
468 *
469 * Adds a port to the discovery helper if up and discovery is enabled,
470 * or calls {@link #removePort(Port)} otherwise.
471 */
472 private void updatePort(LinkDiscovery discoverer, Port port) {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800473 if (port == null) {
474 return;
475 }
HIGUCHI Yutab853b3f2015-11-17 18:43:20 -0800476 if (port.number().isLogical()) {
477 // silently ignore logical ports
478 return;
479 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600480
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800481 if (rules.isSuppressed(port) || isBlacklisted(port)) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700482 log.trace("LinkDiscovery from {} disabled by configuration", port);
483 removePort(port);
484 return;
485 }
486
487 // check if enabled and turn off discovery?
488 if (!port.isEnabled()) {
489 removePort(port);
490 return;
491 }
492
HIGUCHI Yutab853b3f2015-11-17 18:43:20 -0800493 discoverer.addPort(port);
alshabib7911a052014-10-16 17:49:37 -0700494 }
495
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700496 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700497 * Removes a port from the specified discovery helper.
498 * @param port the port
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700499 */
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700500 private void removePort(Port port) {
501 if (port.element() instanceof Device) {
502 Device d = (Device) port.element();
503 LinkDiscovery ld = discoverers.get(d.id());
504 if (ld != null) {
505 ld.removePort(port.number());
Jonathan Hart45066bc2015-07-28 11:18:34 -0700506 }
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700507 } else {
508 log.warn("Attempted to remove non-Device port", port);
Jonathan Hart45066bc2015-07-28 11:18:34 -0700509 }
510 }
511
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700512 /**
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700513 * Requests packet intercepts.
Charles M.C. Chane148de82015-05-06 12:38:21 +0800514 */
Thomas Vachuska27bee092015-06-23 19:03:10 -0700515 private void requestIntercepts() {
516 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Thomas Vachuska347cc872015-09-23 10:25:29 -0700517 selector.matchEthType(TYPE_LLDP);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700518 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800519
Thomas Vachuska347cc872015-09-23 10:25:29 -0700520 selector.matchEthType(TYPE_BSN);
Jonathan Hartb35540a2015-11-17 09:30:56 -0800521 if (useBddp) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700522 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
523 } else {
524 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800525 }
526 }
527
Thomas Vachuska27bee092015-06-23 19:03:10 -0700528 /**
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700529 * Withdraws packet intercepts.
Thomas Vachuska27bee092015-06-23 19:03:10 -0700530 */
531 private void withdrawIntercepts() {
532 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Thomas Vachuska347cc872015-09-23 10:25:29 -0700533 selector.matchEthType(TYPE_LLDP);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700534 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Thomas Vachuska347cc872015-09-23 10:25:29 -0700535 selector.matchEthType(TYPE_BSN);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700536 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
537 }
538
Naoki Shiota399a0b32015-11-15 20:36:13 -0600539 protected SuppressionRules rules() {
540 return rules;
541 }
542
543 protected void updateRules(SuppressionRules newRules) {
544 if (!rules.equals(newRules)) {
545 rules = newRules;
546 loadDevices();
547 }
548 }
549
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700550 /**
551 * Processes device mastership role changes.
552 */
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800553 private class InternalRoleListener implements MastershipListener {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800554 @Override
555 public void event(MastershipEvent event) {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800556 if (MastershipEvent.Type.BACKUPS_CHANGED.equals(event.type())) {
557 // only need new master events
558 return;
559 }
560
561 DeviceId deviceId = event.subject();
562 Device device = deviceService.getDevice(deviceId);
563 if (device == null) {
Thomas Vachuska3358af22015-05-19 18:40:34 -0700564 log.debug("Device {} doesn't exist, or isn't there yet", deviceId);
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800565 return;
566 }
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700567 if (clusterService.getLocalNode().id().equals(event.roleInfo().master())) {
568 updateDevice(device).ifPresent(ld -> updatePorts(ld, device.id()));
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800569 }
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800570 }
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800571 }
alshabib7911a052014-10-16 17:49:37 -0700572
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700573 /**
574 * Processes device events.
575 */
576 private class InternalDeviceListener implements DeviceListener {
alshabib7911a052014-10-16 17:49:37 -0700577 @Override
578 public void event(DeviceEvent event) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800579 if (event.type() == Type.PORT_STATS_UPDATED) {
580 return;
581 }
alshabib7911a052014-10-16 17:49:37 -0700582 Device device = event.subject();
alshabibacd91832014-10-17 14:38:41 -0700583 Port port = event.port();
alshabibdfc7afb2014-10-21 20:13:27 -0700584 if (device == null) {
585 log.error("Device is null.");
586 return;
587 }
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700588 log.trace("{} {} {}", event.type(), event.subject(), event);
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700589 final DeviceId deviceId = device.id();
alshabib7911a052014-10-16 17:49:37 -0700590 switch (event.type()) {
591 case DEVICE_ADDED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700592 case DEVICE_UPDATED:
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700593 updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId));
alshabib7911a052014-10-16 17:49:37 -0700594 break;
595 case PORT_ADDED:
596 case PORT_UPDATED:
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700597 if (port.isEnabled()) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700598 updateDevice(device).ifPresent(ld -> updatePort(ld, port));
alshabib7911a052014-10-16 17:49:37 -0700599 } else {
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700600 log.debug("Port down {}", port);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700601 removePort(port);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600602 providerService.linksVanished(new ConnectPoint(port.element().id(),
603 port.number()));
alshabib7911a052014-10-16 17:49:37 -0700604 }
605 break;
606 case PORT_REMOVED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700607 log.debug("Port removed {}", port);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700608 removePort(port);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600609 providerService.linksVanished(new ConnectPoint(port.element().id(),
610 port.number()));
alshabib7911a052014-10-16 17:49:37 -0700611 break;
612 case DEVICE_REMOVED:
613 case DEVICE_SUSPENDED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700614 log.debug("Device removed {}", deviceId);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700615 removeDevice(deviceId);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600616 providerService.linksVanished(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700617 break;
618 case DEVICE_AVAILABILITY_CHANGED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700619 if (deviceService.isAvailable(deviceId)) {
620 log.debug("Device up {}", deviceId);
alshabibe3af2652015-12-01 23:05:34 -0800621 updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId));
alshabib7911a052014-10-16 17:49:37 -0700622 } else {
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700623 log.debug("Device down {}", deviceId);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700624 removeDevice(deviceId);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600625 providerService.linksVanished(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700626 }
627 break;
Jonathan Hart9de692c2015-04-23 11:45:47 -0700628 case PORT_STATS_UPDATED:
629 break;
alshabib7911a052014-10-16 17:49:37 -0700630 default:
631 log.debug("Unknown event {}", event);
632 }
633 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700634 }
alshabib7911a052014-10-16 17:49:37 -0700635
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700636 /**
637 * Processes incoming packets.
638 */
639 private class InternalPacketProcessor implements PacketProcessor {
alshabib7911a052014-10-16 17:49:37 -0700640 @Override
641 public void process(PacketContext context) {
Thomas Vachuska347cc872015-09-23 10:25:29 -0700642 if (context == null || context.isHandled()) {
alshabib4a179dc2014-10-17 17:17:01 -0700643 return;
644 }
Thomas Vachuska347cc872015-09-23 10:25:29 -0700645
646 Ethernet eth = context.inPacket().parsed();
647 if (eth == null || (eth.getEtherType() != TYPE_LLDP && eth.getEtherType() != TYPE_BSN)) {
648 return;
649 }
650
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700651 LinkDiscovery ld = discoverers.get(context.inPacket().receivedFrom().deviceId());
alshabib7911a052014-10-16 17:49:37 -0700652 if (ld == null) {
653 return;
654 }
655
Jonathan Hartb35540a2015-11-17 09:30:56 -0800656 if (ld.handleLldp(context)) {
alshabib7911a052014-10-16 17:49:37 -0700657 context.block();
658 }
659 }
660 }
661
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700662 /**
663 * Auxiliary task to keep device ports up to date.
664 */
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800665 private final class SyncDeviceInfoTask implements Runnable {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800666 @Override
667 public void run() {
668 if (Thread.currentThread().isInterrupted()) {
669 log.info("Interrupted, quitting");
670 return;
671 }
672 // check what deviceService sees, to see if we are missing anything
673 try {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700674 loadDevices();
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800675 } catch (Exception e) {
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700676 // Catch all exceptions to avoid task being suppressed
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800677 log.error("Exception thrown during synchronization process", e);
678 }
679 }
680 }
681
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700682 /**
683 * Auxiliary task for pruning stale links.
684 */
685 private class LinkPrunerTask implements Runnable {
686 @Override
687 public void run() {
688 if (Thread.currentThread().isInterrupted()) {
689 log.info("Interrupted, quitting");
690 return;
691 }
692
693 try {
694 // TODO: There is still a slight possibility of mastership
695 // change occurring right with link going stale. This will
696 // result in the stale link not being pruned.
697 Maps.filterEntries(linkTimes, e -> {
698 if (!masterService.isLocalMaster(e.getKey().dst().deviceId())) {
699 return true;
700 }
701 if (isStale(e.getValue())) {
702 providerService.linkVanished(new DefaultLinkDescription(e.getKey().src(),
703 e.getKey().dst(),
704 DIRECT));
705 return true;
706 }
707 return false;
708 }).clear();
709
710 } catch (Exception e) {
711 // Catch all exceptions to avoid task being suppressed
712 log.error("Exception thrown during link pruning process", e);
713 }
714 }
715
716 private boolean isStale(long lastSeen) {
717 return lastSeen < System.currentTimeMillis() - staleLinkAge;
718 }
719 }
720
721 /**
722 * Provides processing context for the device link discovery helpers.
723 */
Ray Milkey957390e2016-02-09 10:02:46 -0800724 private class InternalDiscoveryContext implements LinkDiscoveryContext {
Thomas Vachuska05453c92015-09-09 14:40:49 -0700725 @Override
726 public MastershipService mastershipService() {
727 return masterService;
728 }
729
730 @Override
731 public LinkProviderService providerService() {
732 return providerService;
733 }
734
735 @Override
736 public PacketService packetService() {
737 return packetService;
738 }
739
740 @Override
741 public long probeRate() {
742 return probeRate;
743 }
744
745 @Override
Jonathan Hartb35540a2015-11-17 09:30:56 -0800746 public boolean useBddp() {
747 return useBddp;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700748 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700749
750 @Override
751 public void touchLink(LinkKey key) {
752 linkTimes.put(key, System.currentTimeMillis());
753 }
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800754
755 @Override
756 public String fingerprint() {
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800757 ClusterMetadata mdata = clusterMetadataService.getClusterMetadata();
758 return mdata == null ? NO_NAME : mdata.getName();
759 }
760
761 @Override
762 public DeviceService deviceService() {
763 return deviceService;
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800764 }
Thomas Vachuska05453c92015-09-09 14:40:49 -0700765 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700766
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800767 static final EnumSet<NetworkConfigEvent.Type> CONFIG_CHANGED
768 = EnumSet.of(NetworkConfigEvent.Type.CONFIG_ADDED,
769 NetworkConfigEvent.Type.CONFIG_UPDATED,
770 NetworkConfigEvent.Type.CONFIG_REMOVED);
771
Naoki Shiota399a0b32015-11-15 20:36:13 -0600772 private class InternalConfigListener implements NetworkConfigListener {
773
774 private synchronized void reconfigureSuppressionRules(SuppressionConfig cfg) {
775 if (cfg == null) {
776 log.error("Suppression Config is null.");
777 return;
778 }
779
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800780 SuppressionRules newRules = new SuppressionRules(cfg.deviceTypes(),
Naoki Shiota399a0b32015-11-15 20:36:13 -0600781 cfg.annotation());
782
783 updateRules(newRules);
784 }
785
786 @Override
787 public void event(NetworkConfigEvent event) {
Andrea Campanella90f044f2016-03-02 09:14:57 -0800788 SharedExecutors.getPoolThreadExecutor().execute(() -> {
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800789 if (event.configClass() == LinkDiscoveryFromDevice.class &&
790 CONFIG_CHANGED.contains(event.type())) {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800791
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800792 if (event.subject() instanceof DeviceId) {
793 final DeviceId did = (DeviceId) event.subject();
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800794 Device device = deviceService.getDevice(did);
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800795 updateDevice(device).ifPresent(ld -> updatePorts(ld, did));
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800796 }
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800797
798 } else if (event.configClass() == LinkDiscoveryFromPort.class &&
799 CONFIG_CHANGED.contains(event.type())) {
800
801 if (event.subject() instanceof ConnectPoint) {
802 ConnectPoint cp = (ConnectPoint) event.subject();
803 if (cp.elementId() instanceof DeviceId) {
804 final DeviceId did = (DeviceId) cp.elementId();
805 Device device = deviceService.getDevice(did);
806 Port port = deviceService.getPort(did, cp.port());
807 updateDevice(device).ifPresent(ld -> updatePort(ld, port));
808 }
809 }
810
811 } else if (event.configClass() == FingerprintProbeFromDevice.class &&
812 CONFIG_CHANGED.contains(event.type())) {
813
814 if (event.subject() instanceof DeviceId) {
815 final DeviceId did = (DeviceId) event.subject();
816 Device device = deviceService.getDevice(did);
817 updateDevice(device);
818 }
819
820 } else if (event.configClass().equals(SuppressionConfig.class) &&
821 (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
822 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) {
823 SuppressionConfig cfg = cfgRegistry.getConfig(appId, SuppressionConfig.class);
824 reconfigureSuppressionRules(cfg);
825 log.trace("Network config reconfigured");
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800826 }
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800827 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600828 }
829 }
alshabib7911a052014-10-16 17:49:37 -0700830}