blob: 6613a7e3d60f42a7c8882623d6d0aba2c95557e6 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080018import com.google.common.collect.ImmutableMap;
19import com.google.common.collect.ImmutableSet;
alshabib7911a052014-10-16 17:49:37 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
Yuta HIGUCHI41289382014-12-19 17:47:12 -080023import org.apache.felix.scr.annotations.Modified;
24import org.apache.felix.scr.annotations.Property;
alshabib7911a052014-10-16 17:49:37 -070025import org.apache.felix.scr.annotations.Reference;
26import org.apache.felix.scr.annotations.ReferenceCardinality;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080027import org.onlab.packet.Ethernet;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070028import org.onosproject.cfg.ComponentConfigService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080029import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.mastership.MastershipEvent;
32import org.onosproject.mastership.MastershipListener;
33import org.onosproject.mastership.MastershipService;
34import org.onosproject.net.ConnectPoint;
35import org.onosproject.net.Device;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.Port;
38import org.onosproject.net.device.DeviceEvent;
39import org.onosproject.net.device.DeviceListener;
40import org.onosproject.net.device.DeviceService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080041import org.onosproject.net.flow.DefaultTrafficSelector;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080042import org.onosproject.net.flow.TrafficSelector;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.net.link.LinkProvider;
44import org.onosproject.net.link.LinkProviderRegistry;
45import org.onosproject.net.link.LinkProviderService;
46import org.onosproject.net.packet.PacketContext;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080047import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080048import org.onosproject.net.packet.PacketProcessor;
49import org.onosproject.net.packet.PacketService;
50import org.onosproject.net.provider.AbstractProvider;
51import org.onosproject.net.provider.ProviderId;
Yuta HIGUCHI41289382014-12-19 17:47:12 -080052import org.osgi.service.component.ComponentContext;
alshabib7911a052014-10-16 17:49:37 -070053import org.slf4j.Logger;
54
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080055import java.io.IOException;
56import java.util.Dictionary;
57import java.util.EnumSet;
58import java.util.Map;
Thomas Vachuska05453c92015-09-09 14:40:49 -070059import java.util.Properties;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080060import java.util.concurrent.ConcurrentHashMap;
61import java.util.concurrent.ScheduledExecutorService;
62
Thomas Vachuska05453c92015-09-09 14:40:49 -070063import static com.google.common.base.Strings.isNullOrEmpty;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080064import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
65import static java.util.concurrent.TimeUnit.SECONDS;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070066import static org.onlab.util.Tools.get;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080067import static org.onlab.util.Tools.groupedThreads;
68import static org.slf4j.LoggerFactory.getLogger;
Yuta HIGUCHI41289382014-12-19 17:47:12 -080069
alshabib7911a052014-10-16 17:49:37 -070070/**
Thomas Vachuska05453c92015-09-09 14:40:49 -070071 * Provider which uses LLDP and BDDP packets to detect network infrastructure links.
alshabib7911a052014-10-16 17:49:37 -070072 */
73@Component(immediate = true)
74public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
75
Thomas Vachuskafc52fec2015-05-18 19:13:56 -070076 private static final String PROVIDER_NAME = "org.onosproject.provider.lldp";
77
Thomas Vachuska05453c92015-09-09 14:40:49 -070078 private static final String FORMAT =
79 "Settings: enabled={}, useBDDP={}, probeRate={}, " +
80 "staleLinkAge={}, lldpSuppression={}";
Yuta HIGUCHI41289382014-12-19 17:47:12 -080081
alshabib7911a052014-10-16 17:49:37 -070082 private final Logger log = getLogger(getClass());
83
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080084 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected CoreService coreService;
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabib7911a052014-10-16 17:49:37 -070088 protected LinkProviderRegistry providerRegistry;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected DeviceService deviceService;
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -080094 protected PacketService packetService;
alshabib7911a052014-10-16 17:49:37 -070095
alshabib875d6262014-10-17 16:19:40 -070096 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected MastershipService masterService;
98
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070099 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected ComponentConfigService cfgService;
101
alshabib7911a052014-10-16 17:49:37 -0700102 private LinkProviderService providerService;
103
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800104 private ScheduledExecutorService executor;
105
Thomas Vachuska05453c92015-09-09 14:40:49 -0700106 private static final long INIT_DELAY = 5;
107 private static final long DELAY = 5;
108
109 private static final String PROP_ENABLED = "enabled";
110 @Property(name = PROP_ENABLED, boolValue = true,
111 label = "If false, link discovery is disabled")
112 private boolean enabled = false;
113
114 private static final String PROP_USE_BDDP = "useBDDP";
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700115 @Property(name = PROP_USE_BDDP, boolValue = true,
116 label = "Use BDDP for link discovery")
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800117 private boolean useBDDP = true;
alshabib7911a052014-10-16 17:49:37 -0700118
Thomas Vachuska05453c92015-09-09 14:40:49 -0700119 private static final String PROP_PROBE_RATE = "probeRate";
120 private static final int DEFAULT_PROBE_RATE = 3_000;
121 @Property(name = PROP_PROBE_RATE, intValue = DEFAULT_PROBE_RATE,
122 label = "LLDP and BDDP probe rate specified in millis")
123 private int probeRate = DEFAULT_PROBE_RATE;
Saurav Dasc313c402015-02-27 10:09:47 -0800124
Thomas Vachuska05453c92015-09-09 14:40:49 -0700125 private static final String PROP_STALE_LINK_AGE = "staleLinkAge";
126 private static final int DEFAULT_STALE_LINK_AGE = 10_000;
127 @Property(name = PROP_STALE_LINK_AGE, intValue = DEFAULT_STALE_LINK_AGE,
128 label = "Number of millis beyond which links will be considered stale")
129 private int staleLinkAge = DEFAULT_STALE_LINK_AGE;
alshabib7911a052014-10-16 17:49:37 -0700130
Thomas Vachuska05453c92015-09-09 14:40:49 -0700131 // FIXME: convert to use network config subsystem instead
132 private static final String PROP_LLDP_SUPPRESSION = "lldpSuppression";
133 private static final String DEFAULT_LLDP_SUPPRESSION_CONFIG = "../config/lldp_suppression.json";
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700134 @Property(name = PROP_LLDP_SUPPRESSION, value = DEFAULT_LLDP_SUPPRESSION_CONFIG,
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800135 label = "Path to LLDP suppression configuration file")
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700136 private String lldpSuppression = DEFAULT_LLDP_SUPPRESSION_CONFIG;
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800137
138
Thomas Vachuska05453c92015-09-09 14:40:49 -0700139 private final DiscoveryContext context = new InternalDiscoveryContext();
alshabib7911a052014-10-16 17:49:37 -0700140 private final InternalLinkProvider listener = new InternalLinkProvider();
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800141 private final InternalRoleListener roleListener = new InternalRoleListener();
142
alshabib7911a052014-10-16 17:49:37 -0700143 protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>();
144
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800145 private SuppressionRules rules;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800146 private ApplicationId appId;
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800147
alshabib7911a052014-10-16 17:49:37 -0700148 /**
149 * Creates an OpenFlow link provider.
150 */
151 public LLDPLinkProvider() {
Thomas Vachuskafc52fec2015-05-18 19:13:56 -0700152 super(new ProviderId("lldp", PROVIDER_NAME));
alshabib7911a052014-10-16 17:49:37 -0700153 }
154
155 @Activate
Saurav Dasc313c402015-02-27 10:09:47 -0800156 public void activate(ComponentContext context) {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700157 cfgService.registerProperties(getClass());
Thomas Vachuskafc52fec2015-05-18 19:13:56 -0700158 appId = coreService.registerApplication(PROVIDER_NAME);
Saurav Dasc313c402015-02-27 10:09:47 -0800159 modified(context);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700160 log.info("Started");
161 }
162
163 @Deactivate
164 public void deactivate() {
165 cfgService.unregisterProperties(getClass(), false);
166 disable();
167 log.info("Stopped");
168 }
169
170 @Modified
171 public void modified(ComponentContext context) {
172 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
173
174 boolean newEnabled, newUseBddp;
175 int newProbeRate, newStaleLinkAge;
176 String newLldpSuppression;
177 try {
178 String s = get(properties, PROP_ENABLED);
179 newEnabled = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim());
180
181 s = get(properties, PROP_USE_BDDP);
182 newUseBddp = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim());
183
184 s = get(properties, PROP_PROBE_RATE);
185 newProbeRate = isNullOrEmpty(s) ? probeRate : Integer.parseInt(s.trim());
186
187 s = get(properties, PROP_STALE_LINK_AGE);
188 newStaleLinkAge = isNullOrEmpty(s) ? staleLinkAge : Integer.parseInt(s.trim());
189
190 s = get(properties, PROP_LLDP_SUPPRESSION);
191 newLldpSuppression = isNullOrEmpty(s) ? DEFAULT_LLDP_SUPPRESSION_CONFIG : s;
192
193 } catch (NumberFormatException e) {
194 log.warn(e.getMessage());
195 newEnabled = enabled;
196 newUseBddp = useBDDP;
197 newProbeRate = probeRate;
198 newStaleLinkAge = staleLinkAge;
199 newLldpSuppression = lldpSuppression;
Saurav Dasc313c402015-02-27 10:09:47 -0800200 }
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800201
Thomas Vachuska05453c92015-09-09 14:40:49 -0700202 boolean wasEnabled = enabled;
203
204 enabled = newEnabled;
205 useBDDP = newUseBddp;
206 probeRate = newProbeRate;
207 staleLinkAge = newStaleLinkAge;
208 lldpSuppression = newLldpSuppression;
209
210 if (!wasEnabled && enabled) {
211 enable();
212 } else if (wasEnabled && !enabled) {
213 disable();
214 }
215
216 log.info(FORMAT, enabled, useBDDP, probeRate, staleLinkAge, lldpSuppression);
217 }
218
219 private void enable() {
alshabib7911a052014-10-16 17:49:37 -0700220 providerService = providerRegistry.register(this);
221 deviceService.addListener(listener);
Brian O'Connor3b783262015-07-29 17:49:24 -0700222 packetService.addProcessor(listener, PacketProcessor.advisor(0));
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800223 masterService.addListener(roleListener);
224
Thomas Vachuska05453c92015-09-09 14:40:49 -0700225 processDevices();
226
227 executor = newSingleThreadScheduledExecutor(groupedThreads("onos/device", "sync-%d"));
228 executor.scheduleAtFixedRate(new SyncDeviceInfoTask(), INIT_DELAY, DELAY, SECONDS);
229
230 loadSuppressionRules();
231 requestIntercepts();
232 }
233
234 private void disable() {
235 withdrawIntercepts();
236
237 providerRegistry.unregister(this);
238 deviceService.removeListener(listener);
239 packetService.removeProcessor(listener);
240 masterService.removeListener(roleListener);
241
242 if (executor != null) {
243 executor.shutdownNow();
244 }
245 discoverers.values().forEach(LinkDiscovery::stop);
246 discoverers.clear();
247
248 providerService = null;
249 }
250
251 private void processDevices() {
alshabib5dc5a342014-12-03 14:11:16 -0800252 for (Device device : deviceService.getAvailableDevices()) {
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800253 if (rules.isSuppressed(device)) {
254 log.debug("LinkDiscovery from {} disabled by configuration", device.id());
255 continue;
256 }
Thomas Vachuska05453c92015-09-09 14:40:49 -0700257 LinkDiscovery ld = new LinkDiscovery(device, context);
alshabibdfc7afb2014-10-21 20:13:27 -0700258 discoverers.put(device.id(), ld);
Jonathan Hart45066bc2015-07-28 11:18:34 -0700259 addPorts(ld, device.id());
alshabibdfc7afb2014-10-21 20:13:27 -0700260 }
alshabib7911a052014-10-16 17:49:37 -0700261 }
262
Jonathan Hart45066bc2015-07-28 11:18:34 -0700263 private void addPorts(LinkDiscovery discoverer, DeviceId deviceId) {
264 for (Port p : deviceService.getPorts(deviceId)) {
265 if (rules.isSuppressed(p)) {
266 continue;
267 }
268 if (!p.number().isLogical()) {
269 discoverer.addPort(p);
270 }
271 }
272 }
273
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800274 private void loadSuppressionRules() {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700275 SuppressionRulesStore store = new SuppressionRulesStore(lldpSuppression);
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800276 try {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700277 log.info("Reading suppression rules from {}", lldpSuppression);
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800278 rules = store.read();
279 } catch (IOException e) {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700280 log.info("Failed to load {}, using built-in rules", lldpSuppression);
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800281 // default rule to suppress ROADM to maintain compatibility
282 rules = new SuppressionRules(ImmutableSet.of(),
283 EnumSet.of(Device.Type.ROADM),
284 ImmutableMap.of());
285 }
286
287 // should refresh discoverers when we need dynamic reconfiguration
288 }
289
Charles M.C. Chane148de82015-05-06 12:38:21 +0800290 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700291 * Request packet intercepts.
Charles M.C. Chane148de82015-05-06 12:38:21 +0800292 */
Thomas Vachuska27bee092015-06-23 19:03:10 -0700293 private void requestIntercepts() {
294 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
295 selector.matchEthType(Ethernet.TYPE_LLDP);
296 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800297
Thomas Vachuska27bee092015-06-23 19:03:10 -0700298 selector.matchEthType(Ethernet.TYPE_BSN);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800299 if (useBDDP) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700300 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
301 } else {
302 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800303 }
304 }
305
Thomas Vachuska27bee092015-06-23 19:03:10 -0700306 /**
307 * Withdraw packet intercepts.
308 */
309 private void withdrawIntercepts() {
310 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
311 selector.matchEthType(Ethernet.TYPE_LLDP);
312 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
313 selector.matchEthType(Ethernet.TYPE_BSN);
314 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
315 }
316
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800317 private class InternalRoleListener implements MastershipListener {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800318 @Override
319 public void event(MastershipEvent event) {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800320 if (MastershipEvent.Type.BACKUPS_CHANGED.equals(event.type())) {
321 // only need new master events
322 return;
323 }
324
325 DeviceId deviceId = event.subject();
326 Device device = deviceService.getDevice(deviceId);
327 if (device == null) {
Thomas Vachuska3358af22015-05-19 18:40:34 -0700328 log.debug("Device {} doesn't exist, or isn't there yet", deviceId);
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800329 return;
330 }
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800331 if (rules.isSuppressed(device)) {
332 return;
333 }
Thomas Vachuska05453c92015-09-09 14:40:49 -0700334 discoverers.computeIfAbsent(deviceId, k -> new LinkDiscovery(device, context));
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800335 }
336
337 }
alshabib7911a052014-10-16 17:49:37 -0700338
339 private class InternalLinkProvider implements PacketProcessor, DeviceListener {
alshabib7911a052014-10-16 17:49:37 -0700340 @Override
341 public void event(DeviceEvent event) {
Thomas Vachuska05453c92015-09-09 14:40:49 -0700342 LinkDiscovery ld;
alshabib7911a052014-10-16 17:49:37 -0700343 Device device = event.subject();
alshabibacd91832014-10-17 14:38:41 -0700344 Port port = event.port();
alshabibdfc7afb2014-10-21 20:13:27 -0700345 if (device == null) {
346 log.error("Device is null.");
347 return;
348 }
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700349 log.trace("{} {} {}", event.type(), event.subject(), event);
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700350 final DeviceId deviceId = device.id();
alshabib7911a052014-10-16 17:49:37 -0700351 switch (event.type()) {
352 case DEVICE_ADDED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700353 case DEVICE_UPDATED:
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800354 synchronized (discoverers) {
355 ld = discoverers.get(deviceId);
356 if (ld == null) {
357 if (rules.isSuppressed(device)) {
358 log.debug("LinkDiscovery from {} disabled by configuration", device.id());
359 return;
360 }
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700361 log.debug("Device added ({}) {}", event.type(), deviceId);
Thomas Vachuska05453c92015-09-09 14:40:49 -0700362 discoverers.put(deviceId, new LinkDiscovery(device, context));
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800363 } else {
364 if (ld.isStopped()) {
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700365 log.debug("Device restarted ({}) {}", event.type(), deviceId);
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800366 ld.start();
367 }
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800368 }
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700369 }
alshabib7911a052014-10-16 17:49:37 -0700370 break;
371 case PORT_ADDED:
372 case PORT_UPDATED:
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700373 if (port.isEnabled()) {
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700374 ld = discoverers.get(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700375 if (ld == null) {
376 return;
377 }
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800378 if (rules.isSuppressed(port)) {
379 log.debug("LinkDiscovery from {}@{} disabled by configuration",
380 port.number(), device.id());
381 return;
382 }
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -0700383 if (!port.number().isLogical()) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700384 log.debug("Port added {}", port);
Yuta HIGUCHI00b476f2014-10-25 21:33:07 -0700385 ld.addPort(port);
386 }
alshabib7911a052014-10-16 17:49:37 -0700387 } else {
Yuta HIGUCHIf6725882014-10-29 15:25:51 -0700388 log.debug("Port down {}", port);
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700389 ConnectPoint point = new ConnectPoint(deviceId, port.number());
alshabib7911a052014-10-16 17:49:37 -0700390 providerService.linksVanished(point);
391 }
392 break;
393 case PORT_REMOVED:
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700394 log.debug("Port removed {}", port);
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700395 ConnectPoint point = new ConnectPoint(deviceId, port.number());
alshabib7911a052014-10-16 17:49:37 -0700396 providerService.linksVanished(point);
alshabib4785eec2014-12-04 16:45:45 -0800397
alshabib7911a052014-10-16 17:49:37 -0700398 break;
399 case DEVICE_REMOVED:
400 case DEVICE_SUSPENDED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700401 log.debug("Device removed {}", deviceId);
402 ld = discoverers.get(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700403 if (ld == null) {
404 return;
405 }
406 ld.stop();
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700407 providerService.linksVanished(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700408 break;
409 case DEVICE_AVAILABILITY_CHANGED:
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700410 ld = discoverers.get(deviceId);
alshabib7911a052014-10-16 17:49:37 -0700411 if (ld == null) {
412 return;
413 }
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700414 if (deviceService.isAvailable(deviceId)) {
415 log.debug("Device up {}", deviceId);
alshabib7911a052014-10-16 17:49:37 -0700416 ld.start();
417 } else {
Yuta HIGUCHId19f6702014-10-31 15:23:25 -0700418 providerService.linksVanished(deviceId);
419 log.debug("Device down {}", deviceId);
alshabib7911a052014-10-16 17:49:37 -0700420 ld.stop();
421 }
422 break;
Jonathan Hart9de692c2015-04-23 11:45:47 -0700423 case PORT_STATS_UPDATED:
424 break;
alshabib7911a052014-10-16 17:49:37 -0700425 default:
426 log.debug("Unknown event {}", event);
427 }
428 }
429
430 @Override
431 public void process(PacketContext context) {
alshabib4a179dc2014-10-17 17:17:01 -0700432 if (context == null) {
433 return;
434 }
Thomas Vachuska96f3ea72015-09-08 13:50:12 -0700435 LinkDiscovery ld = discoverers.get(context.inPacket().receivedFrom().deviceId());
alshabib7911a052014-10-16 17:49:37 -0700436 if (ld == null) {
437 return;
438 }
439
440 if (ld.handleLLDP(context)) {
441 context.block();
442 }
443 }
444 }
445
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800446 private final class SyncDeviceInfoTask implements Runnable {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800447 @Override
448 public void run() {
449 if (Thread.currentThread().isInterrupted()) {
450 log.info("Interrupted, quitting");
451 return;
452 }
453 // check what deviceService sees, to see if we are missing anything
454 try {
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800455 for (Device dev : deviceService.getDevices()) {
Yuta HIGUCHI41289382014-12-19 17:47:12 -0800456 if (rules.isSuppressed(dev)) {
457 continue;
458 }
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800459 DeviceId did = dev.id();
460 synchronized (discoverers) {
Thomas Vachuska05453c92015-09-09 14:40:49 -0700461 LinkDiscovery ld = discoverers
462 .computeIfAbsent(did, k -> new LinkDiscovery(dev, context));
463 addPorts(ld, did);
Ayaka Koshibeccfa94c2014-11-20 11:15:52 -0800464 }
465 }
466 } catch (Exception e) {
467 // catch all Exception to avoid Scheduled task being suppressed.
468 log.error("Exception thrown during synchronization process", e);
469 }
470 }
471 }
472
Thomas Vachuska05453c92015-09-09 14:40:49 -0700473 private class InternalDiscoveryContext implements DiscoveryContext {
474 @Override
475 public MastershipService mastershipService() {
476 return masterService;
477 }
478
479 @Override
480 public LinkProviderService providerService() {
481 return providerService;
482 }
483
484 @Override
485 public PacketService packetService() {
486 return packetService;
487 }
488
489 @Override
490 public long probeRate() {
491 return probeRate;
492 }
493
494 @Override
495 public long staleLinkAge() {
496 return staleLinkAge;
497 }
498
499 @Override
500 public boolean useBDDP() {
501 return useBDDP;
502 }
503 }
alshabib7911a052014-10-16 17:49:37 -0700504}