blob: 46b7d88bf2d5a9a59b17a85906ac142abb7a8193 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-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.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;
Jian Lid9b5f552016-03-11 18:15:31 -080038import org.onlab.util.Tools;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070039import org.onosproject.cfg.ComponentConfigService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080040import org.onosproject.core.ApplicationId;
41import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.ConnectPoint;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080043import org.onosproject.net.Device;
Brian O'Connorabafb502014-12-02 22:26:20 -080044import org.onosproject.net.Host;
45import org.onosproject.net.HostId;
46import org.onosproject.net.HostLocation;
47import org.onosproject.net.device.DeviceEvent;
48import org.onosproject.net.device.DeviceListener;
49import org.onosproject.net.device.DeviceService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080050import org.onosproject.net.flow.DefaultTrafficSelector;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080051import org.onosproject.net.flow.TrafficSelector;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.net.host.DefaultHostDescription;
53import org.onosproject.net.host.HostDescription;
54import org.onosproject.net.host.HostProvider;
55import org.onosproject.net.host.HostProviderRegistry;
56import org.onosproject.net.host.HostProviderService;
57import org.onosproject.net.host.HostService;
58import org.onosproject.net.packet.PacketContext;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080059import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080060import org.onosproject.net.packet.PacketProcessor;
61import org.onosproject.net.packet.PacketService;
62import org.onosproject.net.provider.AbstractProvider;
63import org.onosproject.net.provider.ProviderId;
64import org.onosproject.net.topology.Topology;
65import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33601602014-11-19 03:32:15 -080066import org.osgi.service.component.ComponentContext;
alshabibe1cf87d2014-10-17 09:23:50 -070067import org.slf4j.Logger;
68
Thomas Vachuskaf845cf62015-03-24 10:13:09 -070069import java.util.Dictionary;
70import java.util.Set;
Madan Jampania3770c32015-12-11 12:07:41 -080071import java.util.concurrent.ExecutorService;
Thomas Vachuskaf845cf62015-03-24 10:13:09 -070072
Madan Jampania3770c32015-12-11 12:07:41 -080073import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
74import static org.onlab.util.Tools.groupedThreads;
Thomas Vachuskaf845cf62015-03-24 10:13:09 -070075import static org.slf4j.LoggerFactory.getLogger;
76
alshabibe1cf87d2014-10-17 09:23:50 -070077/**
Thomas Vachuskaec9c7dd2015-09-03 18:30:04 -070078 * Provider which uses an OpenFlow controller to detect network end-station
79 * hosts.
alshabibe1cf87d2014-10-17 09:23:50 -070080 */
81@Component(immediate = true)
82public class HostLocationProvider extends AbstractProvider implements HostProvider {
83
84 private final Logger log = getLogger(getClass());
85
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080086 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected CoreService coreService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
alshabibe1cf87d2014-10-17 09:23:50 -070090 protected HostProviderRegistry providerRegistry;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Pavlin Radoslavovd6612f92015-02-23 13:53:32 -080093 protected PacketService packetService;
alshabibe1cf87d2014-10-17 09:23:50 -070094
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected TopologyService topologyService;
97
Thomas Vachuska33601602014-11-19 03:32:15 -080098 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected HostService hostService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected DeviceService deviceService;
103
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected ComponentConfigService cfgService;
106
alshabibe1cf87d2014-10-17 09:23:50 -0700107 private HostProviderService providerService;
108
109 private final InternalHostProvider processor = new InternalHostProvider();
Thomas Vachuska33601602014-11-19 03:32:15 -0800110 private final DeviceListener deviceListener = new InternalDeviceListener();
111
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800112 private ApplicationId appId;
113
Thomas Vachuska33601602014-11-19 03:32:15 -0800114 @Property(name = "hostRemovalEnabled", boolValue = true,
115 label = "Enable host removal on port/device down events")
116 private boolean hostRemovalEnabled = true;
alshabibe1cf87d2014-10-17 09:23:50 -0700117
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800118 @Property(name = "ipv6NeighborDiscovery", boolValue = false,
Thomas Vachuska27bee092015-06-23 19:03:10 -0700119 label = "Enable using IPv6 Neighbor Discovery by the " +
120 "Host Location Provider; default is false")
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800121 private boolean ipv6NeighborDiscovery = false;
alshabibe1cf87d2014-10-17 09:23:50 -0700122
Jonathan Hart9af322d2016-01-06 17:42:04 -0800123 @Property(name = "requestInterceptsEnabled", boolValue = true,
124 label = "Enable requesting packet intercepts")
125 private boolean requestInterceptsEnabled = true;
126
Madan Jampania3770c32015-12-11 12:07:41 -0800127 protected ExecutorService eventHandler;
128
alshabibe1cf87d2014-10-17 09:23:50 -0700129 /**
130 * Creates an OpenFlow host provider.
131 */
132 public HostLocationProvider() {
Brian O'Connorabafb502014-12-02 22:26:20 -0800133 super(new ProviderId("of", "org.onosproject.provider.host"));
alshabibe1cf87d2014-10-17 09:23:50 -0700134 }
135
136 @Activate
Thomas Vachuska33601602014-11-19 03:32:15 -0800137 public void activate(ComponentContext context) {
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700138 cfgService.registerProperties(getClass());
139 appId = coreService.registerApplication("org.onosproject.provider.host");
Jonathan Hart9af322d2016-01-06 17:42:04 -0800140 eventHandler = newSingleThreadScheduledExecutor(
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700141 groupedThreads("onos/host-loc-provider", "event-handler", log));
alshabibe1cf87d2014-10-17 09:23:50 -0700142 providerService = providerRegistry.register(this);
Brian O'Connor3b783262015-07-29 17:49:24 -0700143 packetService.addProcessor(processor, PacketProcessor.advisor(1));
Thomas Vachuska33601602014-11-19 03:32:15 -0800144 deviceService.addListener(deviceListener);
Jonathan Hart9af322d2016-01-06 17:42:04 -0800145
146 modified(context);
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800147
Charles M.C. Chane148de82015-05-06 12:38:21 +0800148 log.info("Started with Application ID {}", appId.id());
149 }
150
151 @Deactivate
152 public void deactivate() {
Charles M.C. Chane148de82015-05-06 12:38:21 +0800153 cfgService.unregisterProperties(getClass(), false);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700154
155 withdrawIntercepts();
156
Charles M.C. Chane148de82015-05-06 12:38:21 +0800157 providerRegistry.unregister(this);
158 packetService.removeProcessor(processor);
159 deviceService.removeListener(deviceListener);
Madan Jampania3770c32015-12-11 12:07:41 -0800160 eventHandler.shutdown();
Charles M.C. Chane148de82015-05-06 12:38:21 +0800161 providerService = null;
162 log.info("Stopped");
163 }
164
165 @Modified
166 public void modified(ComponentContext context) {
Charles M.C. Chane148de82015-05-06 12:38:21 +0800167 readComponentConfiguration(context);
Jonathan Hart9af322d2016-01-06 17:42:04 -0800168
169 if (requestInterceptsEnabled) {
170 requestIntercepts();
171 } else {
172 withdrawIntercepts();
173 }
Charles M.C. Chane148de82015-05-06 12:38:21 +0800174 }
175
176 /**
Thomas Vachuska27bee092015-06-23 19:03:10 -0700177 * Request packet intercepts.
Charles M.C. Chane148de82015-05-06 12:38:21 +0800178 */
Thomas Vachuska27bee092015-06-23 19:03:10 -0700179 private void requestIntercepts() {
180 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
181 selector.matchEthType(Ethernet.TYPE_ARP);
182 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800183
Thomas Vachuska27bee092015-06-23 19:03:10 -0700184 // IPv6 Neighbor Solicitation packet.
185 selector.matchEthType(Ethernet.TYPE_IPV6);
186 selector.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
187 selector.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800188 if (ipv6NeighborDiscovery) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700189 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
190 } else {
191 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800192 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700193
194 // IPv6 Neighbor Advertisement packet.
195 selector.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
196 if (ipv6NeighborDiscovery) {
197 packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
198 } else {
199 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
200 }
201 }
202
203 /**
204 * Withdraw packet intercepts.
205 */
206 private void withdrawIntercepts() {
207 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
208 selector.matchEthType(Ethernet.TYPE_ARP);
Aaron Kruglikov07a923d2015-07-03 13:30:57 -0700209 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Thomas Vachuska27bee092015-06-23 19:03:10 -0700210
211 // IPv6 Neighbor Solicitation packet.
212 selector.matchEthType(Ethernet.TYPE_IPV6);
213 selector.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
214 selector.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
215 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
216
217 // IPv6 Neighbor Advertisement packet.
218 selector.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
219 packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800220 }
221
222 /**
223 * Extracts properties from the component configuration context.
224 *
225 * @param context the component context
226 */
227 private void readComponentConfiguration(ComponentContext context) {
228 Dictionary<?, ?> properties = context.getProperties();
229 Boolean flag;
230
Jian Lid9b5f552016-03-11 18:15:31 -0800231 flag = Tools.isPropertyEnabled(properties, "hostRemovalEnabled");
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800232 if (flag == null) {
233 log.info("Host removal on port/device down events is not configured, " +
Thomas Vachuska27bee092015-06-23 19:03:10 -0700234 "using current value of {}", hostRemovalEnabled);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800235 } else {
236 hostRemovalEnabled = flag;
237 log.info("Configured. Host removal on port/device down events is {}",
238 hostRemovalEnabled ? "enabled" : "disabled");
Thomas Vachuska33601602014-11-19 03:32:15 -0800239 }
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800240
Jian Lid9b5f552016-03-11 18:15:31 -0800241 flag = Tools.isPropertyEnabled(properties, "ipv6NeighborDiscovery");
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800242 if (flag == null) {
243 log.info("Using IPv6 Neighbor Discovery is not configured, " +
Thomas Vachuska27bee092015-06-23 19:03:10 -0700244 "using current value of {}", ipv6NeighborDiscovery);
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800245 } else {
246 ipv6NeighborDiscovery = flag;
247 log.info("Configured. Using IPv6 Neighbor Discovery is {}",
248 ipv6NeighborDiscovery ? "enabled" : "disabled");
249 }
Jonathan Hart9af322d2016-01-06 17:42:04 -0800250
Jian Lid9b5f552016-03-11 18:15:31 -0800251 flag = Tools.isPropertyEnabled(properties, "requestInterceptsEnabled");
Jonathan Hart9af322d2016-01-06 17:42:04 -0800252 if (flag == null) {
253 log.info("Request intercepts is not configured, " +
254 "using current value of {}", requestInterceptsEnabled);
255 } else {
256 requestInterceptsEnabled = flag;
257 log.info("Configured. Request intercepts is {}",
258 requestInterceptsEnabled ? "enabled" : "disabled");
259 }
Pavlin Radoslavov93b606b2015-02-25 17:28:39 -0800260 }
261
alshabibe1cf87d2014-10-17 09:23:50 -0700262 @Override
263 public void triggerProbe(Host host) {
264 log.info("Triggering probe on device {}", host);
265 }
266
267 private class InternalHostProvider implements PacketProcessor {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800268 /**
269 * Update host location only.
270 *
Thomas Vachuska27bee092015-06-23 19:03:10 -0700271 * @param hid host ID
272 * @param mac source Mac address
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800273 * @param vlan VLAN ID
274 * @param hloc host location
275 */
276 private void updateLocation(HostId hid, MacAddress mac,
Thomas Vachuska27bee092015-06-23 19:03:10 -0700277 VlanId vlan, HostLocation hloc) {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800278 HostDescription desc = new DefaultHostDescription(mac, vlan, hloc);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700279 try {
Ray Milkeydc083442016-02-22 11:27:57 -0800280 providerService.hostDetected(hid, desc, false);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700281 } catch (IllegalStateException e) {
282 log.debug("Host {} suppressed", hid);
283 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800284 }
Thomas Vachuska27bee092015-06-23 19:03:10 -0700285
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800286 /**
287 * Update host location and IP address.
288 *
Thomas Vachuska27bee092015-06-23 19:03:10 -0700289 * @param hid host ID
290 * @param mac source Mac address
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800291 * @param vlan VLAN ID
292 * @param hloc host location
Thomas Vachuska27bee092015-06-23 19:03:10 -0700293 * @param ip source IP address
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800294 */
295 private void updateLocationIP(HostId hid, MacAddress mac,
296 VlanId vlan, HostLocation hloc,
297 IpAddress ip) {
Thomas Vachuskae7966102015-09-09 17:33:33 -0700298 HostDescription desc = ip.isZero() || ip.isSelfAssigned() ?
Thomas Vachuskaec9c7dd2015-09-03 18:30:04 -0700299 new DefaultHostDescription(mac, vlan, hloc) :
300 new DefaultHostDescription(mac, vlan, hloc, ip);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700301 try {
Ray Milkeydc083442016-02-22 11:27:57 -0800302 providerService.hostDetected(hid, desc, false);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700303 } catch (IllegalStateException e) {
304 log.debug("Host {} suppressed", hid);
305 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800306 }
alshabibe1cf87d2014-10-17 09:23:50 -0700307
308 @Override
309 public void process(PacketContext context) {
alshabib4a179dc2014-10-17 17:17:01 -0700310 if (context == null) {
311 return;
312 }
alshabibe1cf87d2014-10-17 09:23:50 -0700313
Thomas Vachuskaf845cf62015-03-24 10:13:09 -0700314 Ethernet eth = context.inPacket().parsed();
Jonathan Harte8600eb2015-01-12 10:30:45 -0800315 if (eth == null) {
316 return;
317 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800318 MacAddress srcMac = eth.getSourceMAC();
Jonathan Harte8600eb2015-01-12 10:30:45 -0800319
alshabibe1cf87d2014-10-17 09:23:50 -0700320 VlanId vlan = VlanId.vlanId(eth.getVlanID());
321 ConnectPoint heardOn = context.inPacket().receivedFrom();
322
Thomas Vachuskaf845cf62015-03-24 10:13:09 -0700323 // If this arrived on control port, bail out.
324 if (heardOn.port().isLogical()) {
325 return;
326 }
327
alshabibe1cf87d2014-10-17 09:23:50 -0700328 // If this is not an edge port, bail out.
329 Topology topology = topologyService.currentTopology();
330 if (topologyService.isInfrastructure(topology, heardOn)) {
331 return;
332 }
333
Thomas Vachuskaec9c7dd2015-09-03 18:30:04 -0700334 HostLocation hloc = new HostLocation(heardOn, System.currentTimeMillis());
alshabibe1cf87d2014-10-17 09:23:50 -0700335 HostId hid = HostId.hostId(eth.getSourceMAC(), vlan);
336
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800337 // ARP: possible new hosts, update both location and IP
alshabibe1cf87d2014-10-17 09:23:50 -0700338 if (eth.getEtherType() == Ethernet.TYPE_ARP) {
339 ARP arp = (ARP) eth.getPayload();
Pavlin Radoslavovd6612f92015-02-23 13:53:32 -0800340 IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET,
341 arp.getSenderProtocolAddress());
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800342 updateLocationIP(hid, srcMac, vlan, hloc, ip);
alshabibe1cf87d2014-10-17 09:23:50 -0700343
Charles Chan5d5e0622015-09-25 13:00:06 -0700344 // IPv4: update location only
alshabibe1cf87d2014-10-17 09:23:50 -0700345 } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800346 updateLocation(hid, srcMac, vlan, hloc);
alshabibe1cf87d2014-10-17 09:23:50 -0700347
Charles Chan5d5e0622015-09-25 13:00:06 -0700348 //
349 // NeighborAdvertisement and NeighborSolicitation: possible
350 // new hosts, update both location and IP.
351 //
352 // IPv6: update location only
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800353 } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800354 IPv6 ipv6 = (IPv6) eth.getPayload();
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800355 IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET6,
Thomas Vachuska27bee092015-06-23 19:03:10 -0700356 ipv6.getSourceAddress());
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800357
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800358 // skip extension headers
359 IPacket pkt = ipv6;
360 while (pkt.getPayload() != null &&
361 pkt.getPayload() instanceof IExtensionHeader) {
362 pkt = pkt.getPayload();
363 }
364
365 // Neighbor Discovery Protocol
Charles M.C. Chan9148d2d2015-04-27 03:36:39 +0800366 pkt = pkt.getPayload();
367 if (pkt != null && pkt instanceof ICMP6) {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800368 pkt = pkt.getPayload();
369 // RouterSolicitation, RouterAdvertisement
Charles M.C. Chan9148d2d2015-04-27 03:36:39 +0800370 if (pkt != null && (pkt instanceof RouterAdvertisement ||
Thomas Vachuska27bee092015-06-23 19:03:10 -0700371 pkt instanceof RouterSolicitation)) {
Charles M.C. Chan441d7da2015-03-17 21:03:39 +0800372 return;
373 }
Charles M.C. Chan9148d2d2015-04-27 03:36:39 +0800374 if (pkt != null && (pkt instanceof NeighborSolicitation ||
Thomas Vachuska27bee092015-06-23 19:03:10 -0700375 pkt instanceof NeighborAdvertisement)) {
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800376 // Duplicate Address Detection
377 if (ip.isZero()) {
Charles M.C. Chan441d7da2015-03-17 21:03:39 +0800378 return;
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800379 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800380 // NeighborSolicitation, NeighborAdvertisement
381 updateLocationIP(hid, srcMac, vlan, hloc, ip);
382 return;
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800383 }
Charles M.C. Chan7fee36a2014-12-31 00:19:59 +0800384 }
Charles M.C. Chan956cb692015-04-26 18:49:39 +0800385
386 // multicast
387 if (eth.isMulticast()) {
388 return;
389 }
390
391 // normal IPv6 packets
392 updateLocation(hid, srcMac, vlan, hloc);
alshabibe1cf87d2014-10-17 09:23:50 -0700393 }
394 }
395 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800396
397 // Auxiliary listener to device events.
398 private class InternalDeviceListener implements DeviceListener {
399 @Override
400 public void event(DeviceEvent event) {
Madan Jampania3770c32015-12-11 12:07:41 -0800401 eventHandler.execute(() -> handleEvent(event));
402 }
403
404 private void handleEvent(DeviceEvent event) {
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800405 Device device = event.subject();
406 switch (event.type()) {
Thomas Vachuska27bee092015-06-23 19:03:10 -0700407 case DEVICE_ADDED:
408 break;
409 case DEVICE_AVAILABILITY_CHANGED:
410 if (hostRemovalEnabled &&
411 !deviceService.isAvailable(device.id())) {
412 removeHosts(hostService.getConnectedHosts(device.id()));
413 }
414 break;
415 case DEVICE_SUSPENDED:
416 case DEVICE_UPDATED:
417 // Nothing to do?
418 break;
419 case DEVICE_REMOVED:
420 if (hostRemovalEnabled) {
421 removeHosts(hostService.getConnectedHosts(device.id()));
422 }
423 break;
424 case PORT_ADDED:
425 break;
426 case PORT_UPDATED:
427 if (hostRemovalEnabled) {
428 ConnectPoint point =
429 new ConnectPoint(device.id(), event.port().number());
430 removeHosts(hostService.getConnectedHosts(point));
431 }
432 break;
433 case PORT_REMOVED:
434 // Nothing to do?
435 break;
436 default:
437 break;
Thomas Vachuska33601602014-11-19 03:32:15 -0800438 }
439 }
440 }
441
442 // Signals host vanish for all specified hosts.
443 private void removeHosts(Set<Host> hosts) {
444 for (Host host : hosts) {
Charles Chan8b0fdaa2016-02-23 18:35:27 -0800445 if (host.providerId().equals(HostLocationProvider.this.id())) {
446 providerService.hostVanished(host.id());
447 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800448 }
449 }
450
alshabibe1cf87d2014-10-17 09:23:50 -0700451}