blob: b43b50f91a769d8e7b382a3197f99b771da5a4a0 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.host.impl;
alshabib4a179dc2014-10-17 17:17:01 -070017
Yi Tseng7a38f9a2017-06-09 14:36:40 -070018import com.google.common.collect.ImmutableList;
Thomas Vachuska27bee092015-06-23 19:03:10 -070019import com.google.common.collect.ImmutableSet;
Charles Chan420e7372016-11-17 10:58:17 -080020import com.google.common.collect.Lists;
Madan Jampania3770c32015-12-11 12:07:41 -080021import com.google.common.util.concurrent.MoreExecutors;
alshabib4a179dc2014-10-17 17:17:01 -070022import org.junit.After;
23import org.junit.Before;
24import org.junit.Test;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070025import org.onlab.junit.TestUtils;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080026import org.onlab.osgi.ComponentContextAdapter;
27import org.onlab.packet.ARP;
28import org.onlab.packet.ChassisId;
Charles Chane6067892016-11-17 10:23:46 -080029import org.onlab.packet.DHCP;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070030import org.onlab.packet.dhcp.CircuitId;
Yi Tsengc7403c22017-06-19 16:23:22 -070031import org.onlab.packet.dhcp.DhcpOption;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080032import org.onlab.packet.Ethernet;
Charles Chan5d5e0622015-09-25 13:00:06 -070033import org.onlab.packet.ICMP6;
34import org.onlab.packet.IPv4;
35import org.onlab.packet.IPv6;
36import org.onlab.packet.Ip6Address;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080037import org.onlab.packet.IpAddress;
38import org.onlab.packet.MacAddress;
Charles Chane6067892016-11-17 10:23:46 -080039import org.onlab.packet.UDP;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080040import org.onlab.packet.VlanId;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070041import org.onlab.packet.dhcp.DhcpRelayAgentOption;
Charles Chan5d5e0622015-09-25 13:00:06 -070042import org.onlab.packet.ndp.NeighborAdvertisement;
43import org.onlab.packet.ndp.NeighborSolicitation;
44import org.onlab.packet.ndp.RouterAdvertisement;
45import org.onlab.packet.ndp.RouterSolicitation;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070046import org.onosproject.cfg.ComponentConfigAdapter;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080047import org.onosproject.core.ApplicationId;
48import org.onosproject.core.CoreService;
49import org.onosproject.core.DefaultApplicationId;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070050import org.onosproject.incubator.net.intf.Interface;
51import org.onosproject.incubator.net.intf.InterfaceListener;
52import org.onosproject.incubator.net.intf.InterfaceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080053import org.onosproject.net.ConnectPoint;
54import org.onosproject.net.DefaultDevice;
55import org.onosproject.net.DefaultHost;
56import org.onosproject.net.DefaultPort;
57import org.onosproject.net.Device;
58import org.onosproject.net.DeviceId;
59import org.onosproject.net.Host;
60import org.onosproject.net.HostId;
61import org.onosproject.net.HostLocation;
62import org.onosproject.net.device.DeviceEvent;
63import org.onosproject.net.device.DeviceListener;
64import org.onosproject.net.device.DeviceServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080065import org.onosproject.net.host.HostDescription;
66import org.onosproject.net.host.HostProvider;
67import org.onosproject.net.host.HostProviderRegistry;
68import org.onosproject.net.host.HostProviderService;
69import org.onosproject.net.host.HostServiceAdapter;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070070import org.onosproject.net.host.InterfaceIpAddress;
Brian O'Connorabafb502014-12-02 22:26:20 -080071import org.onosproject.net.packet.DefaultInboundPacket;
72import org.onosproject.net.packet.InboundPacket;
Andrey Komarov2398d962016-09-26 15:11:23 +030073import org.onosproject.net.packet.PacketContextAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080074import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska27bee092015-06-23 19:03:10 -070075import org.onosproject.net.packet.PacketServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080076import org.onosproject.net.provider.AbstractProviderService;
77import org.onosproject.net.provider.ProviderId;
78import org.onosproject.net.topology.Topology;
79import org.onosproject.net.topology.TopologyServiceAdapter;
alshabib4a179dc2014-10-17 17:17:01 -070080
Thomas Vachuska27bee092015-06-23 19:03:10 -070081import java.nio.ByteBuffer;
82import java.util.Collections;
83import java.util.Dictionary;
84import java.util.Hashtable;
Charles Chan420e7372016-11-17 10:58:17 -080085import java.util.List;
Thomas Vachuska27bee092015-06-23 19:03:10 -070086import java.util.Set;
87
Michele Santuari72f6bee2016-11-18 12:56:30 +010088import static org.easymock.EasyMock.createMock;
89import static org.easymock.EasyMock.expect;
90import static org.easymock.EasyMock.replay;
Charles Chan5d5e0622015-09-25 13:00:06 -070091import static org.hamcrest.Matchers.is;
Michele Santuari72f6bee2016-11-18 12:56:30 +010092import static org.junit.Assert.assertEquals;
93import static org.junit.Assert.assertNotEquals;
94import static org.junit.Assert.assertNotNull;
95import static org.junit.Assert.assertThat;
Thomas Vachuska27bee092015-06-23 19:03:10 -070096import static org.onlab.packet.VlanId.vlanId;
97import static org.onosproject.net.Device.Type.SWITCH;
98import static org.onosproject.net.DeviceId.deviceId;
99import static org.onosproject.net.HostId.hostId;
100import static org.onosproject.net.PortNumber.portNumber;
Michele Santuari72f6bee2016-11-18 12:56:30 +0100101import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
102import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
103import static org.onosproject.net.device.DeviceEvent.Type.PORT_UPDATED;
Thomas Vachuska33601602014-11-19 03:32:15 -0800104
alshabib4a179dc2014-10-17 17:17:01 -0700105public class HostLocationProviderTest {
Charles Chan8b0fdaa2016-02-23 18:35:27 -0800106 private static final ProviderId PROVIDER_ID =
107 new ProviderId("of", "org.onosproject.provider.host");
108
alshabib4a179dc2014-10-17 17:17:01 -0700109 private static final Integer INPORT = 10;
Charles Chane6067892016-11-17 10:23:46 -0800110 private static final Integer INPORT2 = 11;
alshabib4a179dc2014-10-17 17:17:01 -0700111 private static final String DEV1 = "of:1";
112 private static final String DEV2 = "of:2";
113 private static final String DEV3 = "of:3";
Charles Chan5d5e0622015-09-25 13:00:06 -0700114 private static final String DEV4 = "of:4";
115 private static final String DEV5 = "of:5";
116 private static final String DEV6 = "of:6";
alshabib4a179dc2014-10-17 17:17:01 -0700117
Thomas Vachuska33601602014-11-19 03:32:15 -0800118 private static final VlanId VLAN = vlanId();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700119 private static final VlanId VLAN_100 = VlanId.vlanId("100");
Charles Chan5d5e0622015-09-25 13:00:06 -0700120
121 // IPv4 Host
alshabib4a179dc2014-10-17 17:17:01 -0700122 private static final MacAddress MAC = MacAddress.valueOf("00:00:11:00:00:01");
123 private static final MacAddress BCMAC = MacAddress.valueOf("ff:ff:ff:ff:ff:ff");
124 private static final byte[] IP = new byte[]{10, 0, 0, 1};
Thomas Vachuska33601602014-11-19 03:32:15 -0800125 private static final IpAddress IP_ADDRESS =
126 IpAddress.valueOf(IpAddress.Version.INET, IP);
127 private static final HostLocation LOCATION =
128 new HostLocation(deviceId(DEV1), portNumber(INPORT), 0L);
Thomas Vachuska33601602014-11-19 03:32:15 -0800129 private static final DefaultHost HOST =
Charles Chan8b0fdaa2016-02-23 18:35:27 -0800130 new DefaultHost(PROVIDER_ID, hostId(MAC), MAC,
Charles Chane6067892016-11-17 10:23:46 -0800131 VLAN, LOCATION,
132 ImmutableSet.of(IP_ADDRESS));
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700133 private static final DefaultHost HOST_VLAN_100 =
134 new DefaultHost(PROVIDER_ID, hostId(MAC, VLAN_100), MAC,
135 VLAN_100, LOCATION,
136 ImmutableSet.of(IP_ADDRESS));
Thomas Vachuska33601602014-11-19 03:32:15 -0800137
Charles Chan5d5e0622015-09-25 13:00:06 -0700138 // IPv6 Host
139 private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02");
140 private static final MacAddress BCMAC2 = MacAddress.valueOf("33:33:00:00:00:01");
141 private static final byte[] IP2 = Ip6Address.valueOf("1000::1").toOctets();
142 private static final IpAddress IP_ADDRESS2 =
143 IpAddress.valueOf(IpAddress.Version.INET6, IP2);
144 private static final HostLocation LOCATION2 =
145 new HostLocation(deviceId(DEV4), portNumber(INPORT), 0L);
146 private static final DefaultHost HOST2 =
Charles Chan8b0fdaa2016-02-23 18:35:27 -0800147 new DefaultHost(PROVIDER_ID, hostId(MAC2), MAC2,
Charles Chane6067892016-11-17 10:23:46 -0800148 VLAN, LOCATION2,
149 ImmutableSet.of(IP_ADDRESS2));
150
151 // DHCP Server
152 private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03");
153 private static final byte[] IP3 = new byte[]{10, 0, 0, 2};
154 private static final IpAddress IP_ADDRESS3 =
155 IpAddress.valueOf(IpAddress.Version.INET, IP3);
156
157 private static final HostLocation LOCATION3 =
158 new HostLocation(deviceId(DEV1), portNumber(INPORT2), 0L);
159 private static final DefaultHost HOST3 =
160 new DefaultHost(PROVIDER_ID, hostId(MAC3), MAC3,
161 VLAN, LOCATION3,
162 ImmutableSet.of(IP_ADDRESS3));
Charles Chan5d5e0622015-09-25 13:00:06 -0700163
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700164 // Gateway information for relay agent
165 private static final InterfaceIpAddress GW_IFACE_ADDR = InterfaceIpAddress.valueOf("10.0.1.1/32");
166 private static final Interface GW_IFACE = new Interface("gateway",
167 LOCATION,
168 ImmutableList.of(GW_IFACE_ADDR),
169 null,
170 VLAN_100);
171
Thomas Vachuska33601602014-11-19 03:32:15 -0800172 private static final ComponentContextAdapter CTX_FOR_REMOVE =
173 new ComponentContextAdapter() {
174 @Override
175 public Dictionary getProperties() {
176 Hashtable<String, String> props = new Hashtable<>();
177 props.put("hostRemovalEnabled", "true");
178 return props;
179 }
180 };
181
182 public static final ComponentContextAdapter CTX_FOR_NO_REMOVE =
183 new ComponentContextAdapter() {
184 @Override
185 public Dictionary getProperties() {
186 return new Hashtable();
187 }
188 };
189
alshabib4a179dc2014-10-17 17:17:01 -0700190 private final HostLocationProvider provider = new HostLocationProvider();
Thomas Vachuska33601602014-11-19 03:32:15 -0800191 private final TestHostRegistry hostRegistry = new TestHostRegistry();
alshabib4a179dc2014-10-17 17:17:01 -0700192 private final TestTopologyService topoService = new TestTopologyService();
Thomas Vachuska33601602014-11-19 03:32:15 -0800193 private final TestDeviceService deviceService = new TestDeviceService();
194 private final TestHostService hostService = new TestHostService();
alshabib4a179dc2014-10-17 17:17:01 -0700195 private final TestPacketService packetService = new TestPacketService();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700196 private final TestInterfaceService interfaceService = new TestInterfaceService();
alshabib4a179dc2014-10-17 17:17:01 -0700197
198 private PacketProcessor testProcessor;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800199 private CoreService coreService;
alshabib4a179dc2014-10-17 17:17:01 -0700200 private TestHostProviderService providerService;
201
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800202 private ApplicationId appId =
203 new DefaultApplicationId(100, "org.onosproject.provider.host");
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800204
alshabib4a179dc2014-10-17 17:17:01 -0700205 @Before
206 public void setUp() {
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800207 coreService = createMock(CoreService.class);
208 expect(coreService.registerApplication(appId.name()))
Thomas Vachuska27bee092015-06-23 19:03:10 -0700209 .andReturn(appId).anyTimes();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800210 replay(coreService);
211
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700212 provider.cfgService = new ComponentConfigAdapter();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800213 provider.coreService = coreService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800214
Thomas Vachuska33601602014-11-19 03:32:15 -0800215 provider.providerRegistry = hostRegistry;
alshabib4a179dc2014-10-17 17:17:01 -0700216 provider.topologyService = topoService;
Pavlin Radoslavovd6612f92015-02-23 13:53:32 -0800217 provider.packetService = packetService;
Thomas Vachuska33601602014-11-19 03:32:15 -0800218 provider.deviceService = deviceService;
219 provider.hostService = hostService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700220 provider.interfaceService = interfaceService;
alshabib4a179dc2014-10-17 17:17:01 -0700221
Thomas Vachuska33601602014-11-19 03:32:15 -0800222 provider.activate(CTX_FOR_NO_REMOVE);
Madan Jampania3770c32015-12-11 12:07:41 -0800223
224 provider.eventHandler = MoreExecutors.newDirectExecutorService();
alshabib4a179dc2014-10-17 17:17:01 -0700225 }
226
227 @Test
228 public void basics() {
229 assertNotNull("registration expected", providerService);
230 assertEquals("incorrect provider", provider, providerService.provider());
231 }
232
233 @Test
234 public void events() {
Charles Chan420e7372016-11-17 10:58:17 -0800235 // New host. Expect one additional host description.
Charles Chan5d5e0622015-09-25 13:00:06 -0700236 testProcessor.process(new TestArpPacketContext(DEV1));
Charles Chan420e7372016-11-17 10:58:17 -0800237 assertThat("New host expected", providerService.descriptions.size(), is(1));
alshabib4a179dc2014-10-17 17:17:01 -0700238
Charles Chan420e7372016-11-17 10:58:17 -0800239 // The host moved to new switch. Expect one additional host description.
240 // The second host description should have a different location.
Charles Chan5d5e0622015-09-25 13:00:06 -0700241 testProcessor.process(new TestArpPacketContext(DEV2));
Charles Chan420e7372016-11-17 10:58:17 -0800242 assertThat("Host motion expected", providerService.descriptions.size(), is(2));
243 HostLocation loc1 = providerService.descriptions.get(0).location();
244 HostLocation loc2 = providerService.descriptions.get(1).location();
245 assertNotEquals("Host location should be different", loc1, loc2);
alshabib4a179dc2014-10-17 17:17:01 -0700246
Charles Chan420e7372016-11-17 10:58:17 -0800247 // The host was misheard on a spine. Expect no additional host description.
Charles Chan5d5e0622015-09-25 13:00:06 -0700248 testProcessor.process(new TestArpPacketContext(DEV3));
Charles Chan420e7372016-11-17 10:58:17 -0800249 assertThat("Host misheard on spine switch", providerService.descriptions.size(), is(2));
Charles Chan5d5e0622015-09-25 13:00:06 -0700250
251 providerService.clear();
252
Charles Chan420e7372016-11-17 10:58:17 -0800253 // New host. Expect one additional host description.
Jonathan Hartb35540a2015-11-17 09:30:56 -0800254 testProcessor.process(new TestNaPacketContext(DEV4));
Charles Chan420e7372016-11-17 10:58:17 -0800255 assertThat("New host expected", providerService.descriptions.size(), is(1));
Charles Chan5d5e0622015-09-25 13:00:06 -0700256
Charles Chan420e7372016-11-17 10:58:17 -0800257 // The host moved to new switch. Expect one additional host description.
258 // The second host description should have a different location.
Jonathan Hartb35540a2015-11-17 09:30:56 -0800259 testProcessor.process(new TestNaPacketContext(DEV5));
Charles Chan420e7372016-11-17 10:58:17 -0800260 assertThat("Host motion expected", providerService.descriptions.size(), is(2));
261 loc1 = providerService.descriptions.get(0).location();
262 loc2 = providerService.descriptions.get(1).location();
263 assertNotEquals("Host location should be different", loc1, loc2);
Charles Chan5d5e0622015-09-25 13:00:06 -0700264
Charles Chan420e7372016-11-17 10:58:17 -0800265 // The host was misheard on a spine. Expect no additional host description.
Jonathan Hartb35540a2015-11-17 09:30:56 -0800266 testProcessor.process(new TestNaPacketContext(DEV6));
Charles Chan420e7372016-11-17 10:58:17 -0800267 assertThat("Host misheard on spine switch", providerService.descriptions.size(), is(2));
alshabib4a179dc2014-10-17 17:17:01 -0700268 }
269
Thomas Vachuska33601602014-11-19 03:32:15 -0800270 @Test
271 public void removeHostByDeviceRemove() {
272 provider.modified(CTX_FOR_REMOVE);
Charles Chan5d5e0622015-09-25 13:00:06 -0700273 testProcessor.process(new TestArpPacketContext(DEV1));
Jonathan Hartb35540a2015-11-17 09:30:56 -0800274 testProcessor.process(new TestNaPacketContext(DEV4));
Charles Chan5d5e0622015-09-25 13:00:06 -0700275
Thomas Vachuska33601602014-11-19 03:32:15 -0800276 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
277 "m", "h", "s", "n", new ChassisId(0L));
278 deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
Charles Chan888e20a2017-05-01 15:44:23 -0700279 assertEquals("incorrect remove count", 2, providerService.locationRemoveCount);
Charles Chan5d5e0622015-09-25 13:00:06 -0700280
281 device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
282 "m", "h", "s", "n", new ChassisId(0L));
283 deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
Charles Chan888e20a2017-05-01 15:44:23 -0700284 assertEquals("incorrect remove count", 3, providerService.locationRemoveCount);
Thomas Vachuska33601602014-11-19 03:32:15 -0800285 }
286
287 @Test
288 public void removeHostByDeviceOffline() {
289 provider.modified(CTX_FOR_REMOVE);
Charles Chan5d5e0622015-09-25 13:00:06 -0700290 testProcessor.process(new TestArpPacketContext(DEV1));
291 testProcessor.process(new TestArpPacketContext(DEV4));
292
Thomas Vachuska33601602014-11-19 03:32:15 -0800293 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
294 "m", "h", "s", "n", new ChassisId(0L));
295 deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
Charles Chan888e20a2017-05-01 15:44:23 -0700296 assertEquals("incorrect remove count", 2, providerService.locationRemoveCount);
Charles Chan5d5e0622015-09-25 13:00:06 -0700297
298 device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
299 "m", "h", "s", "n", new ChassisId(0L));
300 deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
Charles Chan888e20a2017-05-01 15:44:23 -0700301 assertEquals("incorrect remove count", 3, providerService.locationRemoveCount);
Thomas Vachuska33601602014-11-19 03:32:15 -0800302 }
303
304 @Test
305 public void removeHostByDevicePortDown() {
306 provider.modified(CTX_FOR_REMOVE);
Charles Chan5d5e0622015-09-25 13:00:06 -0700307 testProcessor.process(new TestArpPacketContext(DEV1));
308 testProcessor.process(new TestArpPacketContext(DEV4));
309
Thomas Vachuska33601602014-11-19 03:32:15 -0800310 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
311 "m", "h", "s", "n", new ChassisId(0L));
312 deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
Charles Chan5d5e0622015-09-25 13:00:06 -0700313 new DefaultPort(device, portNumber(INPORT), false)));
Charles Chan888e20a2017-05-01 15:44:23 -0700314 assertEquals("incorrect remove count", 1, providerService.locationRemoveCount);
Charles Chan5d5e0622015-09-25 13:00:06 -0700315
316 device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
317 "m", "h", "s", "n", new ChassisId(0L));
318 deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
319 new DefaultPort(device, portNumber(INPORT), false)));
Charles Chan888e20a2017-05-01 15:44:23 -0700320 assertEquals("incorrect remove count", 2, providerService.locationRemoveCount);
Thomas Vachuska33601602014-11-19 03:32:15 -0800321 }
322
Charles Chan5d5e0622015-09-25 13:00:06 -0700323 /**
324 * When receiving ARP, updates location and IP.
325 */
326 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300327 public void receiveArp() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700328 testProcessor.process(new TestArpPacketContext(DEV1));
Andrey Komarov2398d962016-09-26 15:11:23 +0300329 assertThat("receiveArp. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800330 providerService.descriptions.size(), is(1));
331 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700332 assertThat(descr.location(), is(LOCATION));
333 assertThat(descr.hwAddress(), is(MAC));
334 assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS));
335 assertThat(descr.vlan(), is(VLAN));
336 }
337
338 /**
339 * When receiving IPv4, updates location only.
340 */
341 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300342 public void receiveIpv4() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700343 testProcessor.process(new TestIpv4PacketContext(DEV1));
Andrey Komarov2398d962016-09-26 15:11:23 +0300344 assertThat("receiveIpv4. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800345 providerService.descriptions.size(), is(1));
346 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700347 assertThat(descr.location(), is(LOCATION));
348 assertThat(descr.hwAddress(), is(MAC));
349 assertThat(descr.ipAddress().size(), is(0));
350 assertThat(descr.vlan(), is(VLAN));
351 }
352
353 /**
Charles Chane6067892016-11-17 10:23:46 -0800354 * When receiving DHCP REQUEST, update MAC, location of client.
355 * When receiving DHCP ACK, update MAC, location of server and IP of client.
356 */
357 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300358 public void receiveDhcp() {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700359 TestUtils.setField(provider, "useDhcp", true);
Charles Chane6067892016-11-17 10:23:46 -0800360 // DHCP Request
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700361 testProcessor.process(new TestDhcpRequestPacketContext(DEV1, VLAN));
Andrey Komarov2398d962016-09-26 15:11:23 +0300362 assertThat("receiveDhcpRequest. One host description expected",
Charles Chane6067892016-11-17 10:23:46 -0800363 providerService.descriptions.size(), is(1));
364 // Should learn the MAC and location of DHCP client
365 HostDescription descr = providerService.descriptions.get(0);
366 assertThat(descr.location(), is(LOCATION));
367 assertThat(descr.hwAddress(), is(MAC));
368 assertThat(descr.ipAddress().size(), is(0));
369 assertThat(descr.vlan(), is(VLAN));
370
371 // DHCP Ack
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700372 testProcessor.process(new TestDhcpAckPacketContext(DEV1, false));
Andrey Komarov2398d962016-09-26 15:11:23 +0300373 assertThat("receiveDhcpAck. Two additional host descriptions expected",
Yi Tsengcfa637a2017-07-26 17:24:10 -0700374 providerService.descriptions.size(), is(3));
Charles Chane6067892016-11-17 10:23:46 -0800375
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700376 // Should also learn the MAC, location of DHCP server
377 HostDescription descr2 = providerService.descriptions.get(1);
378 assertThat(descr2.location(), is(LOCATION3));
379 assertThat(descr2.hwAddress(), is(MAC3));
380 assertThat(descr2.ipAddress().size(), is(0));
381 assertThat(descr2.vlan(), is(VLAN));
382
Yi Tsengcfa637a2017-07-26 17:24:10 -0700383 // Should update the IP address of the client.
384 HostDescription descr3 = providerService.descriptions.get(2);
385 assertThat(descr3.location(), is(LOCATION));
386 assertThat(descr3.hwAddress(), is(MAC));
387 assertThat(descr3.ipAddress().size(), is(1));
388 IpAddress ip = descr3.ipAddress().iterator().next();
389 assertThat(ip, is(IP_ADDRESS.getIp4Address()));
390 assertThat(descr3.vlan(), is(VLAN));
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700391 }
392
393 /**
394 * The host store should not updated when we disabled "useDhcp".
395 */
396 @Test
397 public void receiveDhcpButNotEnabled() {
398 TestUtils.setField(provider, "useDhcp", false);
399 // DHCP Request
400 testProcessor.process(new TestDhcpRequestPacketContext(DEV1, VLAN));
401 assertThat("receiveDhcpButNotEnabled. No host description expected",
402 providerService.descriptions.size(), is(0));
Charles Chane6067892016-11-17 10:23:46 -0800403 }
404
405 /**
Charles Chan5d5e0622015-09-25 13:00:06 -0700406 * When receiving NeighborAdvertisement, updates location and IP.
407 */
408 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300409 public void receiveNa() {
Jonathan Hartb35540a2015-11-17 09:30:56 -0800410 testProcessor.process(new TestNaPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300411 assertThat("receiveNa. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800412 providerService.descriptions.size(), is(1));
413 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700414 assertThat(descr.location(), is(LOCATION2));
415 assertThat(descr.hwAddress(), is(MAC2));
416 assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS2));
417 assertThat(descr.vlan(), is(VLAN));
418 }
419
420 /**
421 * When receiving NeighborSolicitation, updates location and IP.
422 */
423 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300424 public void receiveNs() {
Jonathan Hartb35540a2015-11-17 09:30:56 -0800425 testProcessor.process(new TestNsPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300426 assertThat("receiveNs. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800427 providerService.descriptions.size(), is(1));
428 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700429 assertThat(descr.location(), is(LOCATION2));
430 assertThat(descr.hwAddress(), is(MAC2));
431 assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS2));
432 assertThat(descr.vlan(), is(VLAN));
433 }
434
435 /**
436 * When receiving RouterAdvertisement, ignores it.
437 */
438 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300439 public void receivesRa() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700440 testProcessor.process(new TestRAPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300441 assertThat("receivesRa. No host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800442 providerService.descriptions.size(), is(0));
Charles Chan5d5e0622015-09-25 13:00:06 -0700443 }
444
445 /**
446 * When receiving RouterSolicitation, ignores it.
447 */
448 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300449 public void receiveRs() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700450 testProcessor.process(new TestRSPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300451 assertThat("receiveRs. No host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800452 providerService.descriptions.size(), is(0));
Charles Chan5d5e0622015-09-25 13:00:06 -0700453 }
454
455 /**
456 * When receiving Duplicate Address Detection (DAD), ignores it.
457 */
458 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300459 public void receiveDad() {
Jonathan Hartb35540a2015-11-17 09:30:56 -0800460 testProcessor.process(new TestDadPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300461 assertThat("receiveDad. No host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800462 providerService.descriptions.size(), is(0));
Charles Chan5d5e0622015-09-25 13:00:06 -0700463 }
464
465 /**
466 * When receiving IPv6 multicast packet, ignores it.
467 */
468 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300469 public void receiveIpv6Multicast() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700470 testProcessor.process(new TestIpv6McastPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300471 assertThat("receiveIpv6Multicast. No host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800472 providerService.descriptions.size(), is(0));
Charles Chan5d5e0622015-09-25 13:00:06 -0700473 }
474
475 /**
476 * When receiving IPv6 unicast packet, updates location only.
477 */
478 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300479 public void receiveIpv6Unicast() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700480 testProcessor.process(new TestIpv6PacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300481 assertThat("receiveIpv6Unicast. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800482 providerService.descriptions.size(), is(1));
483 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700484 assertThat(descr.location(), is(LOCATION2));
485 assertThat(descr.hwAddress(), is(MAC2));
486 assertThat(descr.ipAddress().size(), is(0));
487 assertThat(descr.vlan(), is(VLAN));
488 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800489
alshabib4a179dc2014-10-17 17:17:01 -0700490 @After
491 public void tearDown() {
492 provider.deactivate();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800493 provider.coreService = null;
alshabib4a179dc2014-10-17 17:17:01 -0700494 provider.providerRegistry = null;
alshabib4a179dc2014-10-17 17:17:01 -0700495 }
496
497 private class TestHostRegistry implements HostProviderRegistry {
498
499 @Override
500 public HostProviderService register(HostProvider provider) {
501 providerService = new TestHostProviderService(provider);
502 return providerService;
503 }
504
505 @Override
506 public void unregister(HostProvider provider) {
507 }
508
509 @Override
510 public Set<ProviderId> getProviders() {
511 return null;
512 }
513
514 }
515
516 private class TestHostProviderService
517 extends AbstractProviderService<HostProvider>
518 implements HostProviderService {
519
Charles Chan420e7372016-11-17 10:58:17 -0800520 List<HostDescription> descriptions = Lists.newArrayList();
Charles Chan888e20a2017-05-01 15:44:23 -0700521 int hostRemoveCount;
522 int ipRemoveCount;
523 int locationRemoveCount;
alshabib4a179dc2014-10-17 17:17:01 -0700524
Charles Chan5d5e0622015-09-25 13:00:06 -0700525 public void clear() {
Charles Chan420e7372016-11-17 10:58:17 -0800526 descriptions.clear();
Charles Chan888e20a2017-05-01 15:44:23 -0700527 hostRemoveCount = 0;
528 ipRemoveCount = 0;
529 locationRemoveCount = 0;
Charles Chan5d5e0622015-09-25 13:00:06 -0700530 }
531
alshabib4a179dc2014-10-17 17:17:01 -0700532 protected TestHostProviderService(HostProvider provider) {
533 super(provider);
534 }
535
536 @Override
Brian O'Connorf107bd72015-09-21 15:31:03 -0700537 public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) {
Charles Chan420e7372016-11-17 10:58:17 -0800538 descriptions.add(hostDescription);
alshabib4a179dc2014-10-17 17:17:01 -0700539 }
540
541 @Override
542 public void hostVanished(HostId hostId) {
Charles Chan888e20a2017-05-01 15:44:23 -0700543 hostRemoveCount++;
alshabib4a179dc2014-10-17 17:17:01 -0700544 }
545
samanwita palc40e5ed2015-09-24 11:01:51 -0700546 @Override
547 public void removeIpFromHost(HostId hostId, IpAddress ipAddress) {
Charles Chan888e20a2017-05-01 15:44:23 -0700548 ipRemoveCount++;
549 }
550
551 @Override
552 public void removeLocationFromHost(HostId hostId, HostLocation location) {
553 locationRemoveCount++;
samanwita palc40e5ed2015-09-24 11:01:51 -0700554 }
555
alshabib4a179dc2014-10-17 17:17:01 -0700556 }
557
Thomas Vachuska27bee092015-06-23 19:03:10 -0700558 private class TestPacketService extends PacketServiceAdapter {
alshabib4a179dc2014-10-17 17:17:01 -0700559 @Override
560 public void addProcessor(PacketProcessor processor, int priority) {
561 testProcessor = processor;
562 }
alshabib4a179dc2014-10-17 17:17:01 -0700563 }
564
alshabib4a179dc2014-10-17 17:17:01 -0700565 private class TestTopologyService extends TopologyServiceAdapter {
566 @Override
567 public boolean isInfrastructure(Topology topology,
568 ConnectPoint connectPoint) {
569 //simulate DPID3 as an infrastructure switch
Charles Chan5d5e0622015-09-25 13:00:06 -0700570 if ((connectPoint.deviceId()).equals(deviceId(DEV3)) ||
571 connectPoint.deviceId().equals(deviceId(DEV6))) {
alshabib4a179dc2014-10-17 17:17:01 -0700572 return true;
573 }
574 return false;
575 }
576 }
577
Charles Chan5d5e0622015-09-25 13:00:06 -0700578 /**
579 * Generates ARP packet.
580 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300581 private class TestArpPacketContext extends PacketContextAdapter {
alshabib4a179dc2014-10-17 17:17:01 -0700582 private final String deviceId;
583
Charles Chan5d5e0622015-09-25 13:00:06 -0700584 public TestArpPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300585 super(0, null, null, false);
alshabib4a179dc2014-10-17 17:17:01 -0700586 this.deviceId = deviceId;
587 }
588
589 @Override
alshabib4a179dc2014-10-17 17:17:01 -0700590 public InboundPacket inPacket() {
591 ARP arp = new ARP();
592 arp.setSenderProtocolAddress(IP)
593 .setSenderHardwareAddress(MAC.toBytes())
594 .setTargetHardwareAddress(BCMAC.toBytes())
595 .setTargetProtocolAddress(IP);
596
597 Ethernet eth = new Ethernet();
598 eth.setEtherType(Ethernet.TYPE_ARP)
599 .setVlanID(VLAN.toShort())
600 .setSourceMACAddress(MAC.toBytes())
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800601 .setDestinationMACAddress(BCMAC)
alshabib4a179dc2014-10-17 17:17:01 -0700602 .setPayload(arp);
Thomas Vachuska33601602014-11-19 03:32:15 -0800603 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
604 portNumber(INPORT));
alshabib4a179dc2014-10-17 17:17:01 -0700605 return new DefaultInboundPacket(receivedFrom, eth,
606 ByteBuffer.wrap(eth.serialize()));
607 }
alshabib4a179dc2014-10-17 17:17:01 -0700608 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800609
Charles Chan5d5e0622015-09-25 13:00:06 -0700610 /**
Charles Chane6067892016-11-17 10:23:46 -0800611 * Generates IPv4 Unicast packet.
Charles Chan5d5e0622015-09-25 13:00:06 -0700612 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300613 private class TestIpv4PacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700614 private final String deviceId;
615
616 public TestIpv4PacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300617 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700618 this.deviceId = deviceId;
619 }
620
621 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700622 public InboundPacket inPacket() {
623 IPv4 ipv4 = new IPv4();
624 ipv4.setDestinationAddress("10.0.0.1");
625 ipv4.setSourceAddress(IP_ADDRESS.toString());
626 Ethernet eth = new Ethernet();
627 eth.setEtherType(Ethernet.TYPE_IPV4)
628 .setVlanID(VLAN.toShort())
629 .setSourceMACAddress(MAC)
630 .setDestinationMACAddress(MacAddress.valueOf("00:00:00:00:00:01"))
631 .setPayload(ipv4);
632 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
633 portNumber(INPORT));
634 return new DefaultInboundPacket(receivedFrom, eth,
635 ByteBuffer.wrap(eth.serialize()));
636 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700637 }
Charles Chane6067892016-11-17 10:23:46 -0800638 /**
639 * Generates DHCP REQUEST packet.
640 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300641 private class TestDhcpRequestPacketContext extends PacketContextAdapter {
Charles Chane6067892016-11-17 10:23:46 -0800642 private final String deviceId;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700643 private final VlanId vlanId;
Charles Chane6067892016-11-17 10:23:46 -0800644
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700645 public TestDhcpRequestPacketContext(String deviceId, VlanId vlanId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300646 super(0, null, null, false);
Charles Chane6067892016-11-17 10:23:46 -0800647 this.deviceId = deviceId;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700648 this.vlanId = vlanId;
Charles Chane6067892016-11-17 10:23:46 -0800649 }
650
651 @Override
Charles Chane6067892016-11-17 10:23:46 -0800652 public InboundPacket inPacket() {
653 byte[] dhcpMsgType = new byte[1];
Yi Tsengc7403c22017-06-19 16:23:22 -0700654 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPREQUEST.getValue();
Charles Chane6067892016-11-17 10:23:46 -0800655
Yi Tsengc7403c22017-06-19 16:23:22 -0700656 DhcpOption dhcpOption = new DhcpOption();
Charles Chane6067892016-11-17 10:23:46 -0800657 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
658 dhcpOption.setData(dhcpMsgType);
659 dhcpOption.setLength((byte) 1);
660 DHCP dhcp = new DHCP();
661 dhcp.setOptions(Collections.singletonList(dhcpOption));
662 dhcp.setClientHardwareAddress(MAC.toBytes());
663 UDP udp = new UDP();
664 udp.setPayload(dhcp);
665 udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
666 udp.setDestinationPort(UDP.DHCP_SERVER_PORT);
667 IPv4 ipv4 = new IPv4();
668 ipv4.setPayload(udp);
669 ipv4.setDestinationAddress(IP_ADDRESS3.toString());
670 ipv4.setSourceAddress(IP_ADDRESS.toString());
671 Ethernet eth = new Ethernet();
672 eth.setEtherType(Ethernet.TYPE_IPV4)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700673 .setVlanID(this.vlanId.toShort())
Charles Chane6067892016-11-17 10:23:46 -0800674 .setSourceMACAddress(MAC)
675 .setDestinationMACAddress(MAC3)
676 .setPayload(ipv4);
677 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
678 portNumber(INPORT));
679 return new DefaultInboundPacket(receivedFrom, eth,
680 ByteBuffer.wrap(eth.serialize()));
681 }
Charles Chane6067892016-11-17 10:23:46 -0800682 }
683
684 /**
685 * Generates DHCP ACK packet.
686 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300687 private class TestDhcpAckPacketContext extends PacketContextAdapter {
Charles Chane6067892016-11-17 10:23:46 -0800688 private final String deviceId;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700689 private final boolean withRelayinfo;
Charles Chane6067892016-11-17 10:23:46 -0800690
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700691 public TestDhcpAckPacketContext(String deviceId, boolean withRelayInfo) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300692 super(0, null, null, false);
Charles Chane6067892016-11-17 10:23:46 -0800693 this.deviceId = deviceId;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700694 this.withRelayinfo = withRelayInfo;
Charles Chane6067892016-11-17 10:23:46 -0800695 }
696
697 @Override
Charles Chane6067892016-11-17 10:23:46 -0800698 public InboundPacket inPacket() {
699 byte[] dhcpMsgType = new byte[1];
Yi Tsengc7403c22017-06-19 16:23:22 -0700700 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPACK.getValue();
Charles Chane6067892016-11-17 10:23:46 -0800701
Yi Tsengc7403c22017-06-19 16:23:22 -0700702 DhcpOption dhcpOption = new DhcpOption();
Charles Chane6067892016-11-17 10:23:46 -0800703 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
704 dhcpOption.setData(dhcpMsgType);
705 dhcpOption.setLength((byte) 1);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700706
Charles Chane6067892016-11-17 10:23:46 -0800707 DHCP dhcp = new DHCP();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700708
709 if (withRelayinfo) {
710 CircuitId cid = new CircuitId(LOCATION.toString(), VLAN_100);
711 byte[] circuitId = cid.serialize();
712 DhcpOption circuitIdSubOption = new DhcpOption();
713 circuitIdSubOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
714 circuitIdSubOption.setData(circuitId);
715 circuitIdSubOption.setLength((byte) circuitId.length);
716
717 DhcpRelayAgentOption relayInfoOption = new DhcpRelayAgentOption();
718 relayInfoOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
719 relayInfoOption.addSubOption(circuitIdSubOption);
720 dhcp.setOptions(ImmutableList.of(dhcpOption, relayInfoOption));
721 dhcp.setGatewayIPAddress(GW_IFACE_ADDR.ipAddress().getIp4Address().toInt());
722 } else {
723 dhcp.setOptions(ImmutableList.of(dhcpOption));
724 }
725
Charles Chane6067892016-11-17 10:23:46 -0800726 dhcp.setClientHardwareAddress(MAC.toBytes());
727 dhcp.setYourIPAddress(IP_ADDRESS.getIp4Address().toInt());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700728
Charles Chane6067892016-11-17 10:23:46 -0800729 UDP udp = new UDP();
730 udp.setPayload(dhcp);
731 udp.setSourcePort(UDP.DHCP_SERVER_PORT);
732 udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
733 IPv4 ipv4 = new IPv4();
734 ipv4.setPayload(udp);
735 ipv4.setDestinationAddress(IP_ADDRESS.toString());
736 ipv4.setSourceAddress(IP_ADDRESS3.toString());
737 Ethernet eth = new Ethernet();
738 eth.setEtherType(Ethernet.TYPE_IPV4)
739 .setVlanID(VLAN.toShort())
740 .setSourceMACAddress(MAC3)
741 .setDestinationMACAddress(MAC)
742 .setPayload(ipv4);
743 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
744 portNumber(INPORT2));
745 return new DefaultInboundPacket(receivedFrom, eth,
746 ByteBuffer.wrap(eth.serialize()));
747 }
Charles Chane6067892016-11-17 10:23:46 -0800748 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700749
750 /**
751 * Generates NeighborAdvertisement packet.
752 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300753 private class TestNaPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700754 private final String deviceId;
755
Jonathan Hartb35540a2015-11-17 09:30:56 -0800756 public TestNaPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300757 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700758 this.deviceId = deviceId;
759 }
760
761 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700762 public InboundPacket inPacket() {
763 NeighborAdvertisement na = new NeighborAdvertisement();
764 ICMP6 icmp6 = new ICMP6();
765 icmp6.setPayload(na);
766 IPv6 ipv6 = new IPv6();
767 ipv6.setPayload(icmp6);
768 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
769 ipv6.setSourceAddress(IP2);
770 Ethernet eth = new Ethernet();
771 eth.setEtherType(Ethernet.TYPE_IPV6)
772 .setVlanID(VLAN.toShort())
773 .setSourceMACAddress(MAC2.toBytes())
774 .setDestinationMACAddress(BCMAC2)
775 .setPayload(ipv6);
776 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
777 portNumber(INPORT));
778 return new DefaultInboundPacket(receivedFrom, eth,
779 ByteBuffer.wrap(eth.serialize()));
780 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700781 }
782
783 /**
784 * Generates NeighborSolicitation packet.
785 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300786 private class TestNsPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700787 private final String deviceId;
788
Jonathan Hartb35540a2015-11-17 09:30:56 -0800789 public TestNsPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300790 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700791 this.deviceId = deviceId;
792 }
793
794 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700795 public InboundPacket inPacket() {
796 NeighborSolicitation ns = new NeighborSolicitation();
797 ICMP6 icmp6 = new ICMP6();
798 icmp6.setPayload(ns);
799 IPv6 ipv6 = new IPv6();
800 ipv6.setPayload(icmp6);
801 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1:ff00:0000").toOctets());
802 ipv6.setSourceAddress(IP2);
803 Ethernet eth = new Ethernet();
804 eth.setEtherType(Ethernet.TYPE_IPV6)
805 .setVlanID(VLAN.toShort())
806 .setSourceMACAddress(MAC2.toBytes())
807 .setDestinationMACAddress(BCMAC2)
808 .setPayload(ipv6);
809 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
810 portNumber(INPORT));
811 return new DefaultInboundPacket(receivedFrom, eth,
812 ByteBuffer.wrap(eth.serialize()));
813 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700814 }
815
816 /**
817 * Generates Duplicate Address Detection packet.
818 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300819 private class TestDadPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700820 private final String deviceId;
821
Jonathan Hartb35540a2015-11-17 09:30:56 -0800822 public TestDadPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300823 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700824 this.deviceId = deviceId;
825 }
826
827 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700828 public InboundPacket inPacket() {
829 NeighborSolicitation ns = new NeighborSolicitation();
830 ICMP6 icmp6 = new ICMP6();
831 icmp6.setPayload(ns);
832 IPv6 ipv6 = new IPv6();
833 ipv6.setPayload(icmp6);
834 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
835 ipv6.setSourceAddress(Ip6Address.valueOf("::").toOctets());
836 Ethernet eth = new Ethernet();
837 eth.setEtherType(Ethernet.TYPE_IPV6)
838 .setVlanID(VLAN.toShort())
839 .setSourceMACAddress(MAC2.toBytes())
840 .setDestinationMACAddress(BCMAC2)
841 .setPayload(ipv6);
842 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
843 portNumber(INPORT));
844 return new DefaultInboundPacket(receivedFrom, eth,
845 ByteBuffer.wrap(eth.serialize()));
846 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700847 }
848
849 /**
850 * Generates Router Solicitation packet.
851 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300852 private class TestRSPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700853 private final String deviceId;
854
855 public TestRSPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300856 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700857 this.deviceId = deviceId;
858 }
859
860 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700861 public InboundPacket inPacket() {
862 RouterSolicitation ns = new RouterSolicitation();
863 ICMP6 icmp6 = new ICMP6();
864 icmp6.setPayload(ns);
865 IPv6 ipv6 = new IPv6();
866 ipv6.setPayload(icmp6);
867 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::2").toOctets());
868 ipv6.setSourceAddress(Ip6Address.valueOf("::").toOctets());
869 Ethernet eth = new Ethernet();
870 eth.setEtherType(Ethernet.TYPE_IPV6)
871 .setVlanID(VLAN.toShort())
872 .setSourceMACAddress(MAC2.toBytes())
873 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:02"))
874 .setPayload(ipv6);
875 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
876 portNumber(INPORT));
877 return new DefaultInboundPacket(receivedFrom, eth,
878 ByteBuffer.wrap(eth.serialize()));
879 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700880 }
881
882 /**
883 * Generates Router Advertisement packet.
884 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300885 private class TestRAPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700886 private final String deviceId;
887
888 public TestRAPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300889 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700890 this.deviceId = deviceId;
891 }
892
893 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700894 public InboundPacket inPacket() {
895 RouterAdvertisement ns = new RouterAdvertisement();
896 ICMP6 icmp6 = new ICMP6();
897 icmp6.setPayload(ns);
898 IPv6 ipv6 = new IPv6();
899 ipv6.setPayload(icmp6);
900 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
901 ipv6.setSourceAddress(IP2);
902 Ethernet eth = new Ethernet();
903 eth.setEtherType(Ethernet.TYPE_IPV6)
904 .setVlanID(VLAN.toShort())
905 .setSourceMACAddress(MAC2.toBytes())
906 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:01"))
907 .setPayload(ipv6);
908 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
909 portNumber(INPORT));
910 return new DefaultInboundPacket(receivedFrom, eth,
911 ByteBuffer.wrap(eth.serialize()));
912 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700913 }
914
915 /**
916 * Generates IPv6 Multicast packet.
917 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300918 private class TestIpv6McastPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700919 private final String deviceId;
920
921 public TestIpv6McastPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300922 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700923 this.deviceId = deviceId;
924 }
925
926 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700927 public InboundPacket inPacket() {
928 IPv6 ipv6 = new IPv6();
929 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
930 ipv6.setSourceAddress(IP2);
931 Ethernet eth = new Ethernet();
932 eth.setEtherType(Ethernet.TYPE_IPV6)
933 .setVlanID(VLAN.toShort())
934 .setSourceMACAddress(MAC2.toBytes())
935 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:01"))
936 .setPayload(ipv6);
937 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
938 portNumber(INPORT));
939 return new DefaultInboundPacket(receivedFrom, eth,
940 ByteBuffer.wrap(eth.serialize()));
941 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700942 }
943
944 /**
945 * Generates IPv6 Unicast packet.
946 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300947 private class TestIpv6PacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700948 private final String deviceId;
949
950 public TestIpv6PacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300951 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700952 this.deviceId = deviceId;
953 }
954
955 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700956 public InboundPacket inPacket() {
957 IPv6 ipv6 = new IPv6();
958 ipv6.setDestinationAddress(Ip6Address.valueOf("1000::1").toOctets());
959 ipv6.setSourceAddress(IP2);
960 Ethernet eth = new Ethernet();
961 eth.setEtherType(Ethernet.TYPE_IPV6)
962 .setVlanID(VLAN.toShort())
963 .setSourceMACAddress(MAC2)
964 .setDestinationMACAddress(MacAddress.valueOf("00:00:00:00:00:01"))
965 .setPayload(ipv6);
966 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
967 portNumber(INPORT));
968 return new DefaultInboundPacket(receivedFrom, eth,
969 ByteBuffer.wrap(eth.serialize()));
970 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700971 }
972
Thomas Vachuska33601602014-11-19 03:32:15 -0800973 private class TestDeviceService extends DeviceServiceAdapter {
974 private DeviceListener listener;
975
976 @Override
977 public void addListener(DeviceListener listener) {
978 this.listener = listener;
979 }
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800980
981 @Override
982 public Iterable<Device> getDevices() {
983 return Collections.emptyList();
984 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800985 }
986
987 private class TestHostService extends HostServiceAdapter {
988 @Override
989 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Charles Chan5d5e0622015-09-25 13:00:06 -0700990 ConnectPoint cp1 = new ConnectPoint(deviceId(DEV1), portNumber(INPORT));
991 ConnectPoint cp2 = new ConnectPoint(deviceId(DEV4), portNumber(INPORT));
Charles Chane6067892016-11-17 10:23:46 -0800992 ConnectPoint cp3 = new ConnectPoint(deviceId(DEV1), portNumber(INPORT2));
Charles Chan5d5e0622015-09-25 13:00:06 -0700993 if (connectPoint.equals(cp1)) {
994 return ImmutableSet.of(HOST);
995 } else if (connectPoint.equals(cp2)) {
996 return ImmutableSet.of(HOST2);
Charles Chane6067892016-11-17 10:23:46 -0800997 } else if (connectPoint.equals(cp3)) {
998 return ImmutableSet.of(HOST3);
Charles Chan5d5e0622015-09-25 13:00:06 -0700999 } else {
1000 return ImmutableSet.of();
1001 }
Thomas Vachuska33601602014-11-19 03:32:15 -08001002 }
1003
1004 @Override
1005 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Charles Chan5d5e0622015-09-25 13:00:06 -07001006 if (deviceId.equals(deviceId(DEV1))) {
Charles Chane6067892016-11-17 10:23:46 -08001007 return ImmutableSet.of(HOST, HOST3);
Charles Chan5d5e0622015-09-25 13:00:06 -07001008 } else if (deviceId.equals(deviceId(DEV4))) {
1009 return ImmutableSet.of(HOST2);
1010 } else {
1011 return ImmutableSet.of();
1012 }
Thomas Vachuska33601602014-11-19 03:32:15 -08001013 }
1014
Charles Chane6067892016-11-17 10:23:46 -08001015 @Override
1016 public Host getHost(HostId hostId) {
1017 if (hostId.equals(HostId.hostId(MAC, VLAN))) {
1018 return HOST;
1019 } else if (hostId.equals(HostId.hostId(MAC2, VLAN))) {
1020 return HOST2;
1021 } else if (hostId.equals(HostId.hostId(MAC3, VLAN))) {
1022 return HOST3;
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001023 } else if (hostId.equals(HostId.hostId(MAC, VLAN_100))) {
1024 return HOST_VLAN_100;
Charles Chane6067892016-11-17 10:23:46 -08001025 }
1026 return null;
1027 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001028 }
Charles Chane6067892016-11-17 10:23:46 -08001029
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001030 private class TestInterfaceService implements InterfaceService {
1031 @Override
1032 public Set<Interface> getInterfaces() {
1033 return null;
1034 }
1035
1036 @Override
1037 public Interface getInterfaceByName(ConnectPoint connectPoint, String name) {
1038 return null;
1039 }
1040
1041 @Override
1042 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
1043 return null;
1044 }
1045
1046 public Set<Interface> getInterfacesByIp(IpAddress ip) {
1047 if (ip.equals(GW_IFACE_ADDR.ipAddress())) {
1048 return ImmutableSet.of(GW_IFACE);
1049 } else {
1050 return ImmutableSet.of();
1051 }
1052 }
1053
1054 @Override
1055 public Set<Interface> getInterfacesByVlan(VlanId vlan) {
1056 return null;
1057 }
1058
1059 @Override
1060 public Interface getMatchingInterface(IpAddress ip) {
1061 return null;
1062 }
1063
1064 @Override
1065 public Set<Interface> getMatchingInterfaces(IpAddress ip) {
1066 return null;
1067 }
1068
1069 @Override
1070 public void addListener(InterfaceListener listener) {
1071
1072 }
1073
1074 @Override
1075 public void removeListener(InterfaceListener listener) {
1076
1077 }
Thomas Vachuska33601602014-11-19 03:32:15 -08001078 }
alshabib4a179dc2014-10-17 17:17:01 -07001079}