Charles M.C. Chan

ONOS-1414: Fix phantom hosts

- Refactor HostLocationProvider
- Ignore multicast packets other than NDP

Change-Id: I6b66becbc30a6a7e83f1da53fb46cf9c073fc86c
...@@ -28,7 +28,9 @@ import org.onlab.packet.ICMP6; ...@@ -28,7 +28,9 @@ import org.onlab.packet.ICMP6;
28 import org.onlab.packet.IPacket; 28 import org.onlab.packet.IPacket;
29 import org.onlab.packet.IPv6; 29 import org.onlab.packet.IPv6;
30 import org.onlab.packet.IpAddress; 30 import org.onlab.packet.IpAddress;
31 +import org.onlab.packet.MacAddress;
31 import org.onlab.packet.VlanId; 32 import org.onlab.packet.VlanId;
33 +import org.onlab.packet.ipv6.IExtensionHeader;
32 import org.onlab.packet.ndp.NeighborAdvertisement; 34 import org.onlab.packet.ndp.NeighborAdvertisement;
33 import org.onlab.packet.ndp.NeighborSolicitation; 35 import org.onlab.packet.ndp.NeighborSolicitation;
34 import org.onlab.packet.ndp.RouterAdvertisement; 36 import org.onlab.packet.ndp.RouterAdvertisement;
...@@ -230,6 +232,34 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -230,6 +232,34 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
230 } 232 }
231 233
232 private class InternalHostProvider implements PacketProcessor { 234 private class InternalHostProvider implements PacketProcessor {
235 + /**
236 + * Update host location only.
237 + *
238 + * @param hid host ID
239 + * @param mac source Mac address
240 + * @param vlan VLAN ID
241 + * @param hloc host location
242 + */
243 + private void updateLocation(HostId hid, MacAddress mac,
244 + VlanId vlan, HostLocation hloc) {
245 + HostDescription desc = new DefaultHostDescription(mac, vlan, hloc);
246 + providerService.hostDetected(hid, desc);
247 + }
248 + /**
249 + * Update host location and IP address.
250 + *
251 + * @param hid host ID
252 + * @param mac source Mac address
253 + * @param vlan VLAN ID
254 + * @param hloc host location
255 + * @param ip source IP address
256 + */
257 + private void updateLocationIP(HostId hid, MacAddress mac,
258 + VlanId vlan, HostLocation hloc,
259 + IpAddress ip) {
260 + HostDescription desc = new DefaultHostDescription(mac, vlan, hloc, ip);
261 + providerService.hostDetected(hid, desc);
262 + }
233 263
234 @Override 264 @Override
235 public void process(PacketContext context) { 265 public void process(PacketContext context) {
...@@ -241,6 +271,7 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -241,6 +271,7 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
241 if (eth == null) { 271 if (eth == null) {
242 return; 272 return;
243 } 273 }
274 + MacAddress srcMac = eth.getSourceMAC();
244 275
245 VlanId vlan = VlanId.vlanId(eth.getVlanID()); 276 VlanId vlan = VlanId.vlanId(eth.getVlanID());
246 ConnectPoint heardOn = context.inPacket().receivedFrom(); 277 ConnectPoint heardOn = context.inPacket().receivedFrom();
...@@ -266,16 +297,11 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -266,16 +297,11 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
266 ARP arp = (ARP) eth.getPayload(); 297 ARP arp = (ARP) eth.getPayload();
267 IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET, 298 IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET,
268 arp.getSenderProtocolAddress()); 299 arp.getSenderProtocolAddress());
269 - HostDescription hdescr = 300 + updateLocationIP(hid, srcMac, vlan, hloc, ip);
270 - new DefaultHostDescription(eth.getSourceMAC(), vlan,
271 - hloc, ip);
272 - providerService.hostDetected(hid, hdescr);
273 301
274 // IPv4: update location only 302 // IPv4: update location only
275 } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) { 303 } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
276 - HostDescription hdescr = 304 + updateLocation(hid, srcMac, vlan, hloc);
277 - new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc);
278 - providerService.hostDetected(hid, hdescr);
279 305
280 // 306 //
281 // NeighborAdvertisement and NeighborSolicitation: possible 307 // NeighborAdvertisement and NeighborSolicitation: possible
...@@ -283,36 +309,44 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -283,36 +309,44 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
283 // 309 //
284 // IPv6: update location only 310 // IPv6: update location only
285 } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) { 311 } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
286 - IpAddress ip = null;
287 IPv6 ipv6 = (IPv6) eth.getPayload(); 312 IPv6 ipv6 = (IPv6) eth.getPayload();
313 + IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET6,
314 + ipv6.getSourceAddress());
288 315
289 - IPacket iPkt = ipv6; 316 + // skip extension headers
290 - while (iPkt != null) { 317 + IPacket pkt = ipv6;
291 - // Ignore Router Solicitation and Advertisement 318 + while (pkt.getPayload() != null &&
292 - if (iPkt instanceof RouterAdvertisement || 319 + pkt.getPayload() instanceof IExtensionHeader) {
293 - iPkt instanceof RouterSolicitation) { 320 + pkt = pkt.getPayload();
321 + }
322 +
323 + // Neighbor Discovery Protocol
324 + if (pkt instanceof ICMP6) {
325 + pkt = pkt.getPayload();
326 + // RouterSolicitation, RouterAdvertisement
327 + if (pkt instanceof RouterAdvertisement ||
328 + pkt instanceof RouterSolicitation) {
294 return; 329 return;
295 } 330 }
296 - if (iPkt instanceof NeighborAdvertisement || 331 + if (pkt instanceof NeighborSolicitation ||
297 - iPkt instanceof NeighborSolicitation) { 332 + pkt instanceof NeighborAdvertisement) {
298 - IpAddress sourceAddress = 333 + // Duplicate Address Detection
299 - IpAddress.valueOf(IpAddress.Version.INET6, 334 + if (ip.isZero()) {
300 - ipv6.getSourceAddress());
301 - // Ignore DAD packets, in which source address is zero
302 - if (sourceAddress.isZero()) {
303 return; 335 return;
304 } 336 }
305 - ip = sourceAddress; 337 + // NeighborSolicitation, NeighborAdvertisement
306 - break; 338 + updateLocationIP(hid, srcMac, vlan, hloc, ip);
339 + return;
307 } 340 }
308 - iPkt = iPkt.getPayload();
309 } 341 }
310 - HostDescription hdescr = (ip == null) ? 342 +
311 - new DefaultHostDescription(eth.getSourceMAC(), vlan, 343 + // multicast
312 - hloc) : 344 + if (eth.isMulticast()) {
313 - new DefaultHostDescription(eth.getSourceMAC(), vlan, 345 + return;
314 - hloc, ip); 346 + }
315 - providerService.hostDetected(hid, hdescr); 347 +
348 + // normal IPv6 packets
349 + updateLocation(hid, srcMac, vlan, hloc);
316 } 350 }
317 } 351 }
318 } 352 }
......