blob: b1c661c53ebcaf9ce47fc7a948c1496430cec939 [file] [log] [blame]
/*
* Copyright 2014-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.provider.host.impl;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
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.ICMP6;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
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;
import org.onlab.packet.ndp.RouterAdvertisement;
import org.onlab.packet.ndp.RouterSolicitation;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.host.HostServiceAdapter;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContextAdapter;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketServiceAdapter;
import org.onosproject.net.provider.AbstractProviderService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyServiceAdapter;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.onlab.packet.VlanId.vlanId;
import static org.onosproject.net.Device.Type.SWITCH;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.HostId.hostId;
import static org.onosproject.net.PortNumber.portNumber;
import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
import static org.onosproject.net.device.DeviceEvent.Type.PORT_UPDATED;
public class HostLocationProviderTest {
private static final ProviderId PROVIDER_ID =
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";
private static final String DEV4 = "of:4";
private static final String DEV5 = "of:5";
private static final String DEV6 = "of:6";
private static final VlanId VLAN = vlanId();
// IPv4 Host
private static final MacAddress MAC = MacAddress.valueOf("00:00:11:00:00:01");
private static final MacAddress BCMAC = MacAddress.valueOf("ff:ff:ff:ff:ff:ff");
private static final byte[] IP = new byte[]{10, 0, 0, 1};
private static final IpAddress IP_ADDRESS =
IpAddress.valueOf(IpAddress.Version.INET, IP);
private static final HostLocation LOCATION =
new HostLocation(deviceId(DEV1), portNumber(INPORT), 0L);
private static final DefaultHost HOST =
new DefaultHost(PROVIDER_ID, hostId(MAC), MAC,
VLAN, LOCATION,
ImmutableSet.of(IP_ADDRESS));
// IPv6 Host
private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02");
private static final MacAddress BCMAC2 = MacAddress.valueOf("33:33:00:00:00:01");
private static final byte[] IP2 = Ip6Address.valueOf("1000::1").toOctets();
private static final IpAddress IP_ADDRESS2 =
IpAddress.valueOf(IpAddress.Version.INET6, IP2);
private static final HostLocation LOCATION2 =
new HostLocation(deviceId(DEV4), portNumber(INPORT), 0L);
private static final DefaultHost HOST2 =
new DefaultHost(PROVIDER_ID, hostId(MAC2), MAC2,
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() {
@Override
public Dictionary getProperties() {
Hashtable<String, String> props = new Hashtable<>();
props.put("hostRemovalEnabled", "true");
return props;
}
};
public static final ComponentContextAdapter CTX_FOR_NO_REMOVE =
new ComponentContextAdapter() {
@Override
public Dictionary getProperties() {
return new Hashtable();
}
};
private final HostLocationProvider provider = new HostLocationProvider();
private final TestHostRegistry hostRegistry = new TestHostRegistry();
private final TestTopologyService topoService = new TestTopologyService();
private final TestDeviceService deviceService = new TestDeviceService();
private final TestHostService hostService = new TestHostService();
private final TestPacketService packetService = new TestPacketService();
private PacketProcessor testProcessor;
private CoreService coreService;
private TestHostProviderService providerService;
private ApplicationId appId =
new DefaultApplicationId(100, "org.onosproject.provider.host");
@Before
public void setUp() {
coreService = createMock(CoreService.class);
expect(coreService.registerApplication(appId.name()))
.andReturn(appId).anyTimes();
replay(coreService);
provider.cfgService = new ComponentConfigAdapter();
provider.coreService = coreService;
provider.providerRegistry = hostRegistry;
provider.topologyService = topoService;
provider.packetService = packetService;
provider.deviceService = deviceService;
provider.hostService = hostService;
provider.activate(CTX_FOR_NO_REMOVE);
provider.eventHandler = MoreExecutors.newDirectExecutorService();
}
@Test
public void basics() {
assertNotNull("registration expected", providerService);
assertEquals("incorrect provider", provider, providerService.provider());
}
@Test
public void events() {
// New host. Expect one additional host description.
testProcessor.process(new TestArpPacketContext(DEV1));
assertThat("New host expected", providerService.descriptions.size(), is(1));
// The host moved to new switch. Expect one additional host description.
// The second host description should have a different location.
testProcessor.process(new TestArpPacketContext(DEV2));
assertThat("Host motion expected", providerService.descriptions.size(), is(2));
HostLocation loc1 = providerService.descriptions.get(0).location();
HostLocation loc2 = providerService.descriptions.get(1).location();
assertNotEquals("Host location should be different", loc1, loc2);
// The host was misheard on a spine. Expect no additional host description.
testProcessor.process(new TestArpPacketContext(DEV3));
assertThat("Host misheard on spine switch", providerService.descriptions.size(), is(2));
providerService.clear();
// New host. Expect one additional host description.
testProcessor.process(new TestNaPacketContext(DEV4));
assertThat("New host expected", providerService.descriptions.size(), is(1));
// The host moved to new switch. Expect one additional host description.
// The second host description should have a different location.
testProcessor.process(new TestNaPacketContext(DEV5));
assertThat("Host motion expected", providerService.descriptions.size(), is(2));
loc1 = providerService.descriptions.get(0).location();
loc2 = providerService.descriptions.get(1).location();
assertNotEquals("Host location should be different", loc1, loc2);
// The host was misheard on a spine. Expect no additional host description.
testProcessor.process(new TestNaPacketContext(DEV6));
assertThat("Host misheard on spine switch", providerService.descriptions.size(), is(2));
}
@Test
public void removeHostByDeviceRemove() {
provider.modified(CTX_FOR_REMOVE);
testProcessor.process(new TestArpPacketContext(DEV1));
testProcessor.process(new TestNaPacketContext(DEV4));
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", 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", 3, providerService.removeCount);
}
@Test
public void removeHostByDeviceOffline() {
provider.modified(CTX_FOR_REMOVE);
testProcessor.process(new TestArpPacketContext(DEV1));
testProcessor.process(new TestArpPacketContext(DEV4));
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", 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", 3, providerService.removeCount);
}
@Test
public void removeHostByDevicePortDown() {
provider.modified(CTX_FOR_REMOVE);
testProcessor.process(new TestArpPacketContext(DEV1));
testProcessor.process(new TestArpPacketContext(DEV4));
Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
"m", "h", "s", "n", new ChassisId(0L));
deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
new DefaultPort(device, portNumber(INPORT), false)));
assertEquals("incorrect remove count", 1, providerService.removeCount);
device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
"m", "h", "s", "n", new ChassisId(0L));
deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
new DefaultPort(device, portNumber(INPORT), false)));
assertEquals("incorrect remove count", 2, providerService.removeCount);
}
/**
* When receiving ARP, updates location and IP.
*/
@Test
public void receiveArp() {
testProcessor.process(new TestArpPacketContext(DEV1));
assertThat("receiveArp. One host description expected",
providerService.descriptions.size(), is(1));
HostDescription descr = providerService.descriptions.get(0);
assertThat(descr.location(), is(LOCATION));
assertThat(descr.hwAddress(), is(MAC));
assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS));
assertThat(descr.vlan(), is(VLAN));
}
/**
* When receiving IPv4, updates location only.
*/
@Test
public void receiveIpv4() {
testProcessor.process(new TestIpv4PacketContext(DEV1));
assertThat("receiveIpv4. One host description expected",
providerService.descriptions.size(), is(1));
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));
}
/**
* 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 receiveDhcp() {
// DHCP Request
testProcessor.process(new TestDhcpRequestPacketContext(DEV1));
assertThat("receiveDhcpRequest. 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("receiveDhcpAck. 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
public void receiveNa() {
testProcessor.process(new TestNaPacketContext(DEV4));
assertThat("receiveNa. One host description expected",
providerService.descriptions.size(), is(1));
HostDescription descr = providerService.descriptions.get(0);
assertThat(descr.location(), is(LOCATION2));
assertThat(descr.hwAddress(), is(MAC2));
assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS2));
assertThat(descr.vlan(), is(VLAN));
}
/**
* When receiving NeighborSolicitation, updates location and IP.
*/
@Test
public void receiveNs() {
testProcessor.process(new TestNsPacketContext(DEV4));
assertThat("receiveNs. One host description expected",
providerService.descriptions.size(), is(1));
HostDescription descr = providerService.descriptions.get(0);
assertThat(descr.location(), is(LOCATION2));
assertThat(descr.hwAddress(), is(MAC2));
assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS2));
assertThat(descr.vlan(), is(VLAN));
}
/**
* When receiving RouterAdvertisement, ignores it.
*/
@Test
public void receivesRa() {
testProcessor.process(new TestRAPacketContext(DEV4));
assertThat("receivesRa. No host description expected",
providerService.descriptions.size(), is(0));
}
/**
* When receiving RouterSolicitation, ignores it.
*/
@Test
public void receiveRs() {
testProcessor.process(new TestRSPacketContext(DEV4));
assertThat("receiveRs. No host description expected",
providerService.descriptions.size(), is(0));
}
/**
* When receiving Duplicate Address Detection (DAD), ignores it.
*/
@Test
public void receiveDad() {
testProcessor.process(new TestDadPacketContext(DEV4));
assertThat("receiveDad. No host description expected",
providerService.descriptions.size(), is(0));
}
/**
* When receiving IPv6 multicast packet, ignores it.
*/
@Test
public void receiveIpv6Multicast() {
testProcessor.process(new TestIpv6McastPacketContext(DEV4));
assertThat("receiveIpv6Multicast. No host description expected",
providerService.descriptions.size(), is(0));
}
/**
* When receiving IPv6 unicast packet, updates location only.
*/
@Test
public void receiveIpv6Unicast() {
testProcessor.process(new TestIpv6PacketContext(DEV4));
assertThat("receiveIpv6Unicast. One host description expected",
providerService.descriptions.size(), is(1));
HostDescription descr = providerService.descriptions.get(0);
assertThat(descr.location(), is(LOCATION2));
assertThat(descr.hwAddress(), is(MAC2));
assertThat(descr.ipAddress().size(), is(0));
assertThat(descr.vlan(), is(VLAN));
}
@After
public void tearDown() {
provider.deactivate();
provider.coreService = null;
provider.providerRegistry = null;
}
private class TestHostRegistry implements HostProviderRegistry {
@Override
public HostProviderService register(HostProvider provider) {
providerService = new TestHostProviderService(provider);
return providerService;
}
@Override
public void unregister(HostProvider provider) {
}
@Override
public Set<ProviderId> getProviders() {
return null;
}
}
private class TestHostProviderService
extends AbstractProviderService<HostProvider>
implements HostProviderService {
List<HostDescription> descriptions = Lists.newArrayList();
int removeCount;
public void clear() {
descriptions.clear();
removeCount = 0;
}
protected TestHostProviderService(HostProvider provider) {
super(provider);
}
@Override
public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) {
descriptions.add(hostDescription);
}
@Override
public void hostVanished(HostId hostId) {
removeCount++;
}
@Override
public void removeIpFromHost(HostId hostId, IpAddress ipAddress) {
}
}
private class TestPacketService extends PacketServiceAdapter {
@Override
public void addProcessor(PacketProcessor processor, int priority) {
testProcessor = processor;
}
}
private class TestTopologyService extends TopologyServiceAdapter {
@Override
public boolean isInfrastructure(Topology topology,
ConnectPoint connectPoint) {
//simulate DPID3 as an infrastructure switch
if ((connectPoint.deviceId()).equals(deviceId(DEV3)) ||
connectPoint.deviceId().equals(deviceId(DEV6))) {
return true;
}
return false;
}
}
/**
* Generates ARP packet.
*/
private class TestArpPacketContext extends PacketContextAdapter {
private final String deviceId;
public TestArpPacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@Override
public InboundPacket inPacket() {
ARP arp = new ARP();
arp.setSenderProtocolAddress(IP)
.setSenderHardwareAddress(MAC.toBytes())
.setTargetHardwareAddress(BCMAC.toBytes())
.setTargetProtocolAddress(IP);
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_ARP)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC.toBytes())
.setDestinationMACAddress(BCMAC)
.setPayload(arp);
ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
portNumber(INPORT));
return new DefaultInboundPacket(receivedFrom, eth,
ByteBuffer.wrap(eth.serialize()));
}
}
/**
* Generates IPv4 Unicast packet.
*/
private class TestIpv4PacketContext extends PacketContextAdapter {
private final String deviceId;
public TestIpv4PacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@Override
public InboundPacket inPacket() {
IPv4 ipv4 = new IPv4();
ipv4.setDestinationAddress("10.0.0.1");
ipv4.setSourceAddress(IP_ADDRESS.toString());
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_IPV4)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC)
.setDestinationMACAddress(MacAddress.valueOf("00:00:00:00:00:01"))
.setPayload(ipv4);
ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
portNumber(INPORT));
return new DefaultInboundPacket(receivedFrom, eth,
ByteBuffer.wrap(eth.serialize()));
}
}
/**
* Generates DHCP REQUEST packet.
*/
private class TestDhcpRequestPacketContext extends PacketContextAdapter {
private final String deviceId;
public TestDhcpRequestPacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@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()));
}
}
/**
* Generates DHCP ACK packet.
*/
private class TestDhcpAckPacketContext extends PacketContextAdapter {
private final String deviceId;
public TestDhcpAckPacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@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()));
}
}
/**
* Generates NeighborAdvertisement packet.
*/
private class TestNaPacketContext extends PacketContextAdapter {
private final String deviceId;
public TestNaPacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@Override
public InboundPacket inPacket() {
NeighborAdvertisement na = new NeighborAdvertisement();
ICMP6 icmp6 = new ICMP6();
icmp6.setPayload(na);
IPv6 ipv6 = new IPv6();
ipv6.setPayload(icmp6);
ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
ipv6.setSourceAddress(IP2);
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_IPV6)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC2.toBytes())
.setDestinationMACAddress(BCMAC2)
.setPayload(ipv6);
ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
portNumber(INPORT));
return new DefaultInboundPacket(receivedFrom, eth,
ByteBuffer.wrap(eth.serialize()));
}
}
/**
* Generates NeighborSolicitation packet.
*/
private class TestNsPacketContext extends PacketContextAdapter {
private final String deviceId;
public TestNsPacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@Override
public InboundPacket inPacket() {
NeighborSolicitation ns = new NeighborSolicitation();
ICMP6 icmp6 = new ICMP6();
icmp6.setPayload(ns);
IPv6 ipv6 = new IPv6();
ipv6.setPayload(icmp6);
ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1:ff00:0000").toOctets());
ipv6.setSourceAddress(IP2);
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_IPV6)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC2.toBytes())
.setDestinationMACAddress(BCMAC2)
.setPayload(ipv6);
ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
portNumber(INPORT));
return new DefaultInboundPacket(receivedFrom, eth,
ByteBuffer.wrap(eth.serialize()));
}
}
/**
* Generates Duplicate Address Detection packet.
*/
private class TestDadPacketContext extends PacketContextAdapter {
private final String deviceId;
public TestDadPacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@Override
public InboundPacket inPacket() {
NeighborSolicitation ns = new NeighborSolicitation();
ICMP6 icmp6 = new ICMP6();
icmp6.setPayload(ns);
IPv6 ipv6 = new IPv6();
ipv6.setPayload(icmp6);
ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
ipv6.setSourceAddress(Ip6Address.valueOf("::").toOctets());
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_IPV6)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC2.toBytes())
.setDestinationMACAddress(BCMAC2)
.setPayload(ipv6);
ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
portNumber(INPORT));
return new DefaultInboundPacket(receivedFrom, eth,
ByteBuffer.wrap(eth.serialize()));
}
}
/**
* Generates Router Solicitation packet.
*/
private class TestRSPacketContext extends PacketContextAdapter {
private final String deviceId;
public TestRSPacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@Override
public InboundPacket inPacket() {
RouterSolicitation ns = new RouterSolicitation();
ICMP6 icmp6 = new ICMP6();
icmp6.setPayload(ns);
IPv6 ipv6 = new IPv6();
ipv6.setPayload(icmp6);
ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::2").toOctets());
ipv6.setSourceAddress(Ip6Address.valueOf("::").toOctets());
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_IPV6)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC2.toBytes())
.setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:02"))
.setPayload(ipv6);
ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
portNumber(INPORT));
return new DefaultInboundPacket(receivedFrom, eth,
ByteBuffer.wrap(eth.serialize()));
}
}
/**
* Generates Router Advertisement packet.
*/
private class TestRAPacketContext extends PacketContextAdapter {
private final String deviceId;
public TestRAPacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@Override
public InboundPacket inPacket() {
RouterAdvertisement ns = new RouterAdvertisement();
ICMP6 icmp6 = new ICMP6();
icmp6.setPayload(ns);
IPv6 ipv6 = new IPv6();
ipv6.setPayload(icmp6);
ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
ipv6.setSourceAddress(IP2);
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_IPV6)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC2.toBytes())
.setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:01"))
.setPayload(ipv6);
ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
portNumber(INPORT));
return new DefaultInboundPacket(receivedFrom, eth,
ByteBuffer.wrap(eth.serialize()));
}
}
/**
* Generates IPv6 Multicast packet.
*/
private class TestIpv6McastPacketContext extends PacketContextAdapter {
private final String deviceId;
public TestIpv6McastPacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@Override
public InboundPacket inPacket() {
IPv6 ipv6 = new IPv6();
ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
ipv6.setSourceAddress(IP2);
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_IPV6)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC2.toBytes())
.setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:01"))
.setPayload(ipv6);
ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
portNumber(INPORT));
return new DefaultInboundPacket(receivedFrom, eth,
ByteBuffer.wrap(eth.serialize()));
}
}
/**
* Generates IPv6 Unicast packet.
*/
private class TestIpv6PacketContext extends PacketContextAdapter {
private final String deviceId;
public TestIpv6PacketContext(String deviceId) {
super(0, null, null, false);
this.deviceId = deviceId;
}
@Override
public InboundPacket inPacket() {
IPv6 ipv6 = new IPv6();
ipv6.setDestinationAddress(Ip6Address.valueOf("1000::1").toOctets());
ipv6.setSourceAddress(IP2);
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_IPV6)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC2)
.setDestinationMACAddress(MacAddress.valueOf("00:00:00:00:00:01"))
.setPayload(ipv6);
ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
portNumber(INPORT));
return new DefaultInboundPacket(receivedFrom, eth,
ByteBuffer.wrap(eth.serialize()));
}
}
private class TestDeviceService extends DeviceServiceAdapter {
private DeviceListener listener;
@Override
public void addListener(DeviceListener listener) {
this.listener = listener;
}
@Override
public Iterable<Device> getDevices() {
return Collections.emptyList();
}
}
private class TestHostService extends HostServiceAdapter {
@Override
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();
}
}
@Override
public Set<Host> getConnectedHosts(DeviceId deviceId) {
if (deviceId.equals(deviceId(DEV1))) {
return ImmutableSet.of(HOST, HOST3);
} else if (deviceId.equals(deviceId(DEV4))) {
return ImmutableSet.of(HOST2);
} else {
return ImmutableSet.of();
}
}
@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;
}
}
}