blob: 10a845ffc194943256c01a320a359b71b8e129c4 [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.host.impl;
alshabibe1cf87d2014-10-17 09:23:50 -070017
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
Thomas Vachuska33601602014-11-19 03:32:15 -080021import org.apache.felix.scr.annotations.Modified;
22import org.apache.felix.scr.annotations.Property;
alshabibe1cf87d2014-10-17 09:23:50 -070023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
Jonathan Harte8600eb2015-01-12 10:30:45 -080025import org.onlab.packet.ARP;
26import org.onlab.packet.Ethernet;
Pavlin Radoslavovd6612f92015-02-23 13:53:32 -080027import org.onlab.packet.ICMP6;
Thomas Vachuskaf845cf62015-03-24 10:13:09 -070028import org.onlab.packet.IPacket;
Jonathan Harte8600eb2015-01-12 10:30:45 -080029import org.onlab.packet.IPv6;
30import org.onlab.packet.IpAddress;
Charles M.C. Chan956cb692015-04-26 18:49:39 +080031import org.onlab.packet.MacAddress;
Jonathan Harte8600eb2015-01-12 10:30:45 -080032import org.onlab.packet.VlanId;
Charles M.C. Chan956cb692015-04-26 18:49:39 +080033import org.onlab.packet.ipv6.IExtensionHeader;
Jonathan Harte8600eb2015-01-12 10:30:45 -080034import org.onlab.packet.ndp.NeighborAdvertisement;
35import org.onlab.packet.ndp.NeighborSolicitation;
Charles M.C. Chan441d7da2015-03-17 21:03:39 +080036import org.onlab.packet.ndp.RouterAdvertisement;
37import org.onlab.packet.ndp.RouterSolicitation;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070038import org.onosproject.cfg.ComponentConfigService;
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.net.ConnectPoint;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080042import org.onosproject.net.Device;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.net.Host;
44import org.onosproject.net.HostId;
45import org.onosproject.net.HostLocation;
46import org.onosproject.net.device.DeviceEvent;
47import org.onosproject.net.device.DeviceListener;
48import org.onosproject.net.device.DeviceService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080049import org.onosproject.net.flow.DefaultTrafficSelector;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080050import org.onosproject.net.flow.TrafficSelector;
Brian O'Connorabafb502014-12-02 22:26:20 -080051import org.onosproject.net.host.DefaultHostDescription;
52import org.onosproject.net.host.HostDescription;
53import org.onosproject.net.host.HostProvider;
54import org.onosproject.net.host.HostProviderRegistry;
55import org.onosproject.net.host.HostProviderService;
56import org.onosproject.net.host.HostService;
57import org.onosproject.net.packet.PacketContext;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080058import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080059import org.onosproject.net.packet.PacketProcessor;
60import org.onosproject.net.packet.PacketService;
61import org.onosproject.net.provider.AbstractProvider;
62import org.onosproject.net.provider.ProviderId;
63import org.onosproject.net.topology.Topology;
64import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33601602014-11-19 03:32:15 -080065import org.osgi.service.component.ComponentContext;
alshabibe1cf87d2014-10-17 09:23:50 -070066import org.slf4j.Logger;
67
Thomas Vachuskaf845cf62015-03-24 10:13:09 -070068import java.util.Dictionary;
69import java.util.Set;
70
71import static com.google.common.base.Strings.isNullOrEmpty;
72import static org.slf4j.LoggerFactory.getLogger;
73
alshabibe1cf87d2014-10-17 09:23:50 -070074/**
75 * Provider which uses an OpenFlow controller to detect network
76 * end-station hosts.
77 */
78@Component(immediate = true)
79public class HostLocationProvider extends AbstractProvider implements HostProvider {
80
81 private final Logger log = getLogger(getClass());
82
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080083 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected CoreService coreService;
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibe1cf87d2014-10-17 09:23:50 -070087 protected HostProviderRegistry providerRegistry;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pavlin Radoslavovd6612f92015-02-23 13:53:32 -080090 protected PacketService packetService;
alshabibe1cf87d2014-10-17 09:23:50 -070091
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected TopologyService topologyService;
94
Thomas Vachuska33601602014-11-19 03:32:15 -080095 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected HostService hostService;
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected DeviceService deviceService;
100
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected ComponentConfigService cfgService;
103
alshabibe1cf87d2014-10-17 09:23:50 -0700104 private HostProviderService providerService;
105
106 private final InternalHostProvider processor = new InternalHostProvider();
Thomas Vachuska33601602014-11-19 03:32:15 -0800107 private final DeviceListener deviceListener = new InternalDeviceListener();
108
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800109 private ApplicationId appId;
110
Thomas Vachuska33601602014-11-19 03:32:15 -0800111 @Property(name = "hostRemovalEnabled", boolValue = true,
112 label = "Enable host removal on port/device down events")
113 private boolean hostRemovalEnabled = true;
alshabibe1cf87d2014-10-17 09:23:50 -0700114
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800115 @Property(name = "ipv6NeighborDiscovery", boolValue = false,
Thomas Vachuska27bee092015-06-23 19:03:10 -0700116 label = "Enable using IPv6 Neighbor Discovery by the " +
117 "Host Location Provider; default is false")
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800118 private boolean ipv6NeighborDiscovery = false;
alshabibe1cf87d2014-10-17 09:23:50 -0700119
120 /**
121 * Creates an OpenFlow host provider.
122 */
123 public HostLocationProvider() {
Brian O'Connorabafb502014-12-02 22:26:20 -0800124 super(new ProviderId("of", "org.onosproject.provider.host"));
alshabibe1cf87d2014-10-17 09:23:50 -0700125 }
126
127 @Activate
Thomas Vachuska33601602014-11-19 03:32:15 -0800128 public void activate(ComponentContext context) {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700129 cfgService.registerProperties(getClass());
130 appId = coreService.registerApplication("org.onosproject.provider.host");
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800131
alshabibe1cf87d2014-10-17 09:23:50 -0700132 providerService = providerRegistry.register(this);
Pavlin Radoslavovd6612f92015-02-23 13:53:32 -0800133 packetService.addProcessor(processor, 1);
Thomas Vachuska33601602014-11-19 03:32:15 -0800134 deviceService.addListener(deviceListener);
Charles M.C. Chane148de82015-05-06 12:38:21 +0800135 readComponentConfiguration(context);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700136 requestIntercepts();
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800137
Charles M.C. Chane148de82015-05-06 12:38:21 +0800138 log.info("Started with Application ID {}", appId.id());
139 }
140
141 @Deactivate
142 public void deactivate() {
Charles M.C. Chane148de82015-05-06 12:38:21 +0800143 cfgService.unregisterProperties(getClass(), false);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700144
145 withdrawIntercepts();
146
Charles M.C. Chane148de82015-05-06 12:38:21 +0800147 providerRegistry.unregister(this);
148 packetService.removeProcessor(processor);
149 deviceService.removeListener(deviceListener);
150 providerService = null;
151 log.info("Stopped");
152 }
153
154 @Modified
155 public void modified(ComponentContext context) {
Charles M.C. Chane148de82015-05-06 12:38:21 +0800156 readComponentConfiguration(context);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700157 requestIntercepts();
Charles M.C. Chane148de82015-05-06 12:38:21 +0800158 }
159
160 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700161 * Request packet intercepts.
Charles M.C. Chane148de82015-05-06 12:38:21 +0800162 */
Thomas Vachuska27bee092015-06-23 19:03:10 -0700163 private void requestIntercepts() {
164 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
165 selector.matchEthType(Ethernet.TYPE_ARP);
166 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800167
Thomas Vachuska27bee092015-06-23 19:03:10 -0700168 // IPv6 Neighbor Solicitation packet.
169 selector.matchEthType(Ethernet.TYPE_IPV6);
170 selector.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
171 selector.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800172 if (ipv6NeighborDiscovery) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700173 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
174 } else {
175 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800176 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700177
178 // IPv6 Neighbor Advertisement packet.
179 selector.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
180 if (ipv6NeighborDiscovery) {
181 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
182 } else {
183 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
184 }
185 }
186
187 /**
188 * Withdraw packet intercepts.
189 */
190 private void withdrawIntercepts() {
191 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
192 selector.matchEthType(Ethernet.TYPE_ARP);
Aaron Kruglikov07a923d2015-07-03 13:30:57 -0700193 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700194
195 // IPv6 Neighbor Solicitation packet.
196 selector.matchEthType(Ethernet.TYPE_IPV6);
197 selector.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
198 selector.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
199 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
200
201 // IPv6 Neighbor Advertisement packet.
202 selector.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
203 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800204 }
205
206 /**
207 * Extracts properties from the component configuration context.
208 *
209 * @param context the component context
210 */
211 private void readComponentConfiguration(ComponentContext context) {
212 Dictionary<?, ?> properties = context.getProperties();
213 Boolean flag;
214
215 flag = isPropertyEnabled(properties, "hostRemovalEnabled");
216 if (flag == null) {
217 log.info("Host removal on port/device down events is not configured, " +
Thomas Vachuska27bee092015-06-23 19:03:10 -0700218 "using current value of {}", hostRemovalEnabled);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800219 } else {
220 hostRemovalEnabled = flag;
221 log.info("Configured. Host removal on port/device down events is {}",
222 hostRemovalEnabled ? "enabled" : "disabled");
Thomas Vachuska33601602014-11-19 03:32:15 -0800223 }
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800224
225 flag = isPropertyEnabled(properties, "ipv6NeighborDiscovery");
226 if (flag == null) {
227 log.info("Using IPv6 Neighbor Discovery is not configured, " +
Thomas Vachuska27bee092015-06-23 19:03:10 -0700228 "using current value of {}", ipv6NeighborDiscovery);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800229 } else {
230 ipv6NeighborDiscovery = flag;
231 log.info("Configured. Using IPv6 Neighbor Discovery is {}",
232 ipv6NeighborDiscovery ? "enabled" : "disabled");
233 }
234 }
235
236 /**
237 * Check property name is defined and set to true.
238 *
Thomas Vachuska27bee092015-06-23 19:03:10 -0700239 * @param properties properties to be looked up
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800240 * @param propertyName the name of the property to look up
241 * @return value when the propertyName is defined or return null
242 */
243 private static Boolean isPropertyEnabled(Dictionary<?, ?> properties,
244 String propertyName) {
245 Boolean value = null;
246 try {
247 String s = (String) properties.get(propertyName);
248 value = isNullOrEmpty(s) ? null : s.trim().equals("true");
249 } catch (ClassCastException e) {
250 // No propertyName defined.
251 value = null;
252 }
253 return value;
Thomas Vachuska33601602014-11-19 03:32:15 -0800254 }
255
alshabibe1cf87d2014-10-17 09:23:50 -0700256 @Override
257 public void triggerProbe(Host host) {
258 log.info("Triggering probe on device {}", host);
259 }
260
261 private class InternalHostProvider implements PacketProcessor {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800262 /**
263 * Update host location only.
264 *
Thomas Vachuska27bee092015-06-23 19:03:10 -0700265 * @param hid host ID
266 * @param mac source Mac address
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800267 * @param vlan VLAN ID
268 * @param hloc host location
269 */
270 private void updateLocation(HostId hid, MacAddress mac,
Thomas Vachuska27bee092015-06-23 19:03:10 -0700271 VlanId vlan, HostLocation hloc) {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800272 HostDescription desc = new DefaultHostDescription(mac, vlan, hloc);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700273 try {
274 providerService.hostDetected(hid, desc);
275 } catch (IllegalStateException e) {
276 log.debug("Host {} suppressed", hid);
277 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800278 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700279
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800280 /**
281 * Update host location and IP address.
282 *
Thomas Vachuska27bee092015-06-23 19:03:10 -0700283 * @param hid host ID
284 * @param mac source Mac address
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800285 * @param vlan VLAN ID
286 * @param hloc host location
Thomas Vachuska27bee092015-06-23 19:03:10 -0700287 * @param ip source IP address
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800288 */
289 private void updateLocationIP(HostId hid, MacAddress mac,
290 VlanId vlan, HostLocation hloc,
291 IpAddress ip) {
292 HostDescription desc = new DefaultHostDescription(mac, vlan, hloc, ip);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700293 try {
294 providerService.hostDetected(hid, desc);
295 } catch (IllegalStateException e) {
296 log.debug("Host {} suppressed", hid);
297 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800298 }
alshabibe1cf87d2014-10-17 09:23:50 -0700299
300 @Override
301 public void process(PacketContext context) {
alshabib4a179dc2014-10-17 17:17:01 -0700302 if (context == null) {
303 return;
304 }
alshabibe1cf87d2014-10-17 09:23:50 -0700305
Thomas Vachuskaf845cf62015-03-24 10:13:09 -0700306 Ethernet eth = context.inPacket().parsed();
Jonathan Harte8600eb2015-01-12 10:30:45 -0800307 if (eth == null) {
308 return;
309 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800310 MacAddress srcMac = eth.getSourceMAC();
Jonathan Harte8600eb2015-01-12 10:30:45 -0800311
alshabibe1cf87d2014-10-17 09:23:50 -0700312 VlanId vlan = VlanId.vlanId(eth.getVlanID());
313 ConnectPoint heardOn = context.inPacket().receivedFrom();
314
Thomas Vachuskaf845cf62015-03-24 10:13:09 -0700315 // If this arrived on control port, bail out.
316 if (heardOn.port().isLogical()) {
317 return;
318 }
319
alshabibe1cf87d2014-10-17 09:23:50 -0700320 // If this is not an edge port, bail out.
321 Topology topology = topologyService.currentTopology();
322 if (topologyService.isInfrastructure(topology, heardOn)) {
323 return;
324 }
325
Pavlin Radoslavovd6612f92015-02-23 13:53:32 -0800326 HostLocation hloc =
Thomas Vachuska27bee092015-06-23 19:03:10 -0700327 new HostLocation(heardOn, System.currentTimeMillis());
alshabibe1cf87d2014-10-17 09:23:50 -0700328
329 HostId hid = HostId.hostId(eth.getSourceMAC(), vlan);
330
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800331 // ARP: possible new hosts, update both location and IP
alshabibe1cf87d2014-10-17 09:23:50 -0700332 if (eth.getEtherType() == Ethernet.TYPE_ARP) {
333 ARP arp = (ARP) eth.getPayload();
Pavlin Radoslavovd6612f92015-02-23 13:53:32 -0800334 IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET,
335 arp.getSenderProtocolAddress());
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800336 updateLocationIP(hid, srcMac, vlan, hloc, ip);
alshabibe1cf87d2014-10-17 09:23:50 -0700337
Thomas Vachuska27bee092015-06-23 19:03:10 -0700338 // IPv4: update location only
alshabibe1cf87d2014-10-17 09:23:50 -0700339 } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800340 updateLocation(hid, srcMac, vlan, hloc);
alshabibe1cf87d2014-10-17 09:23:50 -0700341
Thomas Vachuska27bee092015-06-23 19:03:10 -0700342 //
343 // NeighborAdvertisement and NeighborSolicitation: possible
344 // new hosts, update both location and IP.
345 //
346 // IPv6: update location only
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800347 } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800348 IPv6 ipv6 = (IPv6) eth.getPayload();
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800349 IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET6,
Thomas Vachuska27bee092015-06-23 19:03:10 -0700350 ipv6.getSourceAddress());
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800351
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800352 // skip extension headers
353 IPacket pkt = ipv6;
354 while (pkt.getPayload() != null &&
355 pkt.getPayload() instanceof IExtensionHeader) {
356 pkt = pkt.getPayload();
357 }
358
359 // Neighbor Discovery Protocol
Charles M.C. Chan9148d2d2015-04-27 03:36:39 +0800360 pkt = pkt.getPayload();
361 if (pkt != null && pkt instanceof ICMP6) {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800362 pkt = pkt.getPayload();
363 // RouterSolicitation, RouterAdvertisement
Charles M.C. Chan9148d2d2015-04-27 03:36:39 +0800364 if (pkt != null && (pkt instanceof RouterAdvertisement ||
Thomas Vachuska27bee092015-06-23 19:03:10 -0700365 pkt instanceof RouterSolicitation)) {
Charles M.C. Chan441d7da2015-03-17 21:03:39 +0800366 return;
367 }
Charles M.C. Chan9148d2d2015-04-27 03:36:39 +0800368 if (pkt != null && (pkt instanceof NeighborSolicitation ||
Thomas Vachuska27bee092015-06-23 19:03:10 -0700369 pkt instanceof NeighborAdvertisement)) {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800370 // Duplicate Address Detection
371 if (ip.isZero()) {
Charles M.C. Chan441d7da2015-03-17 21:03:39 +0800372 return;
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800373 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800374 // NeighborSolicitation, NeighborAdvertisement
375 updateLocationIP(hid, srcMac, vlan, hloc, ip);
376 return;
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800377 }
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800378 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800379
380 // multicast
381 if (eth.isMulticast()) {
382 return;
383 }
384
385 // normal IPv6 packets
386 updateLocation(hid, srcMac, vlan, hloc);
alshabibe1cf87d2014-10-17 09:23:50 -0700387 }
388 }
389 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800390
391 // Auxiliary listener to device events.
392 private class InternalDeviceListener implements DeviceListener {
393 @Override
394 public void event(DeviceEvent event) {
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800395 Device device = event.subject();
396 switch (event.type()) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700397 case DEVICE_ADDED:
398 break;
399 case DEVICE_AVAILABILITY_CHANGED:
400 if (hostRemovalEnabled &&
401 !deviceService.isAvailable(device.id())) {
402 removeHosts(hostService.getConnectedHosts(device.id()));
403 }
404 break;
405 case DEVICE_SUSPENDED:
406 case DEVICE_UPDATED:
407 // Nothing to do?
408 break;
409 case DEVICE_REMOVED:
410 if (hostRemovalEnabled) {
411 removeHosts(hostService.getConnectedHosts(device.id()));
412 }
413 break;
414 case PORT_ADDED:
415 break;
416 case PORT_UPDATED:
417 if (hostRemovalEnabled) {
418 ConnectPoint point =
419 new ConnectPoint(device.id(), event.port().number());
420 removeHosts(hostService.getConnectedHosts(point));
421 }
422 break;
423 case PORT_REMOVED:
424 // Nothing to do?
425 break;
426 default:
427 break;
Thomas Vachuska33601602014-11-19 03:32:15 -0800428 }
429 }
430 }
431
432 // Signals host vanish for all specified hosts.
433 private void removeHosts(Set<Host> hosts) {
434 for (Host host : hosts) {
435 providerService.hostVanished(host.id());
436 }
437 }
438
alshabibe1cf87d2014-10-17 09:23:50 -0700439}