Use DHCP ACK to learn the DHCP client
This feature can be turn on/off via component config.
In addition, ARP interception can also be turned on/off now.
Change-Id: Ia3310fa3fb06821051fbf3363e51096d00781dbf
diff --git a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
index acf0a13..10a12ab 100644
--- a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
+++ b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
@@ -26,13 +26,19 @@
import org.onlab.osgi.ComponentContextAdapter;
import org.onlab.packet.ARP;
import org.onlab.packet.ChassisId;
+import org.onlab.packet.DHCP;
+import org.onlab.packet.DHCPOption;
+import org.onlab.packet.DHCPPacketType;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP;
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
+import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.UDP;
import org.onlab.packet.VlanId;
import org.onlab.packet.ndp.NeighborAdvertisement;
import org.onlab.packet.ndp.NeighborSolicitation;
@@ -93,6 +99,7 @@
new ProviderId("of", "org.onosproject.provider.host");
private static final Integer INPORT = 10;
+ private static final Integer INPORT2 = 11;
private static final String DEV1 = "of:1";
private static final String DEV2 = "of:2";
private static final String DEV3 = "of:3";
@@ -112,8 +119,8 @@
new HostLocation(deviceId(DEV1), portNumber(INPORT), 0L);
private static final DefaultHost HOST =
new DefaultHost(PROVIDER_ID, hostId(MAC), MAC,
- vlanId(VlanId.UNTAGGED), LOCATION,
- ImmutableSet.of(IP_ADDRESS));
+ VLAN, LOCATION,
+ ImmutableSet.of(IP_ADDRESS));
// IPv6 Host
private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02");
@@ -125,8 +132,21 @@
new HostLocation(deviceId(DEV4), portNumber(INPORT), 0L);
private static final DefaultHost HOST2 =
new DefaultHost(PROVIDER_ID, hostId(MAC2), MAC2,
- vlanId(VlanId.UNTAGGED), LOCATION2,
- ImmutableSet.of(IP_ADDRESS2));
+ VLAN, LOCATION2,
+ ImmutableSet.of(IP_ADDRESS2));
+
+ // DHCP Server
+ private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03");
+ private static final byte[] IP3 = new byte[]{10, 0, 0, 2};
+ private static final IpAddress IP_ADDRESS3 =
+ IpAddress.valueOf(IpAddress.Version.INET, IP3);
+
+ private static final HostLocation LOCATION3 =
+ new HostLocation(deviceId(DEV1), portNumber(INPORT2), 0L);
+ private static final DefaultHost HOST3 =
+ new DefaultHost(PROVIDER_ID, hostId(MAC3), MAC3,
+ VLAN, LOCATION3,
+ ImmutableSet.of(IP_ADDRESS3));
private static final ComponentContextAdapter CTX_FOR_REMOVE =
new ComponentContextAdapter() {
@@ -234,12 +254,12 @@
Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
"m", "h", "s", "n", new ChassisId(0L));
deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
- assertEquals("incorrect remove count", 1, providerService.removeCount);
+ assertEquals("incorrect remove count", 2, providerService.removeCount);
device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
"m", "h", "s", "n", new ChassisId(0L));
deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
- assertEquals("incorrect remove count", 2, providerService.removeCount);
+ assertEquals("incorrect remove count", 3, providerService.removeCount);
}
@Test
@@ -251,12 +271,12 @@
Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
"m", "h", "s", "n", new ChassisId(0L));
deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
- assertEquals("incorrect remove count", 1, providerService.removeCount);
+ assertEquals("incorrect remove count", 2, providerService.removeCount);
device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
"m", "h", "s", "n", new ChassisId(0L));
deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
- assertEquals("incorrect remove count", 2, providerService.removeCount);
+ assertEquals("incorrect remove count", 3, providerService.removeCount);
}
@Test
@@ -309,6 +329,43 @@
}
/**
+ * When receiving DHCP REQUEST, update MAC, location of client.
+ * When receiving DHCP ACK, update MAC, location of server and IP of client.
+ */
+ @Test
+ public void testReceiveDhcp() {
+ // DHCP Request
+ testProcessor.process(new TestDhcpRequestPacketContext(DEV1));
+ assertThat("testReceiveDhcpRequest. One host description expected",
+ providerService.descriptions.size(), is(1));
+ // Should learn the MAC and location of DHCP client
+ HostDescription descr = providerService.descriptions.get(0);
+ assertThat(descr.location(), is(LOCATION));
+ assertThat(descr.hwAddress(), is(MAC));
+ assertThat(descr.ipAddress().size(), is(0));
+ assertThat(descr.vlan(), is(VLAN));
+
+ // DHCP Ack
+ testProcessor.process(new TestDhcpAckPacketContext(DEV1));
+ assertThat("testReceiveDhcpAck. Two additional host descriptions expected",
+ providerService.descriptions.size(), is(3));
+ // Should learn the IP of DHCP client
+ HostDescription descr2 = providerService.descriptions.get(1);
+ assertThat(descr2.location(), is(LOCATION));
+ assertThat(descr2.hwAddress(), is(MAC));
+ assertThat(descr2.ipAddress().size(), is(1));
+ assertTrue(descr2.ipAddress().contains(IP_ADDRESS));
+ assertThat(descr2.vlan(), is(VLAN));
+ // Should also learn the MAC, location of DHCP server
+ HostDescription descr3 = providerService.descriptions.get(2);
+ assertThat(descr3.location(), is(LOCATION3));
+ assertThat(descr3.hwAddress(), is(MAC3));
+ assertThat(descr3.ipAddress().size(), is(0));
+ assertThat(descr3.vlan(), is(VLAN));
+
+ }
+
+ /**
* When receiving NeighborAdvertisement, updates location and IP.
*/
@Test
@@ -533,7 +590,7 @@
}
/**
- * Generates IPv6 Unicast packet.
+ * Generates IPv4 Unicast packet.
*/
private class TestIpv4PacketContext implements PacketContext {
private final String deviceId;
@@ -589,6 +646,152 @@
return false;
}
}
+ /**
+ * Generates DHCP REQUEST packet.
+ */
+ private class TestDhcpRequestPacketContext implements PacketContext {
+ private final String deviceId;
+
+ public TestDhcpRequestPacketContext(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ @Override
+ public long time() {
+ return 0;
+ }
+
+ @Override
+ public InboundPacket inPacket() {
+ byte[] dhcpMsgType = new byte[1];
+ dhcpMsgType[0] = (byte) DHCPPacketType.DHCPREQUEST.getValue();
+
+ DHCPOption dhcpOption = new DHCPOption();
+ dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
+ dhcpOption.setData(dhcpMsgType);
+ dhcpOption.setLength((byte) 1);
+ DHCP dhcp = new DHCP();
+ dhcp.setOptions(Collections.singletonList(dhcpOption));
+ dhcp.setClientHardwareAddress(MAC.toBytes());
+ UDP udp = new UDP();
+ udp.setPayload(dhcp);
+ udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
+ udp.setDestinationPort(UDP.DHCP_SERVER_PORT);
+ IPv4 ipv4 = new IPv4();
+ ipv4.setPayload(udp);
+ ipv4.setDestinationAddress(IP_ADDRESS3.toString());
+ ipv4.setSourceAddress(IP_ADDRESS.toString());
+ Ethernet eth = new Ethernet();
+ eth.setEtherType(Ethernet.TYPE_IPV4)
+ .setVlanID(VLAN.toShort())
+ .setSourceMACAddress(MAC)
+ .setDestinationMACAddress(MAC3)
+ .setPayload(ipv4);
+ ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
+ portNumber(INPORT));
+ return new DefaultInboundPacket(receivedFrom, eth,
+ ByteBuffer.wrap(eth.serialize()));
+ }
+
+ @Override
+ public OutboundPacket outPacket() {
+ return null;
+ }
+
+ @Override
+ public TrafficTreatment.Builder treatmentBuilder() {
+ return null;
+ }
+
+ @Override
+ public void send() {
+
+ }
+
+ @Override
+ public boolean block() {
+ return false;
+ }
+
+ @Override
+ public boolean isHandled() {
+ return false;
+ }
+ }
+
+ /**
+ * Generates DHCP ACK packet.
+ */
+ private class TestDhcpAckPacketContext implements PacketContext {
+ private final String deviceId;
+
+ public TestDhcpAckPacketContext(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ @Override
+ public long time() {
+ return 0;
+ }
+
+ @Override
+ public InboundPacket inPacket() {
+ byte[] dhcpMsgType = new byte[1];
+ dhcpMsgType[0] = (byte) DHCPPacketType.DHCPACK.getValue();
+
+ DHCPOption dhcpOption = new DHCPOption();
+ dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
+ dhcpOption.setData(dhcpMsgType);
+ dhcpOption.setLength((byte) 1);
+ DHCP dhcp = new DHCP();
+ dhcp.setOptions(Collections.singletonList(dhcpOption));
+ dhcp.setClientHardwareAddress(MAC.toBytes());
+ dhcp.setYourIPAddress(IP_ADDRESS.getIp4Address().toInt());
+ UDP udp = new UDP();
+ udp.setPayload(dhcp);
+ udp.setSourcePort(UDP.DHCP_SERVER_PORT);
+ udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
+ IPv4 ipv4 = new IPv4();
+ ipv4.setPayload(udp);
+ ipv4.setDestinationAddress(IP_ADDRESS.toString());
+ ipv4.setSourceAddress(IP_ADDRESS3.toString());
+ Ethernet eth = new Ethernet();
+ eth.setEtherType(Ethernet.TYPE_IPV4)
+ .setVlanID(VLAN.toShort())
+ .setSourceMACAddress(MAC3)
+ .setDestinationMACAddress(MAC)
+ .setPayload(ipv4);
+ ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
+ portNumber(INPORT2));
+ return new DefaultInboundPacket(receivedFrom, eth,
+ ByteBuffer.wrap(eth.serialize()));
+ }
+
+ @Override
+ public OutboundPacket outPacket() {
+ return null;
+ }
+
+ @Override
+ public TrafficTreatment.Builder treatmentBuilder() {
+ return null;
+ }
+
+ @Override
+ public void send() {
+
+ }
+
+ @Override
+ public boolean block() {
+ return false;
+ }
+
+ @Override
+ public boolean isHandled() {
+ return false;
+ }
+ }
/**
* Generates NeighborAdvertisement packet.
@@ -1035,10 +1238,13 @@
public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
ConnectPoint cp1 = new ConnectPoint(deviceId(DEV1), portNumber(INPORT));
ConnectPoint cp2 = new ConnectPoint(deviceId(DEV4), portNumber(INPORT));
+ ConnectPoint cp3 = new ConnectPoint(deviceId(DEV1), portNumber(INPORT2));
if (connectPoint.equals(cp1)) {
return ImmutableSet.of(HOST);
} else if (connectPoint.equals(cp2)) {
return ImmutableSet.of(HOST2);
+ } else if (connectPoint.equals(cp3)) {
+ return ImmutableSet.of(HOST3);
} else {
return ImmutableSet.of();
}
@@ -1047,7 +1253,7 @@
@Override
public Set<Host> getConnectedHosts(DeviceId deviceId) {
if (deviceId.equals(deviceId(DEV1))) {
- return ImmutableSet.of(HOST);
+ return ImmutableSet.of(HOST, HOST3);
} else if (deviceId.equals(deviceId(DEV4))) {
return ImmutableSet.of(HOST2);
} else {
@@ -1055,5 +1261,17 @@
}
}
+ @Override
+ public Host getHost(HostId hostId) {
+ if (hostId.equals(HostId.hostId(MAC, VLAN))) {
+ return HOST;
+ } else if (hostId.equals(HostId.hostId(MAC2, VLAN))) {
+ return HOST2;
+ } else if (hostId.equals(HostId.hostId(MAC3, VLAN))) {
+ return HOST3;
+ }
+ return null;
+ }
+
}
}