ONOS-1414: Fix phantom hosts

- Refactor HostLocationProvider
- Ignore multicast packets other than NDP

Change-Id: I6b66becbc30a6a7e83f1da53fb46cf9c073fc86c
This commit is contained in:
Charles M.C. Chan 2015-04-26 18:49:39 +08:00
parent cdc188d147
commit 956cb69f5e

View File

@ -28,7 +28,9 @@ import org.onlab.packet.ICMP6;
import org.onlab.packet.IPacket; import org.onlab.packet.IPacket;
import org.onlab.packet.IPv6; import org.onlab.packet.IPv6;
import org.onlab.packet.IpAddress; import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId; import org.onlab.packet.VlanId;
import org.onlab.packet.ipv6.IExtensionHeader;
import org.onlab.packet.ndp.NeighborAdvertisement; import org.onlab.packet.ndp.NeighborAdvertisement;
import org.onlab.packet.ndp.NeighborSolicitation; import org.onlab.packet.ndp.NeighborSolicitation;
import org.onlab.packet.ndp.RouterAdvertisement; import org.onlab.packet.ndp.RouterAdvertisement;
@ -230,6 +232,34 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
} }
private class InternalHostProvider implements PacketProcessor { private class InternalHostProvider implements PacketProcessor {
/**
* Update host location only.
*
* @param hid host ID
* @param mac source Mac address
* @param vlan VLAN ID
* @param hloc host location
*/
private void updateLocation(HostId hid, MacAddress mac,
VlanId vlan, HostLocation hloc) {
HostDescription desc = new DefaultHostDescription(mac, vlan, hloc);
providerService.hostDetected(hid, desc);
}
/**
* Update host location and IP address.
*
* @param hid host ID
* @param mac source Mac address
* @param vlan VLAN ID
* @param hloc host location
* @param ip source IP address
*/
private void updateLocationIP(HostId hid, MacAddress mac,
VlanId vlan, HostLocation hloc,
IpAddress ip) {
HostDescription desc = new DefaultHostDescription(mac, vlan, hloc, ip);
providerService.hostDetected(hid, desc);
}
@Override @Override
public void process(PacketContext context) { public void process(PacketContext context) {
@ -241,6 +271,7 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
if (eth == null) { if (eth == null) {
return; return;
} }
MacAddress srcMac = eth.getSourceMAC();
VlanId vlan = VlanId.vlanId(eth.getVlanID()); VlanId vlan = VlanId.vlanId(eth.getVlanID());
ConnectPoint heardOn = context.inPacket().receivedFrom(); ConnectPoint heardOn = context.inPacket().receivedFrom();
@ -266,16 +297,11 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
ARP arp = (ARP) eth.getPayload(); ARP arp = (ARP) eth.getPayload();
IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET, IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET,
arp.getSenderProtocolAddress()); arp.getSenderProtocolAddress());
HostDescription hdescr = updateLocationIP(hid, srcMac, vlan, hloc, ip);
new DefaultHostDescription(eth.getSourceMAC(), vlan,
hloc, ip);
providerService.hostDetected(hid, hdescr);
// IPv4: update location only // IPv4: update location only
} else if (eth.getEtherType() == Ethernet.TYPE_IPV4) { } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
HostDescription hdescr = updateLocation(hid, srcMac, vlan, hloc);
new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc);
providerService.hostDetected(hid, hdescr);
// //
// NeighborAdvertisement and NeighborSolicitation: possible // NeighborAdvertisement and NeighborSolicitation: possible
@ -283,36 +309,44 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
// //
// IPv6: update location only // IPv6: update location only
} else if (eth.getEtherType() == Ethernet.TYPE_IPV6) { } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
IpAddress ip = null;
IPv6 ipv6 = (IPv6) eth.getPayload(); IPv6 ipv6 = (IPv6) eth.getPayload();
IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET6,
IPacket iPkt = ipv6;
while (iPkt != null) {
// Ignore Router Solicitation and Advertisement
if (iPkt instanceof RouterAdvertisement ||
iPkt instanceof RouterSolicitation) {
return;
}
if (iPkt instanceof NeighborAdvertisement ||
iPkt instanceof NeighborSolicitation) {
IpAddress sourceAddress =
IpAddress.valueOf(IpAddress.Version.INET6,
ipv6.getSourceAddress()); ipv6.getSourceAddress());
// Ignore DAD packets, in which source address is zero
if (sourceAddress.isZero()) { // skip extension headers
IPacket pkt = ipv6;
while (pkt.getPayload() != null &&
pkt.getPayload() instanceof IExtensionHeader) {
pkt = pkt.getPayload();
}
// Neighbor Discovery Protocol
if (pkt instanceof ICMP6) {
pkt = pkt.getPayload();
// RouterSolicitation, RouterAdvertisement
if (pkt instanceof RouterAdvertisement ||
pkt instanceof RouterSolicitation) {
return; return;
} }
ip = sourceAddress; if (pkt instanceof NeighborSolicitation ||
break; pkt instanceof NeighborAdvertisement) {
// Duplicate Address Detection
if (ip.isZero()) {
return;
} }
iPkt = iPkt.getPayload(); // NeighborSolicitation, NeighborAdvertisement
updateLocationIP(hid, srcMac, vlan, hloc, ip);
return;
} }
HostDescription hdescr = (ip == null) ? }
new DefaultHostDescription(eth.getSourceMAC(), vlan,
hloc) : // multicast
new DefaultHostDescription(eth.getSourceMAC(), vlan, if (eth.isMulticast()) {
hloc, ip); return;
providerService.hostDetected(hid, hdescr); }
// normal IPv6 packets
updateLocation(hid, srcMac, vlan, hloc);
} }
} }
} }