ONOS-1414: Fix phantom hosts
- Refactor HostLocationProvider
- Ignore multicast packets other than NDP
Change-Id: I6b66becbc30a6a7e83f1da53fb46cf9c073fc86c
diff --git a/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java b/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
index 48f8f27..e320eda 100644
--- a/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
+++ b/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
@@ -28,7 +28,9 @@
import org.onlab.packet.IPacket;
import org.onlab.packet.IPv6;
import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onlab.packet.ipv6.IExtensionHeader;
import org.onlab.packet.ndp.NeighborAdvertisement;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onlab.packet.ndp.RouterAdvertisement;
@@ -230,6 +232,34 @@
}
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
public void process(PacketContext context) {
@@ -241,6 +271,7 @@
if (eth == null) {
return;
}
+ MacAddress srcMac = eth.getSourceMAC();
VlanId vlan = VlanId.vlanId(eth.getVlanID());
ConnectPoint heardOn = context.inPacket().receivedFrom();
@@ -266,16 +297,11 @@
ARP arp = (ARP) eth.getPayload();
IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET,
arp.getSenderProtocolAddress());
- HostDescription hdescr =
- new DefaultHostDescription(eth.getSourceMAC(), vlan,
- hloc, ip);
- providerService.hostDetected(hid, hdescr);
+ updateLocationIP(hid, srcMac, vlan, hloc, ip);
// IPv4: update location only
} else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
- HostDescription hdescr =
- new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc);
- providerService.hostDetected(hid, hdescr);
+ updateLocation(hid, srcMac, vlan, hloc);
//
// NeighborAdvertisement and NeighborSolicitation: possible
@@ -283,36 +309,44 @@
//
// IPv6: update location only
} else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
- IpAddress ip = null;
IPv6 ipv6 = (IPv6) eth.getPayload();
+ IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET6,
+ ipv6.getSourceAddress());
- IPacket iPkt = ipv6;
- while (iPkt != null) {
- // Ignore Router Solicitation and Advertisement
- if (iPkt instanceof RouterAdvertisement ||
- iPkt instanceof RouterSolicitation) {
+ // 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;
}
- if (iPkt instanceof NeighborAdvertisement ||
- iPkt instanceof NeighborSolicitation) {
- IpAddress sourceAddress =
- IpAddress.valueOf(IpAddress.Version.INET6,
- ipv6.getSourceAddress());
- // Ignore DAD packets, in which source address is zero
- if (sourceAddress.isZero()) {
+ if (pkt instanceof NeighborSolicitation ||
+ pkt instanceof NeighborAdvertisement) {
+ // Duplicate Address Detection
+ if (ip.isZero()) {
return;
}
- ip = sourceAddress;
- break;
+ // NeighborSolicitation, NeighborAdvertisement
+ updateLocationIP(hid, srcMac, vlan, hloc, ip);
+ return;
}
- iPkt = iPkt.getPayload();
}
- HostDescription hdescr = (ip == null) ?
- new DefaultHostDescription(eth.getSourceMAC(), vlan,
- hloc) :
- new DefaultHostDescription(eth.getSourceMAC(), vlan,
- hloc, ip);
- providerService.hostDetected(hid, hdescr);
+
+ // multicast
+ if (eth.isMulticast()) {
+ return;
+ }
+
+ // normal IPv6 packets
+ updateLocation(hid, srcMac, vlan, hloc);
}
}
}