blob: 98ae4081f1f09a3cd042d34804a29b01074744cd [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
Ray Milkeyd9bbde82016-06-09 11:35:00 -070018import java.util.Dictionary;
19import java.util.EnumSet;
20import java.util.Map;
21import java.util.Optional;
22import java.util.Properties;
23import java.util.Set;
24import java.util.concurrent.ConcurrentHashMap;
25import java.util.concurrent.ExecutorService;
26import java.util.concurrent.ScheduledExecutorService;
27
alshabib7911a052014-10-16 17:49:37 -070028import org.apache.felix.scr.annotations.Activate;
29import org.apache.felix.scr.annotations.Component;
30import org.apache.felix.scr.annotations.Deactivate;
Yuta HIGUCHI41289382014-12-19 17:47:12 -080031import org.apache.felix.scr.annotations.Modified;
32import org.apache.felix.scr.annotations.Property;
alshabib7911a052014-10-16 17:49:37 -070033import org.apache.felix.scr.annotations.Reference;
34import org.apache.felix.scr.annotations.ReferenceCardinality;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080035import org.onlab.packet.Ethernet;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070036import org.onosproject.cfg.ComponentConfigService;
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080037import org.onosproject.cluster.ClusterMetadataService;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070038import org.onosproject.cluster.ClusterService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080039import org.onosproject.core.ApplicationId;
40import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.mastership.MastershipEvent;
42import org.onosproject.mastership.MastershipListener;
43import org.onosproject.mastership.MastershipService;
44import org.onosproject.net.ConnectPoint;
45import org.onosproject.net.Device;
46import org.onosproject.net.DeviceId;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -070047import org.onosproject.net.LinkKey;
Brian O'Connorabafb502014-12-02 22:26:20 -080048import org.onosproject.net.Port;
Naoki Shiota399a0b32015-11-15 20:36:13 -060049import org.onosproject.net.config.ConfigFactory;
50import org.onosproject.net.config.NetworkConfigEvent;
51import org.onosproject.net.config.NetworkConfigListener;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070052import org.onosproject.net.config.NetworkConfigRegistry;
Brian O'Connorabafb502014-12-02 22:26:20 -080053import org.onosproject.net.device.DeviceEvent;
HIGUCHI Yuta1979f552015-12-28 21:24:26 -080054import org.onosproject.net.device.DeviceEvent.Type;
Brian O'Connorabafb502014-12-02 22:26:20 -080055import org.onosproject.net.device.DeviceListener;
56import org.onosproject.net.device.DeviceService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080057import org.onosproject.net.flow.DefaultTrafficSelector;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080058import org.onosproject.net.flow.TrafficSelector;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -070059import org.onosproject.net.link.DefaultLinkDescription;
Brian O'Connorabafb502014-12-02 22:26:20 -080060import org.onosproject.net.link.LinkProviderRegistry;
61import org.onosproject.net.link.LinkProviderService;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -070062import org.onosproject.net.link.LinkService;
Ray Milkeyd9bbde82016-06-09 11:35:00 -070063import org.onosproject.net.link.ProbedLinkProvider;
Brian O'Connorabafb502014-12-02 22:26:20 -080064import org.onosproject.net.packet.PacketContext;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080065import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080066import org.onosproject.net.packet.PacketProcessor;
67import org.onosproject.net.packet.PacketService;
68import org.onosproject.net.provider.AbstractProvider;
69import org.onosproject.net.provider.ProviderId;
Ray Milkey957390e2016-02-09 10:02:46 -080070import org.onosproject.provider.lldpcommon.LinkDiscovery;
Ray Milkeyd9bbde82016-06-09 11:35:00 -070071import org.onosproject.provider.lldpcommon.LinkDiscoveryContext;
Yuta HIGUCHI41289382014-12-19 17:47:12 -080072import org.osgi.service.component.ComponentContext;
alshabib7911a052014-10-16 17:49:37 -070073import org.slf4j.Logger;
74
Ray Milkeyd9bbde82016-06-09 11:35:00 -070075import com.google.common.collect.ImmutableMap;
76import com.google.common.collect.ImmutableSet;
77import com.google.common.collect.Maps;
Marc De Leenheer0bfc2a12016-02-02 22:46:27 -080078
79import static com.google.common.base.Strings.isNullOrEmpty;
80import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
81import static java.util.concurrent.TimeUnit.SECONDS;
82import static org.onlab.packet.Ethernet.TYPE_BSN;
83import static org.onlab.packet.Ethernet.TYPE_LLDP;
84import static org.onlab.util.Tools.get;
85import static org.onlab.util.Tools.groupedThreads;
Marc De Leenheer0bfc2a12016-02-02 22:46:27 -080086import static org.onosproject.net.Link.Type.DIRECT;
87import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
88import static org.onosproject.net.config.basics.SubjectFactories.CONNECT_POINT_SUBJECT_FACTORY;
89import static org.onosproject.net.config.basics.SubjectFactories.DEVICE_SUBJECT_FACTORY;
90import static org.slf4j.LoggerFactory.getLogger;
Yuta HIGUCHI41289382014-12-19 17:47:12 -080091
alshabib7911a052014-10-16 17:49:37 -070092/**
Thomas Vachuska05453c92015-09-09 14:40:49 -070093 * Provider which uses LLDP and BDDP packets to detect network infrastructure links.
alshabib7911a052014-10-16 17:49:37 -070094 */
95@Component(immediate = true)
Ayaka Koshibe48229222016-05-16 18:04:26 -070096public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProvider {
alshabib7911a052014-10-16 17:49:37 -070097
Thomas Vachuskafc52fec2015-05-18 19:13:56 -070098 private static final String PROVIDER_NAME = "org.onosproject.provider.lldp";
99
Thomas Vachuska05453c92015-09-09 14:40:49 -0700100 private static final String FORMAT =
101 "Settings: enabled={}, useBDDP={}, probeRate={}, " +
Naoki Shiota399a0b32015-11-15 20:36:13 -0600102 "staleLinkAge={}";
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800103
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700104 // When a Device/Port has this annotation, do not send out LLDP/BDDP
105 public static final String NO_LLDP = "no-lldp";
106
Thomas Vachuskaaad8b1d2015-12-11 10:36:53 -0800107 private static final int MAX_RETRIES = 5;
108 private static final int RETRY_DELAY = 1_000; // millis
109
alshabib7911a052014-10-16 17:49:37 -0700110 private final Logger log = getLogger(getClass());
111
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected CoreService coreService;
114
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib7911a052014-10-16 17:49:37 -0700116 protected LinkProviderRegistry providerRegistry;
117
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected DeviceService deviceService;
120
121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700122 protected LinkService linkService;
123
124 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800125 protected PacketService packetService;
alshabib7911a052014-10-16 17:49:37 -0700126
alshabib875d6262014-10-17 16:19:40 -0700127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 protected MastershipService masterService;
129
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
131 protected ComponentConfigService cfgService;
132
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
134 protected ClusterService clusterService;
135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
137 protected NetworkConfigRegistry cfgRegistry;
138
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
140 protected ClusterMetadataService clusterMetadataService;
141
alshabib7911a052014-10-16 17:49:37 -0700142 private LinkProviderService providerService;
143
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800144 private ScheduledExecutorService executor;
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700145 protected ExecutorService eventExecutor;
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800146
Ray Milkeye80e18f2016-06-02 16:44:14 -0700147 private boolean shuttingDown = false;
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
Yuta HIGUCHI09697d02017-03-03 16:53:39 -0800190 = new SuppressionRules(EnumSet.of(Device.Type.ROADM,
191 Device.Type.FIBER_SWITCH,
192 Device.Type.OPTICAL_AMPLIFIER,
193 Device.Type.OTN),
Naoki Shiota399a0b32015-11-15 20:36:13 -0600194 ImmutableMap.of(NO_LLDP, SuppressionRules.ANY_VALUE));
195
196 private SuppressionRules rules = LldpLinkProvider.DEFAULT_RULES;
197
198 public static final String CONFIG_KEY = "suppression";
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800199 public static final String FEATURE_NAME = "linkDiscovery";
Naoki Shiota399a0b32015-11-15 20:36:13 -0600200
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800201 private final Set<ConfigFactory<?, ?>> factories = ImmutableSet.of(
Naoki Shiota399a0b32015-11-15 20:36:13 -0600202 new ConfigFactory<ApplicationId, SuppressionConfig>(APP_SUBJECT_FACTORY,
203 SuppressionConfig.class,
204 CONFIG_KEY) {
205 @Override
206 public SuppressionConfig createConfig() {
207 return new SuppressionConfig();
208 }
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800209 },
210 new ConfigFactory<DeviceId, LinkDiscoveryFromDevice>(DEVICE_SUBJECT_FACTORY,
211 LinkDiscoveryFromDevice.class, FEATURE_NAME) {
212 @Override
213 public LinkDiscoveryFromDevice createConfig() {
214 return new LinkDiscoveryFromDevice();
215 }
216 },
217 new ConfigFactory<ConnectPoint, LinkDiscoveryFromPort>(CONNECT_POINT_SUBJECT_FACTORY,
218 LinkDiscoveryFromPort.class, FEATURE_NAME) {
219 @Override
220 public LinkDiscoveryFromPort createConfig() {
221 return new LinkDiscoveryFromPort();
222 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600223 }
224 );
225
226 private final InternalConfigListener cfgListener = new InternalConfigListener();
227
alshabib7911a052014-10-16 17:49:37 -0700228 /**
229 * Creates an OpenFlow link provider.
230 */
Jonathan Hartb35540a2015-11-17 09:30:56 -0800231 public LldpLinkProvider() {
Thomas Vachuskafc52fec2015-05-18 19:13:56 -0700232 super(new ProviderId("lldp", PROVIDER_NAME));
alshabib7911a052014-10-16 17:49:37 -0700233 }
234
Sho SHIMIZU9efeb812016-08-18 09:29:20 -0700235 private String buildSrcMac() {
Ayaka Koshibe48229222016-05-16 18:04:26 -0700236 String srcMac = ProbedLinkProvider.fingerprintMac(clusterMetadataService.getClusterMetadata());
237 String defMac = ProbedLinkProvider.defaultMac();
238 if (srcMac.equals(defMac)) {
239 log.warn("Couldn't generate fingerprint. Using default value {}", defMac);
240 return defMac;
241 }
242 log.trace("Generated MAC address {}", srcMac);
243 return srcMac;
244 }
245
alshabib7911a052014-10-16 17:49:37 -0700246 @Activate
Saurav Dasc313c402015-02-27 10:09:47 -0800247 public void activate(ComponentContext context) {
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700248 eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/linkevents", "events-%d", log));
Ray Milkeye80e18f2016-06-02 16:44:14 -0700249 shuttingDown = false;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700250 cfgService.registerProperties(getClass());
Thomas Vachuskafc52fec2015-05-18 19:13:56 -0700251 appId = coreService.registerApplication(PROVIDER_NAME);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600252
253 cfgRegistry.addListener(cfgListener);
254 factories.forEach(cfgRegistry::registerConfigFactory);
255
Madan Jampanic6371882016-06-03 21:30:17 -0700256 SuppressionConfig cfg = cfgRegistry.getConfig(appId, SuppressionConfig.class);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600257 if (cfg == null) {
258 // If no configuration is found, register default.
Madan Jampanic6371882016-06-03 21:30:17 -0700259 cfg = this.setDefaultSuppressionConfig();
Naoki Shiota399a0b32015-11-15 20:36:13 -0600260 }
261 cfgListener.reconfigureSuppressionRules(cfg);
262
Saurav Dasc313c402015-02-27 10:09:47 -0800263 modified(context);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700264 log.info("Started");
265 }
266
Thomas Vachuskaaad8b1d2015-12-11 10:36:53 -0800267 private SuppressionConfig setDefaultSuppressionConfig() {
268 SuppressionConfig cfg = cfgRegistry.addConfig(appId, SuppressionConfig.class);
269 cfg.deviceTypes(DEFAULT_RULES.getSuppressedDeviceType())
270 .annotation(DEFAULT_RULES.getSuppressedAnnotation())
271 .apply();
272 return cfg;
273 }
274
Thomas Vachuska05453c92015-09-09 14:40:49 -0700275 @Deactivate
276 public void deactivate() {
Ray Milkeye80e18f2016-06-02 16:44:14 -0700277 shuttingDown = true;
Naoki Shiota399a0b32015-11-15 20:36:13 -0600278 cfgRegistry.removeListener(cfgListener);
279 factories.forEach(cfgRegistry::unregisterConfigFactory);
280
Thomas Vachuska05453c92015-09-09 14:40:49 -0700281 cfgService.unregisterProperties(getClass(), false);
282 disable();
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700283 eventExecutor.shutdownNow();
284 eventExecutor = null;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700285 log.info("Stopped");
286 }
287
288 @Modified
289 public void modified(ComponentContext context) {
290 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
291
292 boolean newEnabled, newUseBddp;
293 int newProbeRate, newStaleLinkAge;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700294 try {
295 String s = get(properties, PROP_ENABLED);
296 newEnabled = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim());
297
298 s = get(properties, PROP_USE_BDDP);
299 newUseBddp = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim());
300
301 s = get(properties, PROP_PROBE_RATE);
302 newProbeRate = isNullOrEmpty(s) ? probeRate : Integer.parseInt(s.trim());
303
304 s = get(properties, PROP_STALE_LINK_AGE);
305 newStaleLinkAge = isNullOrEmpty(s) ? staleLinkAge : Integer.parseInt(s.trim());
306
Thomas Vachuska05453c92015-09-09 14:40:49 -0700307 } catch (NumberFormatException e) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700308 log.warn("Component configuration had invalid values", e);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700309 newEnabled = enabled;
Jonathan Hartb35540a2015-11-17 09:30:56 -0800310 newUseBddp = useBddp;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700311 newProbeRate = probeRate;
312 newStaleLinkAge = staleLinkAge;
Saurav Dasc313c402015-02-27 10:09:47 -0800313 }
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800314
Thomas Vachuska05453c92015-09-09 14:40:49 -0700315 boolean wasEnabled = enabled;
316
317 enabled = newEnabled;
Jonathan Hartb35540a2015-11-17 09:30:56 -0800318 useBddp = newUseBddp;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700319 probeRate = newProbeRate;
320 staleLinkAge = newStaleLinkAge;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700321
322 if (!wasEnabled && enabled) {
323 enable();
324 } else if (wasEnabled && !enabled) {
325 disable();
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700326 } else {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700327 if (enabled) {
328 // update all discovery helper state
329 loadDevices();
330 }
Thomas Vachuska05453c92015-09-09 14:40:49 -0700331 }
332
Naoki Shiota399a0b32015-11-15 20:36:13 -0600333 log.info(FORMAT, enabled, useBddp, probeRate, staleLinkAge);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700334 }
335
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700336 /**
337 * Enables link discovery processing.
338 */
Thomas Vachuska05453c92015-09-09 14:40:49 -0700339 private void enable() {
alshabib7911a052014-10-16 17:49:37 -0700340 providerService = providerRegistry.register(this);
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800341 masterService.addListener(roleListener);
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700342 deviceService.addListener(deviceListener);
343 packetService.addProcessor(packetProcessor, PacketProcessor.advisor(0));
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800344
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700345 loadDevices();
Thomas Vachuska05453c92015-09-09 14:40:49 -0700346
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700347 executor = newSingleThreadScheduledExecutor(groupedThreads("onos/link", "discovery-%d", log));
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700348 executor.scheduleAtFixedRate(new SyncDeviceInfoTask(),
349 DEVICE_SYNC_DELAY, DEVICE_SYNC_DELAY, SECONDS);
350 executor.scheduleAtFixedRate(new LinkPrunerTask(),
351 LINK_PRUNER_DELAY, LINK_PRUNER_DELAY, SECONDS);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700352
Thomas Vachuska05453c92015-09-09 14:40:49 -0700353 requestIntercepts();
354 }
355
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700356 /**
357 * Disables link discovery processing.
358 */
Thomas Vachuska05453c92015-09-09 14:40:49 -0700359 private void disable() {
360 withdrawIntercepts();
361
362 providerRegistry.unregister(this);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700363 masterService.removeListener(roleListener);
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700364 deviceService.removeListener(deviceListener);
365 packetService.removeProcessor(packetProcessor);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700366
367 if (executor != null) {
368 executor.shutdownNow();
369 }
370 discoverers.values().forEach(LinkDiscovery::stop);
371 discoverers.clear();
372
373 providerService = null;
374 }
375
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700376 /**
377 * Loads available devices and registers their ports to be probed.
378 */
379 private void loadDevices() {
Ray Milkey0f87d482016-07-06 11:49:19 -0700380 if (!enabled || deviceService == null) {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600381 return;
382 }
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700383 deviceService.getAvailableDevices()
384 .forEach(d -> updateDevice(d)
385 .ifPresent(ld -> updatePorts(ld, d.id())));
386 }
387
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800388 private boolean isBlacklisted(DeviceId did) {
389 LinkDiscoveryFromDevice cfg = cfgRegistry.getConfig(did, LinkDiscoveryFromDevice.class);
390 if (cfg == null) {
391 return false;
392 }
393 return !cfg.enabled();
394 }
395
396 private boolean isBlacklisted(ConnectPoint cp) {
397 // if parent device is blacklisted, so is the port
398 if (isBlacklisted(cp.deviceId())) {
399 return true;
400 }
401 LinkDiscoveryFromPort cfg = cfgRegistry.getConfig(cp, LinkDiscoveryFromPort.class);
402 if (cfg == null) {
403 return false;
404 }
405 return !cfg.enabled();
406 }
407
408 private boolean isBlacklisted(Port port) {
409 return isBlacklisted(new ConnectPoint(port.element().id(), port.number()));
410 }
411
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700412 /**
413 * Updates discovery helper for specified device.
414 *
415 * Adds and starts a discovery helper for specified device if enabled,
416 * calls {@link #removeDevice(DeviceId)} otherwise.
417 *
418 * @param device device to add
419 * @return discovery helper if discovery is enabled for the device
420 */
421 private Optional<LinkDiscovery> updateDevice(Device device) {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800422 if (device == null) {
423 return Optional.empty();
424 }
425 if (rules.isSuppressed(device) || isBlacklisted(device.id())) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700426 log.trace("LinkDiscovery from {} disabled by configuration", device.id());
427 removeDevice(device.id());
428 return Optional.empty();
429 }
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800430
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700431 LinkDiscovery ld = discoverers.computeIfAbsent(device.id(),
432 did -> new LinkDiscovery(device, context));
433 if (ld.isStopped()) {
434 ld.start();
435 }
436 return Optional.of(ld);
437 }
438
439 /**
440 * Removes after stopping discovery helper for specified device.
441 * @param deviceId device to remove
442 */
443 private void removeDevice(final DeviceId deviceId) {
444 discoverers.computeIfPresent(deviceId, (did, ld) -> {
445 ld.stop();
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700446 return null;
447 });
448
449 }
450
451 /**
452 * Updates ports of the specified device to the specified discovery helper.
453 */
454 private void updatePorts(LinkDiscovery discoverer, DeviceId deviceId) {
455 deviceService.getPorts(deviceId).forEach(p -> updatePort(discoverer, p));
456 }
457
458 /**
459 * Updates discovery helper state of the specified port.
460 *
461 * Adds a port to the discovery helper if up and discovery is enabled,
462 * or calls {@link #removePort(Port)} otherwise.
463 */
464 private void updatePort(LinkDiscovery discoverer, Port port) {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800465 if (port == null) {
466 return;
467 }
HIGUCHI Yutab853b3f2015-11-17 18:43:20 -0800468 if (port.number().isLogical()) {
469 // silently ignore logical ports
470 return;
471 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600472
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800473 if (rules.isSuppressed(port) || isBlacklisted(port)) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700474 log.trace("LinkDiscovery from {} disabled by configuration", port);
475 removePort(port);
476 return;
477 }
478
479 // check if enabled and turn off discovery?
480 if (!port.isEnabled()) {
481 removePort(port);
482 return;
483 }
484
HIGUCHI Yutab853b3f2015-11-17 18:43:20 -0800485 discoverer.addPort(port);
alshabib7911a052014-10-16 17:49:37 -0700486 }
487
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700488 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700489 * Removes a port from the specified discovery helper.
490 * @param port the port
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700491 */
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700492 private void removePort(Port port) {
493 if (port.element() instanceof Device) {
494 Device d = (Device) port.element();
495 LinkDiscovery ld = discoverers.get(d.id());
496 if (ld != null) {
497 ld.removePort(port.number());
Jonathan Hart45066bc2015-07-28 11:18:34 -0700498 }
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700499 } else {
500 log.warn("Attempted to remove non-Device port", port);
Jonathan Hart45066bc2015-07-28 11:18:34 -0700501 }
502 }
503
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700504 /**
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700505 * Requests packet intercepts.
Charles M.C. Chane148de82015-05-06 12:38:21 +0800506 */
Thomas Vachuska27bee092015-06-23 19:03:10 -0700507 private void requestIntercepts() {
508 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Thomas Vachuska347cc872015-09-23 10:25:29 -0700509 selector.matchEthType(TYPE_LLDP);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700510 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800511
Thomas Vachuska347cc872015-09-23 10:25:29 -0700512 selector.matchEthType(TYPE_BSN);
Jonathan Hartb35540a2015-11-17 09:30:56 -0800513 if (useBddp) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700514 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
515 } else {
516 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800517 }
518 }
519
Thomas Vachuska27bee092015-06-23 19:03:10 -0700520 /**
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700521 * Withdraws packet intercepts.
Thomas Vachuska27bee092015-06-23 19:03:10 -0700522 */
523 private void withdrawIntercepts() {
524 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Thomas Vachuska347cc872015-09-23 10:25:29 -0700525 selector.matchEthType(TYPE_LLDP);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700526 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Thomas Vachuska347cc872015-09-23 10:25:29 -0700527 selector.matchEthType(TYPE_BSN);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700528 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
529 }
530
Naoki Shiota399a0b32015-11-15 20:36:13 -0600531 protected SuppressionRules rules() {
532 return rules;
533 }
534
535 protected void updateRules(SuppressionRules newRules) {
536 if (!rules.equals(newRules)) {
537 rules = newRules;
538 loadDevices();
539 }
540 }
541
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700542 /**
543 * Processes device mastership role changes.
544 */
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800545 private class InternalRoleListener implements MastershipListener {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800546 @Override
547 public void event(MastershipEvent event) {
Jon Hall7a8bfc62016-05-26 17:59:04 -0700548 if (MastershipEvent.Type.MASTER_CHANGED.equals(event.type())) {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800549 // only need new master events
Jon Hall7a8bfc62016-05-26 17:59:04 -0700550 eventExecutor.execute(() -> {
551 DeviceId deviceId = event.subject();
552 Device device = deviceService.getDevice(deviceId);
553 if (device == null) {
554 log.debug("Device {} doesn't exist, or isn't there yet", deviceId);
555 return;
556 }
557 if (clusterService.getLocalNode().id().equals(event.roleInfo().master())) {
558 updateDevice(device).ifPresent(ld -> updatePorts(ld, device.id()));
559 }
560 });
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800561 }
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800562 }
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800563 }
alshabib7911a052014-10-16 17:49:37 -0700564
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700565 private class DeviceEventProcessor implements Runnable {
566
567 DeviceEvent event;
568
569 DeviceEventProcessor(DeviceEvent event) {
570 this.event = event;
571 }
572
alshabib7911a052014-10-16 17:49:37 -0700573 @Override
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700574 public void run() {
alshabib7911a052014-10-16 17:49:37 -0700575 Device device = event.subject();
alshabibacd91832014-10-17 14:38:41 -0700576 Port port = event.port();
alshabibdfc7afb2014-10-21 20:13:27 -0700577 if (device == null) {
578 log.error("Device is null.");
579 return;
580 }
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700581 log.trace("{} {} {}", event.type(), event.subject(), event);
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700582 final DeviceId deviceId = device.id();
alshabib7911a052014-10-16 17:49:37 -0700583 switch (event.type()) {
584 case DEVICE_ADDED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700585 case DEVICE_UPDATED:
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700586 updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId));
alshabib7911a052014-10-16 17:49:37 -0700587 break;
588 case PORT_ADDED:
589 case PORT_UPDATED:
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700590 if (port.isEnabled()) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700591 updateDevice(device).ifPresent(ld -> updatePort(ld, port));
alshabib7911a052014-10-16 17:49:37 -0700592 } else {
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700593 log.debug("Port down {}", port);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700594 removePort(port);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600595 providerService.linksVanished(new ConnectPoint(port.element().id(),
596 port.number()));
alshabib7911a052014-10-16 17:49:37 -0700597 }
598 break;
599 case PORT_REMOVED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700600 log.debug("Port removed {}", 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 break;
605 case DEVICE_REMOVED:
606 case DEVICE_SUSPENDED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700607 log.debug("Device removed {}", deviceId);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700608 removeDevice(deviceId);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600609 providerService.linksVanished(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700610 break;
611 case DEVICE_AVAILABILITY_CHANGED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700612 if (deviceService.isAvailable(deviceId)) {
613 log.debug("Device up {}", deviceId);
alshabibe3af2652015-12-01 23:05:34 -0800614 updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId));
alshabib7911a052014-10-16 17:49:37 -0700615 } else {
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700616 log.debug("Device down {}", deviceId);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700617 removeDevice(deviceId);
Naoki Shiota399a0b32015-11-15 20:36:13 -0600618 providerService.linksVanished(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700619 }
620 break;
Jonathan Hart9de692c2015-04-23 11:45:47 -0700621 case PORT_STATS_UPDATED:
622 break;
alshabib7911a052014-10-16 17:49:37 -0700623 default:
624 log.debug("Unknown event {}", event);
625 }
626 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700627 }
alshabib7911a052014-10-16 17:49:37 -0700628
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700629 /**
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700630 * Processes device events.
631 */
632 private class InternalDeviceListener implements DeviceListener {
633 @Override
634 public void event(DeviceEvent event) {
635 if (event.type() == Type.PORT_STATS_UPDATED) {
636 return;
637 }
638
639 Runnable deviceEventProcessor = new DeviceEventProcessor(event);
640
641 eventExecutor.execute(deviceEventProcessor);
642 }
643 }
644
645 /**
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700646 * Processes incoming packets.
647 */
648 private class InternalPacketProcessor implements PacketProcessor {
alshabib7911a052014-10-16 17:49:37 -0700649 @Override
650 public void process(PacketContext context) {
Thomas Vachuska347cc872015-09-23 10:25:29 -0700651 if (context == null || context.isHandled()) {
alshabib4a179dc2014-10-17 17:17:01 -0700652 return;
653 }
Thomas Vachuska347cc872015-09-23 10:25:29 -0700654
655 Ethernet eth = context.inPacket().parsed();
656 if (eth == null || (eth.getEtherType() != TYPE_LLDP && eth.getEtherType() != TYPE_BSN)) {
657 return;
658 }
659
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700660 LinkDiscovery ld = discoverers.get(context.inPacket().receivedFrom().deviceId());
alshabib7911a052014-10-16 17:49:37 -0700661 if (ld == null) {
662 return;
663 }
664
Jonathan Hartb35540a2015-11-17 09:30:56 -0800665 if (ld.handleLldp(context)) {
alshabib7911a052014-10-16 17:49:37 -0700666 context.block();
667 }
668 }
669 }
670
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700671 /**
672 * Auxiliary task to keep device ports up to date.
673 */
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800674 private final class SyncDeviceInfoTask implements Runnable {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800675 @Override
676 public void run() {
677 if (Thread.currentThread().isInterrupted()) {
678 log.info("Interrupted, quitting");
679 return;
680 }
681 // check what deviceService sees, to see if we are missing anything
682 try {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700683 loadDevices();
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800684 } catch (Exception e) {
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700685 // Catch all exceptions to avoid task being suppressed
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800686 log.error("Exception thrown during synchronization process", e);
687 }
688 }
689 }
690
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700691 /**
692 * Auxiliary task for pruning stale links.
693 */
694 private class LinkPrunerTask implements Runnable {
695 @Override
696 public void run() {
697 if (Thread.currentThread().isInterrupted()) {
698 log.info("Interrupted, quitting");
699 return;
700 }
701
702 try {
703 // TODO: There is still a slight possibility of mastership
704 // change occurring right with link going stale. This will
705 // result in the stale link not being pruned.
706 Maps.filterEntries(linkTimes, e -> {
707 if (!masterService.isLocalMaster(e.getKey().dst().deviceId())) {
708 return true;
709 }
710 if (isStale(e.getValue())) {
711 providerService.linkVanished(new DefaultLinkDescription(e.getKey().src(),
712 e.getKey().dst(),
713 DIRECT));
714 return true;
715 }
716 return false;
717 }).clear();
718
719 } catch (Exception e) {
720 // Catch all exceptions to avoid task being suppressed
Ray Milkeye80e18f2016-06-02 16:44:14 -0700721 if (!shuttingDown) {
722 // Error condition
723 log.error("Exception thrown during link pruning process", e);
724 } else {
725 // Provider is shutting down, the error can be ignored
726 log.trace("Shutting down, ignoring error", e);
727 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700728 }
729 }
730
731 private boolean isStale(long lastSeen) {
732 return lastSeen < System.currentTimeMillis() - staleLinkAge;
733 }
734 }
735
736 /**
737 * Provides processing context for the device link discovery helpers.
738 */
Ray Milkey957390e2016-02-09 10:02:46 -0800739 private class InternalDiscoveryContext implements LinkDiscoveryContext {
Thomas Vachuska05453c92015-09-09 14:40:49 -0700740 @Override
741 public MastershipService mastershipService() {
742 return masterService;
743 }
744
745 @Override
746 public LinkProviderService providerService() {
747 return providerService;
748 }
749
750 @Override
751 public PacketService packetService() {
752 return packetService;
753 }
754
755 @Override
756 public long probeRate() {
757 return probeRate;
758 }
759
760 @Override
Jonathan Hartb35540a2015-11-17 09:30:56 -0800761 public boolean useBddp() {
762 return useBddp;
Thomas Vachuska05453c92015-09-09 14:40:49 -0700763 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700764
765 @Override
766 public void touchLink(LinkKey key) {
767 linkTimes.put(key, System.currentTimeMillis());
768 }
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800769
770 @Override
Ayaka Koshibe48229222016-05-16 18:04:26 -0700771 public DeviceService deviceService() {
772 return deviceService;
Ayaka Koshibe3ddb7b22015-12-10 17:32:59 -0800773 }
774
775 @Override
Ayaka Koshibe48229222016-05-16 18:04:26 -0700776 public String fingerprint() {
777 return buildSrcMac();
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800778 }
Thomas Vachuska05453c92015-09-09 14:40:49 -0700779 }
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700780
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800781 static final EnumSet<NetworkConfigEvent.Type> CONFIG_CHANGED
782 = EnumSet.of(NetworkConfigEvent.Type.CONFIG_ADDED,
783 NetworkConfigEvent.Type.CONFIG_UPDATED,
784 NetworkConfigEvent.Type.CONFIG_REMOVED);
785
Naoki Shiota399a0b32015-11-15 20:36:13 -0600786 private class InternalConfigListener implements NetworkConfigListener {
787
788 private synchronized void reconfigureSuppressionRules(SuppressionConfig cfg) {
789 if (cfg == null) {
Ray Milkey0a8ee912016-06-13 09:58:12 -0700790 log.debug("Suppression Config is null.");
Naoki Shiota399a0b32015-11-15 20:36:13 -0600791 return;
792 }
793
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800794 SuppressionRules newRules = new SuppressionRules(cfg.deviceTypes(),
Naoki Shiota399a0b32015-11-15 20:36:13 -0600795 cfg.annotation());
796
797 updateRules(newRules);
798 }
799
800 @Override
801 public void event(NetworkConfigEvent event) {
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700802 eventExecutor.execute(() -> {
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800803 if (event.configClass() == LinkDiscoveryFromDevice.class &&
804 CONFIG_CHANGED.contains(event.type())) {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800805
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800806 if (event.subject() instanceof DeviceId) {
807 final DeviceId did = (DeviceId) event.subject();
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800808 Device device = deviceService.getDevice(did);
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800809 updateDevice(device).ifPresent(ld -> updatePorts(ld, did));
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800810 }
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800811
812 } else if (event.configClass() == LinkDiscoveryFromPort.class &&
813 CONFIG_CHANGED.contains(event.type())) {
814
815 if (event.subject() instanceof ConnectPoint) {
816 ConnectPoint cp = (ConnectPoint) event.subject();
817 if (cp.elementId() instanceof DeviceId) {
818 final DeviceId did = (DeviceId) cp.elementId();
819 Device device = deviceService.getDevice(did);
820 Port port = deviceService.getPort(did, cp.port());
821 updateDevice(device).ifPresent(ld -> updatePort(ld, port));
822 }
823 }
824
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800825 } else if (event.configClass().equals(SuppressionConfig.class) &&
826 (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
827 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) {
828 SuppressionConfig cfg = cfgRegistry.getConfig(appId, SuppressionConfig.class);
829 reconfigureSuppressionRules(cfg);
830 log.trace("Network config reconfigured");
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800831 }
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800832 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600833 }
834 }
alshabib7911a052014-10-16 17:49:37 -0700835}