Support double-tagged host
Change-Id: Ie4041a0b5159e7a8b3a9ed82b55ce3c26b520a3b
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 0633d12..45ed92d 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,6 +28,7 @@
import org.onlab.packet.BasePacket;
import org.onlab.packet.DHCP;
import org.onlab.packet.DHCP6;
+import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPacket;
@@ -441,15 +442,17 @@
* Create or update host information.
* Will not update IP if IP is null, all zero or self-assigned.
*
- * @param hid host ID
- * @param mac source Mac address
- * @param vlan VLAN ID
- * @param hloc host location
- * @param ip source IP address or null if not updating
+ * @param hid host ID
+ * @param mac source Mac address
+ * @param vlan VLAN ID
+ * @param innerVlan inner VLAN ID
+ * @param outerTpid outer TPID
+ * @param hloc host location
+ * @param ip source IP address or null if not updating
*/
- private void createOrUpdateHost(HostId hid, MacAddress mac,
- VlanId vlan, HostLocation hloc,
- IpAddress ip) {
+ private void createOrUpdateHost(HostId hid, MacAddress mac, VlanId vlan,
+ VlanId innerVlan, EthType outerTpid,
+ HostLocation hloc, IpAddress ip) {
Set<HostLocation> newLocations = Sets.newHashSet(hloc);
if (multihomingEnabled) {
@@ -473,8 +476,10 @@
}
HostDescription desc = ip == null || ip.isZero() || ip.isSelfAssigned() ?
- new DefaultHostDescription(mac, vlan, newLocations, Sets.newHashSet(), false) :
- new DefaultHostDescription(mac, vlan, newLocations, Sets.newHashSet(ip), false);
+ new DefaultHostDescription(mac, vlan, newLocations, Sets.newHashSet(),
+ innerVlan, outerTpid, false) :
+ new DefaultHostDescription(mac, vlan, newLocations, Sets.newHashSet(ip),
+ innerVlan, outerTpid, false);
try {
providerService.hostDetected(hid, desc, false);
} catch (IllegalStateException e) {
@@ -521,6 +526,15 @@
}
VlanId vlan = VlanId.vlanId(eth.getVlanID());
+ VlanId outerVlan = VlanId.vlanId(eth.getQinQVID());
+ VlanId innerVlan = VlanId.NONE;
+ EthType outerTpid = EthType.EtherType.UNKNOWN.ethType();
+ // Set up values for double-tagged hosts
+ if (outerVlan.toShort() != Ethernet.VLAN_UNTAGGED) {
+ innerVlan = vlan;
+ vlan = outerVlan;
+ outerTpid = EthType.EtherType.lookup(eth.getQinQTPID()).ethType();
+ }
ConnectPoint heardOn = context.inPacket().receivedFrom();
// If this arrived on control port, bail out.
@@ -550,12 +564,12 @@
ARP arp = (ARP) eth.getPayload();
IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET,
arp.getSenderProtocolAddress());
- createOrUpdateHost(hid, srcMac, vlan, hloc, ip);
+ createOrUpdateHost(hid, srcMac, vlan, innerVlan, outerTpid, hloc, ip);
// IPv4: update location only
} else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
// Update host location
- createOrUpdateHost(hid, srcMac, vlan, hloc, null);
+ createOrUpdateHost(hid, srcMac, vlan, innerVlan, outerTpid, hloc, null);
if (useDhcp) {
DHCP dhcp = findDhcp(eth).orElse(null);
// DHCP ACK: additionally update IP of DHCP client
@@ -586,7 +600,7 @@
// DHCPv6 protocol
DHCP6 dhcp6 = findDhcp6(pkt).orElse(null);
if (dhcp6 != null && useDhcp6) {
- createOrUpdateHost(hid, srcMac, vlan, hloc, null);
+ createOrUpdateHost(hid, srcMac, vlan, innerVlan, outerTpid, hloc, null);
handleDhcp6(dhcp6, vlan);
return;
}
@@ -605,13 +619,13 @@
return;
}
// NeighborSolicitation, NeighborAdvertisement
- createOrUpdateHost(hid, srcMac, vlan, hloc, ip);
+ createOrUpdateHost(hid, srcMac, vlan, innerVlan, outerTpid, hloc, ip);
// Also learn from the target address of NeighborAdvertisement
if (pkt instanceof NeighborAdvertisement) {
NeighborAdvertisement na = (NeighborAdvertisement) pkt;
Ip6Address targetAddr = Ip6Address.valueOf(na.getTargetAddress());
- createOrUpdateHost(hid, srcMac, vlan, hloc, targetAddr);
+ createOrUpdateHost(hid, srcMac, vlan, innerVlan, outerTpid, hloc, targetAddr);
}
return;
}
@@ -624,7 +638,7 @@
}
// normal IPv6 packets
- createOrUpdateHost(hid, srcMac, vlan, hloc, null);
+ createOrUpdateHost(hid, srcMac, vlan, innerVlan, outerTpid, hloc, null);
}
}
diff --git a/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/NetworkConfigHostProvider.java b/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/NetworkConfigHostProvider.java
index 42278d3..a0be2d9 100644
--- a/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/NetworkConfigHostProvider.java
+++ b/providers/netcfghost/src/main/java/org/onosproject/provider/netcfghost/NetworkConfigHostProvider.java
@@ -21,6 +21,7 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
@@ -120,6 +121,28 @@
}
/**
+ * Adds host information.
+ * IP information will be appended if host exists.
+ *
+ * @param mac MAC address of the host
+ * @param vlan VLAN ID of the host
+ * @param locations Location of the host
+ * @param ips Set of IP addresses of the host
+ * @param innerVlan host inner VLAN identifier
+ * @param outerTpid outer TPID of a host
+ */
+ protected void addHost(MacAddress mac, VlanId vlan, Set<HostLocation> locations, Set<IpAddress> ips,
+ VlanId innerVlan, EthType outerTpid) {
+ HostId hid = HostId.hostId(mac, vlan);
+ HostDescription desc = (ips != null) ?
+ new DefaultHostDescription(mac, vlan, locations, ips,
+ innerVlan, outerTpid, true) :
+ new DefaultHostDescription(mac, vlan, locations, Collections.emptySet(),
+ innerVlan, outerTpid, true);
+ providerService.hostDetected(hid, desc, true);
+ }
+
+ /**
* Updates host information.
* IP information will be replaced if host exists.
*
@@ -135,6 +158,25 @@
}
/**
+ * Updates host information.
+ * IP information will be replaced if host exists.
+ *
+ * @param mac MAC address of the host
+ * @param vlan VLAN ID of the host
+ * @param locations Location of the host
+ * @param ips Set of IP addresses of the host
+ * @param innerVlan host inner VLAN identifier
+ * @param outerTpid outer TPID of a host
+ */
+ protected void updateHost(MacAddress mac, VlanId vlan, Set<HostLocation> locations, Set<IpAddress> ips,
+ VlanId innerVlan, EthType outerTpid) {
+ HostId hid = HostId.hostId(mac, vlan);
+ HostDescription desc = new DefaultHostDescription(mac, vlan, locations, ips,
+ innerVlan, outerTpid, true);
+ providerService.hostDetected(hid, desc, true);
+ }
+
+ /**
* Removes host information.
*
* @param mac MAC address of the host
@@ -155,7 +197,9 @@
Set<HostLocation> locations = hostConfig.locations().stream()
.map(hostLocation -> new HostLocation(hostLocation, System.currentTimeMillis()))
.collect(Collectors.toSet());
- addHost(mac, vlan, locations, ipAddresses);
+ VlanId innerVlan = hostConfig.innerVlan();
+ EthType outerTpid = hostConfig.outerTpid();
+ addHost(mac, vlan, locations, ipAddresses, innerVlan, outerTpid);
});
}
@@ -175,6 +219,8 @@
BasicHostConfig hostConfig = networkConfigRegistry.getConfig(hostId, BasicHostConfig.class);
Set<IpAddress> ipAddresses = null;
Set<HostLocation> locations = null;
+ VlanId innerVlan = VlanId.NONE;
+ EthType outerTpid = EthType.EtherType.UNKNOWN.ethType();
// Note: There will be no config presented in the CONFIG_REMOVE case
if (hostConfig != null) {
@@ -187,14 +233,16 @@
locations = locations.stream()
.map(hostLocation -> new HostLocation(hostLocation, System.currentTimeMillis()))
.collect(Collectors.toSet());
+ innerVlan = hostConfig.innerVlan();
+ outerTpid = hostConfig.outerTpid();
}
switch (event.type()) {
case CONFIG_ADDED:
- addHost(mac, vlan, locations, ipAddresses);
+ addHost(mac, vlan, locations, ipAddresses, innerVlan, outerTpid);
break;
case CONFIG_UPDATED:
- updateHost(mac, vlan, locations, ipAddresses);
+ updateHost(mac, vlan, locations, ipAddresses, innerVlan, outerTpid);
break;
case CONFIG_REMOVED:
removeHost(mac, vlan);
diff --git a/providers/netcfghost/src/test/java/org/onosproject/provider/netcfghost/NetworkConfigHostProviderTest.java b/providers/netcfghost/src/test/java/org/onosproject/provider/netcfghost/NetworkConfigHostProviderTest.java
index 36ad76d..36de211 100644
--- a/providers/netcfghost/src/test/java/org/onosproject/provider/netcfghost/NetworkConfigHostProviderTest.java
+++ b/providers/netcfghost/src/test/java/org/onosproject/provider/netcfghost/NetworkConfigHostProviderTest.java
@@ -19,6 +19,7 @@
import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
+import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
@@ -54,6 +55,8 @@
private Set<IpAddress> ips = new HashSet<>();
private HostId hostId = HostId.hostId(mac, vlan);
private HostDescription hostDescription;
+ private VlanId innerVlan = VlanId.vlanId((short) 20);
+ private EthType outerTpid = EthType.EtherType.lookup((short) 0x88a8).ethType();
@Before
public void setUp() {
@@ -62,12 +65,13 @@
// Initialize test variables
ips.add(IpAddress.valueOf("10.0.0.1"));
ips.add(IpAddress.valueOf("192.168.0.1"));
- hostDescription = new DefaultHostDescription(mac, vlan, locations, ips, true);
+ hostDescription = new DefaultHostDescription(mac, vlan, locations, ips,
+ innerVlan, outerTpid, true);
}
@Test
public void testAddHost() throws Exception {
- provider.addHost(mac, vlan, locations, ips);
+ provider.addHost(mac, vlan, locations, ips, innerVlan, outerTpid);
assertThat(providerService.hostId, is(hostId));
assertThat(providerService.hostDescription, is(hostDescription));
assertThat(providerService.event, is("hostDetected"));
@@ -76,7 +80,7 @@
@Test
public void testUpdateHost() throws Exception {
- provider.updateHost(mac, vlan, locations, ips);
+ provider.updateHost(mac, vlan, locations, ips, innerVlan, outerTpid);
assertThat(providerService.hostId, is(hostId));
assertThat(providerService.hostDescription, is(hostDescription));
assertThat(providerService.event, is("hostDetected"));