blob: 77e2caaf814717af2ea2bfff50df59c59187039f [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
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 Tsengfcf5dce2017-07-26 14:30:41 -070030import org.onlab.packet.DHCP6;
31import org.onlab.packet.dhcp.Dhcp6ClientIdOption;
32import org.onlab.packet.dhcp.Dhcp6Duid;
33import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
34import org.onlab.packet.dhcp.Dhcp6IaNaOption;
35import org.onlab.packet.dhcp.Dhcp6Option;
Yi Tsengc7403c22017-06-19 16:23:22 -070036import org.onlab.packet.dhcp.DhcpOption;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080037import org.onlab.packet.Ethernet;
Charles Chan5d5e0622015-09-25 13:00:06 -070038import org.onlab.packet.ICMP6;
39import org.onlab.packet.IPv4;
40import org.onlab.packet.IPv6;
41import org.onlab.packet.Ip6Address;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080042import org.onlab.packet.IpAddress;
43import org.onlab.packet.MacAddress;
Charles Chane6067892016-11-17 10:23:46 -080044import org.onlab.packet.UDP;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080045import org.onlab.packet.VlanId;
Charles Chan5d5e0622015-09-25 13:00:06 -070046import org.onlab.packet.ndp.NeighborAdvertisement;
47import org.onlab.packet.ndp.NeighborSolicitation;
48import org.onlab.packet.ndp.RouterAdvertisement;
49import org.onlab.packet.ndp.RouterSolicitation;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070050import org.onosproject.cfg.ComponentConfigAdapter;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080051import org.onosproject.core.ApplicationId;
52import org.onosproject.core.CoreService;
53import org.onosproject.core.DefaultApplicationId;
Ray Milkeyfacf2862017-08-03 11:58:29 -070054import org.onosproject.net.intf.Interface;
55import org.onosproject.net.intf.InterfaceListener;
56import org.onosproject.net.intf.InterfaceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080057import org.onosproject.net.ConnectPoint;
58import org.onosproject.net.DefaultDevice;
59import org.onosproject.net.DefaultHost;
60import org.onosproject.net.DefaultPort;
61import org.onosproject.net.Device;
62import org.onosproject.net.DeviceId;
63import org.onosproject.net.Host;
64import org.onosproject.net.HostId;
65import org.onosproject.net.HostLocation;
66import org.onosproject.net.device.DeviceEvent;
67import org.onosproject.net.device.DeviceListener;
68import org.onosproject.net.device.DeviceServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080069import org.onosproject.net.host.HostDescription;
70import org.onosproject.net.host.HostProvider;
71import org.onosproject.net.host.HostProviderRegistry;
72import org.onosproject.net.host.HostProviderService;
73import org.onosproject.net.host.HostServiceAdapter;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070074import org.onosproject.net.host.InterfaceIpAddress;
Brian O'Connorabafb502014-12-02 22:26:20 -080075import org.onosproject.net.packet.DefaultInboundPacket;
76import org.onosproject.net.packet.InboundPacket;
Andrey Komarov2398d962016-09-26 15:11:23 +030077import org.onosproject.net.packet.PacketContextAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080078import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska27bee092015-06-23 19:03:10 -070079import org.onosproject.net.packet.PacketServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080080import org.onosproject.net.provider.AbstractProviderService;
81import org.onosproject.net.provider.ProviderId;
82import org.onosproject.net.topology.Topology;
83import org.onosproject.net.topology.TopologyServiceAdapter;
alshabib4a179dc2014-10-17 17:17:01 -070084
Thomas Vachuska27bee092015-06-23 19:03:10 -070085import java.nio.ByteBuffer;
86import java.util.Collections;
87import java.util.Dictionary;
88import java.util.Hashtable;
Charles Chan420e7372016-11-17 10:58:17 -080089import java.util.List;
Thomas Vachuska27bee092015-06-23 19:03:10 -070090import java.util.Set;
91
Michele Santuari72f6bee2016-11-18 12:56:30 +010092import static org.easymock.EasyMock.createMock;
93import static org.easymock.EasyMock.expect;
94import static org.easymock.EasyMock.replay;
Charles Chan5d5e0622015-09-25 13:00:06 -070095import static org.hamcrest.Matchers.is;
Michele Santuari72f6bee2016-11-18 12:56:30 +010096import static org.junit.Assert.assertEquals;
97import static org.junit.Assert.assertNotEquals;
98import static org.junit.Assert.assertNotNull;
99import static org.junit.Assert.assertThat;
Thomas Vachuska27bee092015-06-23 19:03:10 -0700100import static org.onlab.packet.VlanId.vlanId;
101import static org.onosproject.net.Device.Type.SWITCH;
102import static org.onosproject.net.DeviceId.deviceId;
103import static org.onosproject.net.HostId.hostId;
104import static org.onosproject.net.PortNumber.portNumber;
Michele Santuari72f6bee2016-11-18 12:56:30 +0100105import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
106import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
107import static org.onosproject.net.device.DeviceEvent.Type.PORT_UPDATED;
Thomas Vachuska33601602014-11-19 03:32:15 -0800108
alshabib4a179dc2014-10-17 17:17:01 -0700109public class HostLocationProviderTest {
Charles Chan8b0fdaa2016-02-23 18:35:27 -0800110 private static final ProviderId PROVIDER_ID =
111 new ProviderId("of", "org.onosproject.provider.host");
112
alshabib4a179dc2014-10-17 17:17:01 -0700113 private static final Integer INPORT = 10;
Charles Chane6067892016-11-17 10:23:46 -0800114 private static final Integer INPORT2 = 11;
alshabib4a179dc2014-10-17 17:17:01 -0700115 private static final String DEV1 = "of:1";
116 private static final String DEV2 = "of:2";
117 private static final String DEV3 = "of:3";
Charles Chan5d5e0622015-09-25 13:00:06 -0700118 private static final String DEV4 = "of:4";
119 private static final String DEV5 = "of:5";
120 private static final String DEV6 = "of:6";
alshabib4a179dc2014-10-17 17:17:01 -0700121
Thomas Vachuska33601602014-11-19 03:32:15 -0800122 private static final VlanId VLAN = vlanId();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700123 private static final VlanId VLAN_100 = VlanId.vlanId("100");
Charles Chan5d5e0622015-09-25 13:00:06 -0700124
125 // IPv4 Host
alshabib4a179dc2014-10-17 17:17:01 -0700126 private static final MacAddress MAC = MacAddress.valueOf("00:00:11:00:00:01");
127 private static final MacAddress BCMAC = MacAddress.valueOf("ff:ff:ff:ff:ff:ff");
128 private static final byte[] IP = new byte[]{10, 0, 0, 1};
Thomas Vachuska33601602014-11-19 03:32:15 -0800129 private static final IpAddress IP_ADDRESS =
130 IpAddress.valueOf(IpAddress.Version.INET, IP);
131 private static final HostLocation LOCATION =
132 new HostLocation(deviceId(DEV1), portNumber(INPORT), 0L);
Thomas Vachuska33601602014-11-19 03:32:15 -0800133 private static final DefaultHost HOST =
Charles Chan8b0fdaa2016-02-23 18:35:27 -0800134 new DefaultHost(PROVIDER_ID, hostId(MAC), MAC,
Charles Chane6067892016-11-17 10:23:46 -0800135 VLAN, LOCATION,
136 ImmutableSet.of(IP_ADDRESS));
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700137 private static final DefaultHost HOST_VLAN_100 =
138 new DefaultHost(PROVIDER_ID, hostId(MAC, VLAN_100), MAC,
139 VLAN_100, LOCATION,
140 ImmutableSet.of(IP_ADDRESS));
Thomas Vachuska33601602014-11-19 03:32:15 -0800141
Charles Chan5d5e0622015-09-25 13:00:06 -0700142 // IPv6 Host
143 private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02");
144 private static final MacAddress BCMAC2 = MacAddress.valueOf("33:33:00:00:00:01");
145 private static final byte[] IP2 = Ip6Address.valueOf("1000::1").toOctets();
146 private static final IpAddress IP_ADDRESS2 =
147 IpAddress.valueOf(IpAddress.Version.INET6, IP2);
148 private static final HostLocation LOCATION2 =
149 new HostLocation(deviceId(DEV4), portNumber(INPORT), 0L);
150 private static final DefaultHost HOST2 =
Charles Chan8b0fdaa2016-02-23 18:35:27 -0800151 new DefaultHost(PROVIDER_ID, hostId(MAC2), MAC2,
Charles Chane6067892016-11-17 10:23:46 -0800152 VLAN, LOCATION2,
153 ImmutableSet.of(IP_ADDRESS2));
154
155 // DHCP Server
156 private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03");
157 private static final byte[] IP3 = new byte[]{10, 0, 0, 2};
158 private static final IpAddress IP_ADDRESS3 =
159 IpAddress.valueOf(IpAddress.Version.INET, IP3);
Charles Chane6067892016-11-17 10:23:46 -0800160 private static final HostLocation LOCATION3 =
161 new HostLocation(deviceId(DEV1), portNumber(INPORT2), 0L);
162 private static final DefaultHost HOST3 =
163 new DefaultHost(PROVIDER_ID, hostId(MAC3), MAC3,
164 VLAN, LOCATION3,
165 ImmutableSet.of(IP_ADDRESS3));
Charles Chan5d5e0622015-09-25 13:00:06 -0700166
Yi Tsengfcf5dce2017-07-26 14:30:41 -0700167 // DHCP6 Server
168 private static final MacAddress DHCP6_SERVER_MAC = MacAddress.valueOf("00:00:44:00:00:04");
169 private static final IpAddress DHCP6_SERVER_IP =
170 IpAddress.valueOf("2000::1:1000");
171
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700172 // Gateway information for relay agent
173 private static final InterfaceIpAddress GW_IFACE_ADDR = InterfaceIpAddress.valueOf("10.0.1.1/32");
174 private static final Interface GW_IFACE = new Interface("gateway",
175 LOCATION,
176 ImmutableList.of(GW_IFACE_ADDR),
177 null,
178 VLAN_100);
179
Thomas Vachuska33601602014-11-19 03:32:15 -0800180 private static final ComponentContextAdapter CTX_FOR_REMOVE =
181 new ComponentContextAdapter() {
182 @Override
183 public Dictionary getProperties() {
184 Hashtable<String, String> props = new Hashtable<>();
185 props.put("hostRemovalEnabled", "true");
186 return props;
187 }
188 };
189
190 public static final ComponentContextAdapter CTX_FOR_NO_REMOVE =
191 new ComponentContextAdapter() {
192 @Override
193 public Dictionary getProperties() {
194 return new Hashtable();
195 }
196 };
197
alshabib4a179dc2014-10-17 17:17:01 -0700198 private final HostLocationProvider provider = new HostLocationProvider();
Thomas Vachuska33601602014-11-19 03:32:15 -0800199 private final TestHostRegistry hostRegistry = new TestHostRegistry();
alshabib4a179dc2014-10-17 17:17:01 -0700200 private final TestTopologyService topoService = new TestTopologyService();
Thomas Vachuska33601602014-11-19 03:32:15 -0800201 private final TestDeviceService deviceService = new TestDeviceService();
202 private final TestHostService hostService = new TestHostService();
alshabib4a179dc2014-10-17 17:17:01 -0700203 private final TestPacketService packetService = new TestPacketService();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700204 private final TestInterfaceService interfaceService = new TestInterfaceService();
alshabib4a179dc2014-10-17 17:17:01 -0700205
206 private PacketProcessor testProcessor;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800207 private CoreService coreService;
alshabib4a179dc2014-10-17 17:17:01 -0700208 private TestHostProviderService providerService;
209
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800210 private ApplicationId appId =
211 new DefaultApplicationId(100, "org.onosproject.provider.host");
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800212
alshabib4a179dc2014-10-17 17:17:01 -0700213 @Before
214 public void setUp() {
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800215 coreService = createMock(CoreService.class);
216 expect(coreService.registerApplication(appId.name()))
Thomas Vachuska27bee092015-06-23 19:03:10 -0700217 .andReturn(appId).anyTimes();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800218 replay(coreService);
219
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700220 provider.cfgService = new ComponentConfigAdapter();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800221 provider.coreService = coreService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800222
Thomas Vachuska33601602014-11-19 03:32:15 -0800223 provider.providerRegistry = hostRegistry;
alshabib4a179dc2014-10-17 17:17:01 -0700224 provider.topologyService = topoService;
Pavlin Radoslavovd6612f92015-02-23 13:53:32 -0800225 provider.packetService = packetService;
Thomas Vachuska33601602014-11-19 03:32:15 -0800226 provider.deviceService = deviceService;
227 provider.hostService = hostService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700228 provider.interfaceService = interfaceService;
alshabib4a179dc2014-10-17 17:17:01 -0700229
Thomas Vachuska33601602014-11-19 03:32:15 -0800230 provider.activate(CTX_FOR_NO_REMOVE);
Madan Jampania3770c32015-12-11 12:07:41 -0800231
232 provider.eventHandler = MoreExecutors.newDirectExecutorService();
alshabib4a179dc2014-10-17 17:17:01 -0700233 }
234
235 @Test
236 public void basics() {
237 assertNotNull("registration expected", providerService);
238 assertEquals("incorrect provider", provider, providerService.provider());
239 }
240
241 @Test
242 public void events() {
Charles Chan420e7372016-11-17 10:58:17 -0800243 // New host. Expect one additional host description.
Charles Chan5d5e0622015-09-25 13:00:06 -0700244 testProcessor.process(new TestArpPacketContext(DEV1));
Charles Chan420e7372016-11-17 10:58:17 -0800245 assertThat("New host expected", providerService.descriptions.size(), is(1));
alshabib4a179dc2014-10-17 17:17:01 -0700246
Charles Chan420e7372016-11-17 10:58:17 -0800247 // The host moved to new switch. Expect one additional host description.
248 // The second host description should have a different location.
Charles Chan5d5e0622015-09-25 13:00:06 -0700249 testProcessor.process(new TestArpPacketContext(DEV2));
Charles Chan420e7372016-11-17 10:58:17 -0800250 assertThat("Host motion expected", providerService.descriptions.size(), is(2));
251 HostLocation loc1 = providerService.descriptions.get(0).location();
252 HostLocation loc2 = providerService.descriptions.get(1).location();
253 assertNotEquals("Host location should be different", loc1, loc2);
alshabib4a179dc2014-10-17 17:17:01 -0700254
Charles Chan420e7372016-11-17 10:58:17 -0800255 // The host was misheard on a spine. Expect no additional host description.
Charles Chan5d5e0622015-09-25 13:00:06 -0700256 testProcessor.process(new TestArpPacketContext(DEV3));
Charles Chan420e7372016-11-17 10:58:17 -0800257 assertThat("Host misheard on spine switch", providerService.descriptions.size(), is(2));
Charles Chan5d5e0622015-09-25 13:00:06 -0700258
259 providerService.clear();
260
Charles Chan420e7372016-11-17 10:58:17 -0800261 // New host. Expect one additional host description.
Jonathan Hartb35540a2015-11-17 09:30:56 -0800262 testProcessor.process(new TestNaPacketContext(DEV4));
Charles Chan420e7372016-11-17 10:58:17 -0800263 assertThat("New host expected", providerService.descriptions.size(), is(1));
Charles Chan5d5e0622015-09-25 13:00:06 -0700264
Charles Chan420e7372016-11-17 10:58:17 -0800265 // The host moved to new switch. Expect one additional host description.
266 // The second host description should have a different location.
Jonathan Hartb35540a2015-11-17 09:30:56 -0800267 testProcessor.process(new TestNaPacketContext(DEV5));
Charles Chan420e7372016-11-17 10:58:17 -0800268 assertThat("Host motion expected", providerService.descriptions.size(), is(2));
269 loc1 = providerService.descriptions.get(0).location();
270 loc2 = providerService.descriptions.get(1).location();
271 assertNotEquals("Host location should be different", loc1, loc2);
Charles Chan5d5e0622015-09-25 13:00:06 -0700272
Charles Chan420e7372016-11-17 10:58:17 -0800273 // The host was misheard on a spine. Expect no additional host description.
Jonathan Hartb35540a2015-11-17 09:30:56 -0800274 testProcessor.process(new TestNaPacketContext(DEV6));
Charles Chan420e7372016-11-17 10:58:17 -0800275 assertThat("Host misheard on spine switch", providerService.descriptions.size(), is(2));
alshabib4a179dc2014-10-17 17:17:01 -0700276 }
277
Thomas Vachuska33601602014-11-19 03:32:15 -0800278 @Test
279 public void removeHostByDeviceRemove() {
280 provider.modified(CTX_FOR_REMOVE);
Charles Chan5d5e0622015-09-25 13:00:06 -0700281 testProcessor.process(new TestArpPacketContext(DEV1));
Jonathan Hartb35540a2015-11-17 09:30:56 -0800282 testProcessor.process(new TestNaPacketContext(DEV4));
Charles Chan5d5e0622015-09-25 13:00:06 -0700283
Thomas Vachuska33601602014-11-19 03:32:15 -0800284 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
285 "m", "h", "s", "n", new ChassisId(0L));
286 deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
Charles Chan888e20a2017-05-01 15:44:23 -0700287 assertEquals("incorrect remove count", 2, providerService.locationRemoveCount);
Charles Chan5d5e0622015-09-25 13:00:06 -0700288
289 device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
290 "m", "h", "s", "n", new ChassisId(0L));
291 deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
Charles Chan888e20a2017-05-01 15:44:23 -0700292 assertEquals("incorrect remove count", 3, providerService.locationRemoveCount);
Thomas Vachuska33601602014-11-19 03:32:15 -0800293 }
294
295 @Test
296 public void removeHostByDeviceOffline() {
297 provider.modified(CTX_FOR_REMOVE);
Charles Chan5d5e0622015-09-25 13:00:06 -0700298 testProcessor.process(new TestArpPacketContext(DEV1));
299 testProcessor.process(new TestArpPacketContext(DEV4));
300
Thomas Vachuska33601602014-11-19 03:32:15 -0800301 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
302 "m", "h", "s", "n", new ChassisId(0L));
303 deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
Charles Chan888e20a2017-05-01 15:44:23 -0700304 assertEquals("incorrect remove count", 2, providerService.locationRemoveCount);
Charles Chan5d5e0622015-09-25 13:00:06 -0700305
306 device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
307 "m", "h", "s", "n", new ChassisId(0L));
308 deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
Charles Chan888e20a2017-05-01 15:44:23 -0700309 assertEquals("incorrect remove count", 3, providerService.locationRemoveCount);
Thomas Vachuska33601602014-11-19 03:32:15 -0800310 }
311
312 @Test
313 public void removeHostByDevicePortDown() {
314 provider.modified(CTX_FOR_REMOVE);
Charles Chan5d5e0622015-09-25 13:00:06 -0700315 testProcessor.process(new TestArpPacketContext(DEV1));
316 testProcessor.process(new TestArpPacketContext(DEV4));
317
Thomas Vachuska33601602014-11-19 03:32:15 -0800318 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
319 "m", "h", "s", "n", new ChassisId(0L));
320 deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
Charles Chan5d5e0622015-09-25 13:00:06 -0700321 new DefaultPort(device, portNumber(INPORT), false)));
Charles Chan888e20a2017-05-01 15:44:23 -0700322 assertEquals("incorrect remove count", 1, providerService.locationRemoveCount);
Charles Chan5d5e0622015-09-25 13:00:06 -0700323
324 device = new DefaultDevice(ProviderId.NONE, deviceId(DEV4), SWITCH,
325 "m", "h", "s", "n", new ChassisId(0L));
326 deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
327 new DefaultPort(device, portNumber(INPORT), false)));
Charles Chan888e20a2017-05-01 15:44:23 -0700328 assertEquals("incorrect remove count", 2, providerService.locationRemoveCount);
Thomas Vachuska33601602014-11-19 03:32:15 -0800329 }
330
Charles Chan5d5e0622015-09-25 13:00:06 -0700331 /**
332 * When receiving ARP, updates location and IP.
333 */
334 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300335 public void receiveArp() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700336 testProcessor.process(new TestArpPacketContext(DEV1));
Andrey Komarov2398d962016-09-26 15:11:23 +0300337 assertThat("receiveArp. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800338 providerService.descriptions.size(), is(1));
339 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700340 assertThat(descr.location(), is(LOCATION));
341 assertThat(descr.hwAddress(), is(MAC));
342 assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS));
343 assertThat(descr.vlan(), is(VLAN));
344 }
345
346 /**
347 * When receiving IPv4, updates location only.
348 */
349 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300350 public void receiveIpv4() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700351 testProcessor.process(new TestIpv4PacketContext(DEV1));
Andrey Komarov2398d962016-09-26 15:11:23 +0300352 assertThat("receiveIpv4. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800353 providerService.descriptions.size(), is(1));
354 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700355 assertThat(descr.location(), is(LOCATION));
356 assertThat(descr.hwAddress(), is(MAC));
357 assertThat(descr.ipAddress().size(), is(0));
358 assertThat(descr.vlan(), is(VLAN));
359 }
360
361 /**
Charles Chane6067892016-11-17 10:23:46 -0800362 * When receiving DHCP REQUEST, update MAC, location of client.
363 * When receiving DHCP ACK, update MAC, location of server and IP of client.
364 */
365 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300366 public void receiveDhcp() {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700367 TestUtils.setField(provider, "useDhcp", true);
Charles Chane6067892016-11-17 10:23:46 -0800368 // DHCP Request
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700369 testProcessor.process(new TestDhcpRequestPacketContext(DEV1, VLAN));
Andrey Komarov2398d962016-09-26 15:11:23 +0300370 assertThat("receiveDhcpRequest. One host description expected",
Charles Chane6067892016-11-17 10:23:46 -0800371 providerService.descriptions.size(), is(1));
372 // Should learn the MAC and location of DHCP client
373 HostDescription descr = providerService.descriptions.get(0);
374 assertThat(descr.location(), is(LOCATION));
375 assertThat(descr.hwAddress(), is(MAC));
376 assertThat(descr.ipAddress().size(), is(0));
377 assertThat(descr.vlan(), is(VLAN));
378
379 // DHCP Ack
Yi Tsengfcf5dce2017-07-26 14:30:41 -0700380 testProcessor.process(new TestDhcpAckPacketContext(DEV1));
Andrey Komarov2398d962016-09-26 15:11:23 +0300381 assertThat("receiveDhcpAck. Two additional host descriptions expected",
Yi Tsengcfa637a2017-07-26 17:24:10 -0700382 providerService.descriptions.size(), is(3));
Charles Chane6067892016-11-17 10:23:46 -0800383
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700384 // Should also learn the MAC, location of DHCP server
385 HostDescription descr2 = providerService.descriptions.get(1);
386 assertThat(descr2.location(), is(LOCATION3));
387 assertThat(descr2.hwAddress(), is(MAC3));
388 assertThat(descr2.ipAddress().size(), is(0));
389 assertThat(descr2.vlan(), is(VLAN));
390
Yi Tsengcfa637a2017-07-26 17:24:10 -0700391 // Should update the IP address of the client.
392 HostDescription descr3 = providerService.descriptions.get(2);
393 assertThat(descr3.location(), is(LOCATION));
394 assertThat(descr3.hwAddress(), is(MAC));
395 assertThat(descr3.ipAddress().size(), is(1));
396 IpAddress ip = descr3.ipAddress().iterator().next();
397 assertThat(ip, is(IP_ADDRESS.getIp4Address()));
398 assertThat(descr3.vlan(), is(VLAN));
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700399 }
400
401 /**
Yi Tsengfcf5dce2017-07-26 14:30:41 -0700402 * When receiving DHCPv6 REQUEST, update MAC, location of client.
403 * When receiving DHCPv6 ACK, update MAC, location of server and IP of client.
404 */
405 @Test
406 public void receiveDhcp6() {
407 TestUtils.setField(provider, "useDhcp6", true);
408 // DHCP Request
409 testProcessor.process(new TestDhcp6RequestPacketContext(DEV4, VLAN));
410 assertThat("receiveDhcpRequest. One host description expected",
411 providerService.descriptions.size(), is(1));
412 // Should learn the MAC and location of DHCP client
413 HostDescription descr = providerService.descriptions.get(0);
414 assertThat(descr.location(), is(LOCATION2));
415 assertThat(descr.hwAddress(), is(MAC2));
416 assertThat(descr.ipAddress().size(), is(0));
417 assertThat(descr.vlan(), is(VLAN));
418
419 // DHCP Ack
420 testProcessor.process(new TestDhcp6AckPacketContext(DEV1));
421 assertThat("receiveDhcpAck. Two additional host descriptions expected",
422 providerService.descriptions.size(), is(3));
423
424 // Should also learn the MAC, location of DHCP server
425 HostDescription descr2 = providerService.descriptions.get(1);
426 assertThat(descr2.location(), is(LOCATION3));
427 assertThat(descr2.hwAddress(), is(DHCP6_SERVER_MAC));
428 assertThat(descr2.ipAddress().size(), is(0));
429 assertThat(descr2.vlan(), is(VLAN));
430
431 // Should update the IP address of the DHCP client.
432 HostDescription descr3 = providerService.descriptions.get(2);
433 assertThat(descr3.location(), is(LOCATION2));
434 assertThat(descr3.hwAddress(), is(MAC2));
435 assertThat(descr3.ipAddress().size(), is(1));
436 IpAddress ip = descr3.ipAddress().iterator().next();
437 assertThat(ip, is(IP_ADDRESS2.getIp6Address()));
438 assertThat(descr3.vlan(), is(VLAN));
439 }
440
441 /**
Charles Chan5d5e0622015-09-25 13:00:06 -0700442 * When receiving NeighborAdvertisement, updates location and IP.
443 */
444 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300445 public void receiveNa() {
Jonathan Hartb35540a2015-11-17 09:30:56 -0800446 testProcessor.process(new TestNaPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300447 assertThat("receiveNa. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800448 providerService.descriptions.size(), is(1));
449 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700450 assertThat(descr.location(), is(LOCATION2));
451 assertThat(descr.hwAddress(), is(MAC2));
452 assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS2));
453 assertThat(descr.vlan(), is(VLAN));
454 }
455
456 /**
457 * When receiving NeighborSolicitation, updates location and IP.
458 */
459 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300460 public void receiveNs() {
Jonathan Hartb35540a2015-11-17 09:30:56 -0800461 testProcessor.process(new TestNsPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300462 assertThat("receiveNs. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800463 providerService.descriptions.size(), is(1));
464 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700465 assertThat(descr.location(), is(LOCATION2));
466 assertThat(descr.hwAddress(), is(MAC2));
467 assertThat(descr.ipAddress().toArray()[0], is(IP_ADDRESS2));
468 assertThat(descr.vlan(), is(VLAN));
469 }
470
471 /**
472 * When receiving RouterAdvertisement, ignores it.
473 */
474 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300475 public void receivesRa() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700476 testProcessor.process(new TestRAPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300477 assertThat("receivesRa. No host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800478 providerService.descriptions.size(), is(0));
Charles Chan5d5e0622015-09-25 13:00:06 -0700479 }
480
481 /**
482 * When receiving RouterSolicitation, ignores it.
483 */
484 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300485 public void receiveRs() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700486 testProcessor.process(new TestRSPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300487 assertThat("receiveRs. No host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800488 providerService.descriptions.size(), is(0));
Charles Chan5d5e0622015-09-25 13:00:06 -0700489 }
490
491 /**
492 * When receiving Duplicate Address Detection (DAD), ignores it.
493 */
494 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300495 public void receiveDad() {
Jonathan Hartb35540a2015-11-17 09:30:56 -0800496 testProcessor.process(new TestDadPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300497 assertThat("receiveDad. No host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800498 providerService.descriptions.size(), is(0));
Charles Chan5d5e0622015-09-25 13:00:06 -0700499 }
500
501 /**
502 * When receiving IPv6 multicast packet, ignores it.
503 */
504 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300505 public void receiveIpv6Multicast() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700506 testProcessor.process(new TestIpv6McastPacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300507 assertThat("receiveIpv6Multicast. No host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800508 providerService.descriptions.size(), is(0));
Charles Chan5d5e0622015-09-25 13:00:06 -0700509 }
510
511 /**
512 * When receiving IPv6 unicast packet, updates location only.
513 */
514 @Test
Andrey Komarov2398d962016-09-26 15:11:23 +0300515 public void receiveIpv6Unicast() {
Charles Chan5d5e0622015-09-25 13:00:06 -0700516 testProcessor.process(new TestIpv6PacketContext(DEV4));
Andrey Komarov2398d962016-09-26 15:11:23 +0300517 assertThat("receiveIpv6Unicast. One host description expected",
Charles Chan420e7372016-11-17 10:58:17 -0800518 providerService.descriptions.size(), is(1));
519 HostDescription descr = providerService.descriptions.get(0);
Charles Chan5d5e0622015-09-25 13:00:06 -0700520 assertThat(descr.location(), is(LOCATION2));
521 assertThat(descr.hwAddress(), is(MAC2));
522 assertThat(descr.ipAddress().size(), is(0));
523 assertThat(descr.vlan(), is(VLAN));
524 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800525
alshabib4a179dc2014-10-17 17:17:01 -0700526 @After
527 public void tearDown() {
528 provider.deactivate();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800529 provider.coreService = null;
alshabib4a179dc2014-10-17 17:17:01 -0700530 provider.providerRegistry = null;
alshabib4a179dc2014-10-17 17:17:01 -0700531 }
532
533 private class TestHostRegistry implements HostProviderRegistry {
534
535 @Override
536 public HostProviderService register(HostProvider provider) {
537 providerService = new TestHostProviderService(provider);
538 return providerService;
539 }
540
541 @Override
542 public void unregister(HostProvider provider) {
543 }
544
545 @Override
546 public Set<ProviderId> getProviders() {
547 return null;
548 }
549
550 }
551
552 private class TestHostProviderService
553 extends AbstractProviderService<HostProvider>
554 implements HostProviderService {
555
Charles Chan420e7372016-11-17 10:58:17 -0800556 List<HostDescription> descriptions = Lists.newArrayList();
Charles Chan888e20a2017-05-01 15:44:23 -0700557 int hostRemoveCount;
558 int ipRemoveCount;
559 int locationRemoveCount;
alshabib4a179dc2014-10-17 17:17:01 -0700560
Charles Chan5d5e0622015-09-25 13:00:06 -0700561 public void clear() {
Charles Chan420e7372016-11-17 10:58:17 -0800562 descriptions.clear();
Charles Chan888e20a2017-05-01 15:44:23 -0700563 hostRemoveCount = 0;
564 ipRemoveCount = 0;
565 locationRemoveCount = 0;
Charles Chan5d5e0622015-09-25 13:00:06 -0700566 }
567
alshabib4a179dc2014-10-17 17:17:01 -0700568 protected TestHostProviderService(HostProvider provider) {
569 super(provider);
570 }
571
572 @Override
Brian O'Connorf107bd72015-09-21 15:31:03 -0700573 public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) {
Charles Chan420e7372016-11-17 10:58:17 -0800574 descriptions.add(hostDescription);
alshabib4a179dc2014-10-17 17:17:01 -0700575 }
576
577 @Override
578 public void hostVanished(HostId hostId) {
Charles Chan888e20a2017-05-01 15:44:23 -0700579 hostRemoveCount++;
alshabib4a179dc2014-10-17 17:17:01 -0700580 }
581
samanwita palc40e5ed2015-09-24 11:01:51 -0700582 @Override
583 public void removeIpFromHost(HostId hostId, IpAddress ipAddress) {
Charles Chan888e20a2017-05-01 15:44:23 -0700584 ipRemoveCount++;
585 }
586
587 @Override
588 public void removeLocationFromHost(HostId hostId, HostLocation location) {
589 locationRemoveCount++;
samanwita palc40e5ed2015-09-24 11:01:51 -0700590 }
591
alshabib4a179dc2014-10-17 17:17:01 -0700592 }
593
Thomas Vachuska27bee092015-06-23 19:03:10 -0700594 private class TestPacketService extends PacketServiceAdapter {
alshabib4a179dc2014-10-17 17:17:01 -0700595 @Override
596 public void addProcessor(PacketProcessor processor, int priority) {
597 testProcessor = processor;
598 }
alshabib4a179dc2014-10-17 17:17:01 -0700599 }
600
alshabib4a179dc2014-10-17 17:17:01 -0700601 private class TestTopologyService extends TopologyServiceAdapter {
602 @Override
603 public boolean isInfrastructure(Topology topology,
604 ConnectPoint connectPoint) {
605 //simulate DPID3 as an infrastructure switch
Charles Chan5d5e0622015-09-25 13:00:06 -0700606 if ((connectPoint.deviceId()).equals(deviceId(DEV3)) ||
607 connectPoint.deviceId().equals(deviceId(DEV6))) {
alshabib4a179dc2014-10-17 17:17:01 -0700608 return true;
609 }
610 return false;
611 }
612 }
613
Charles Chan5d5e0622015-09-25 13:00:06 -0700614 /**
615 * Generates ARP packet.
616 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300617 private class TestArpPacketContext extends PacketContextAdapter {
alshabib4a179dc2014-10-17 17:17:01 -0700618 private final String deviceId;
619
Charles Chan5d5e0622015-09-25 13:00:06 -0700620 public TestArpPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300621 super(0, null, null, false);
alshabib4a179dc2014-10-17 17:17:01 -0700622 this.deviceId = deviceId;
623 }
624
625 @Override
alshabib4a179dc2014-10-17 17:17:01 -0700626 public InboundPacket inPacket() {
627 ARP arp = new ARP();
628 arp.setSenderProtocolAddress(IP)
629 .setSenderHardwareAddress(MAC.toBytes())
630 .setTargetHardwareAddress(BCMAC.toBytes())
631 .setTargetProtocolAddress(IP);
632
633 Ethernet eth = new Ethernet();
634 eth.setEtherType(Ethernet.TYPE_ARP)
635 .setVlanID(VLAN.toShort())
636 .setSourceMACAddress(MAC.toBytes())
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800637 .setDestinationMACAddress(BCMAC)
alshabib4a179dc2014-10-17 17:17:01 -0700638 .setPayload(arp);
Thomas Vachuska33601602014-11-19 03:32:15 -0800639 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
640 portNumber(INPORT));
alshabib4a179dc2014-10-17 17:17:01 -0700641 return new DefaultInboundPacket(receivedFrom, eth,
642 ByteBuffer.wrap(eth.serialize()));
643 }
alshabib4a179dc2014-10-17 17:17:01 -0700644 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800645
Charles Chan5d5e0622015-09-25 13:00:06 -0700646 /**
Charles Chane6067892016-11-17 10:23:46 -0800647 * Generates IPv4 Unicast packet.
Charles Chan5d5e0622015-09-25 13:00:06 -0700648 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300649 private class TestIpv4PacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700650 private final String deviceId;
651
652 public TestIpv4PacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300653 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700654 this.deviceId = deviceId;
655 }
656
657 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700658 public InboundPacket inPacket() {
659 IPv4 ipv4 = new IPv4();
660 ipv4.setDestinationAddress("10.0.0.1");
661 ipv4.setSourceAddress(IP_ADDRESS.toString());
662 Ethernet eth = new Ethernet();
663 eth.setEtherType(Ethernet.TYPE_IPV4)
664 .setVlanID(VLAN.toShort())
665 .setSourceMACAddress(MAC)
666 .setDestinationMACAddress(MacAddress.valueOf("00:00:00:00:00:01"))
667 .setPayload(ipv4);
668 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
669 portNumber(INPORT));
670 return new DefaultInboundPacket(receivedFrom, eth,
671 ByteBuffer.wrap(eth.serialize()));
672 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700673 }
Yi Tsengfcf5dce2017-07-26 14:30:41 -0700674
Charles Chane6067892016-11-17 10:23:46 -0800675 /**
676 * Generates DHCP REQUEST packet.
677 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300678 private class TestDhcpRequestPacketContext extends PacketContextAdapter {
Charles Chane6067892016-11-17 10:23:46 -0800679 private final String deviceId;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700680 private final VlanId vlanId;
Charles Chane6067892016-11-17 10:23:46 -0800681
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700682 public TestDhcpRequestPacketContext(String deviceId, VlanId vlanId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300683 super(0, null, null, false);
Charles Chane6067892016-11-17 10:23:46 -0800684 this.deviceId = deviceId;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700685 this.vlanId = vlanId;
Charles Chane6067892016-11-17 10:23:46 -0800686 }
687
688 @Override
Charles Chane6067892016-11-17 10:23:46 -0800689 public InboundPacket inPacket() {
690 byte[] dhcpMsgType = new byte[1];
Yi Tsengc7403c22017-06-19 16:23:22 -0700691 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPREQUEST.getValue();
Charles Chane6067892016-11-17 10:23:46 -0800692
Yi Tsengc7403c22017-06-19 16:23:22 -0700693 DhcpOption dhcpOption = new DhcpOption();
Charles Chane6067892016-11-17 10:23:46 -0800694 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
695 dhcpOption.setData(dhcpMsgType);
696 dhcpOption.setLength((byte) 1);
697 DHCP dhcp = new DHCP();
698 dhcp.setOptions(Collections.singletonList(dhcpOption));
699 dhcp.setClientHardwareAddress(MAC.toBytes());
700 UDP udp = new UDP();
701 udp.setPayload(dhcp);
702 udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
703 udp.setDestinationPort(UDP.DHCP_SERVER_PORT);
704 IPv4 ipv4 = new IPv4();
705 ipv4.setPayload(udp);
706 ipv4.setDestinationAddress(IP_ADDRESS3.toString());
707 ipv4.setSourceAddress(IP_ADDRESS.toString());
708 Ethernet eth = new Ethernet();
709 eth.setEtherType(Ethernet.TYPE_IPV4)
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700710 .setVlanID(this.vlanId.toShort())
Charles Chane6067892016-11-17 10:23:46 -0800711 .setSourceMACAddress(MAC)
712 .setDestinationMACAddress(MAC3)
713 .setPayload(ipv4);
714 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
715 portNumber(INPORT));
716 return new DefaultInboundPacket(receivedFrom, eth,
717 ByteBuffer.wrap(eth.serialize()));
718 }
Charles Chane6067892016-11-17 10:23:46 -0800719 }
720
721 /**
722 * Generates DHCP ACK packet.
723 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300724 private class TestDhcpAckPacketContext extends PacketContextAdapter {
Charles Chane6067892016-11-17 10:23:46 -0800725 private final String deviceId;
726
Yi Tsengfcf5dce2017-07-26 14:30:41 -0700727 public TestDhcpAckPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300728 super(0, null, null, false);
Charles Chane6067892016-11-17 10:23:46 -0800729 this.deviceId = deviceId;
730 }
731
732 @Override
Charles Chane6067892016-11-17 10:23:46 -0800733 public InboundPacket inPacket() {
734 byte[] dhcpMsgType = new byte[1];
Yi Tsengc7403c22017-06-19 16:23:22 -0700735 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPACK.getValue();
Charles Chane6067892016-11-17 10:23:46 -0800736
Yi Tsengc7403c22017-06-19 16:23:22 -0700737 DhcpOption dhcpOption = new DhcpOption();
Charles Chane6067892016-11-17 10:23:46 -0800738 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
739 dhcpOption.setData(dhcpMsgType);
740 dhcpOption.setLength((byte) 1);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700741
Charles Chane6067892016-11-17 10:23:46 -0800742 DHCP dhcp = new DHCP();
Yi Tsengfcf5dce2017-07-26 14:30:41 -0700743 dhcp.setOptions(ImmutableList.of(dhcpOption));
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700744
Charles Chane6067892016-11-17 10:23:46 -0800745 dhcp.setClientHardwareAddress(MAC.toBytes());
746 dhcp.setYourIPAddress(IP_ADDRESS.getIp4Address().toInt());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700747
Charles Chane6067892016-11-17 10:23:46 -0800748 UDP udp = new UDP();
749 udp.setPayload(dhcp);
750 udp.setSourcePort(UDP.DHCP_SERVER_PORT);
751 udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
752 IPv4 ipv4 = new IPv4();
753 ipv4.setPayload(udp);
754 ipv4.setDestinationAddress(IP_ADDRESS.toString());
755 ipv4.setSourceAddress(IP_ADDRESS3.toString());
756 Ethernet eth = new Ethernet();
757 eth.setEtherType(Ethernet.TYPE_IPV4)
758 .setVlanID(VLAN.toShort())
759 .setSourceMACAddress(MAC3)
760 .setDestinationMACAddress(MAC)
761 .setPayload(ipv4);
762 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
763 portNumber(INPORT2));
764 return new DefaultInboundPacket(receivedFrom, eth,
765 ByteBuffer.wrap(eth.serialize()));
766 }
Charles Chane6067892016-11-17 10:23:46 -0800767 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700768
769 /**
Yi Tsengfcf5dce2017-07-26 14:30:41 -0700770 * Generates DHCPv6 REQUEST packet.
771 */
772 private class TestDhcp6RequestPacketContext extends PacketContextAdapter {
773 private final String deviceId;
774 private final VlanId vlanId;
775
776 public TestDhcp6RequestPacketContext(String deviceId, VlanId vlanId) {
777 super(0, null, null, false);
778 this.deviceId = deviceId;
779 this.vlanId = vlanId;
780 }
781
782 @Override
783 public InboundPacket inPacket() {
784
785 DHCP6 dhcp6 = new DHCP6();
786 dhcp6.setMsgType(DHCP6.MsgType.REQUEST.value());
787 List<Dhcp6Option> options = Lists.newArrayList();
788
789 // IA address
790 Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
791 iaAddressOption.setIp6Address(IP_ADDRESS2.getIp6Address());
792
793 // IA NA
794 Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
795 iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
796 options.add(iaNaOption);
797
798 dhcp6.setOptions(options);
799
800 UDP udp = new UDP();
801 udp.setPayload(dhcp6);
802 udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
803 udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
804 IPv6 ipv6 = new IPv6();
805 ipv6.setPayload(udp);
806 ipv6.setDestinationAddress(Ip6Address.ZERO.toOctets());
807 ipv6.setSourceAddress(Ip6Address.ZERO.toOctets());
808 ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
809 Ethernet eth = new Ethernet();
810 eth.setEtherType(Ethernet.TYPE_IPV6)
811 .setVlanID(this.vlanId.toShort())
812 .setSourceMACAddress(MAC2)
813 .setDestinationMACAddress(DHCP6_SERVER_MAC)
814 .setPayload(ipv6);
815 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
816 portNumber(INPORT));
817 return new DefaultInboundPacket(receivedFrom, eth,
818 ByteBuffer.wrap(eth.serialize()));
819 }
820 }
821
822 /**
823 * Generates DHCPv6 ACK packet.
824 */
825 private class TestDhcp6AckPacketContext extends PacketContextAdapter {
826 private final String deviceId;
827
828 public TestDhcp6AckPacketContext(String deviceId) {
829 super(0, null, null, false);
830 this.deviceId = deviceId;
831 }
832
833 @Override
834 public InboundPacket inPacket() {
835 DHCP6 dhcp6 = new DHCP6();
836 dhcp6.setMsgType(DHCP6.MsgType.REPLY.value());
837 List<Dhcp6Option> options = Lists.newArrayList();
838
839 // IA address
840 Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
841 iaAddressOption.setIp6Address(IP_ADDRESS2.getIp6Address());
842
843 // IA NA
844 Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
845 iaNaOption.setOptions(ImmutableList.of(iaAddressOption));
846 options.add(iaNaOption);
847
848 // Client ID
849 Dhcp6Duid duid = new Dhcp6Duid();
850 duid.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
851 duid.setHardwareType((short) 1);
852 duid.setDuidTime(0);
853 duid.setLinkLayerAddress(MAC2.toBytes());
854 Dhcp6ClientIdOption clientIdOption = new Dhcp6ClientIdOption();
855 clientIdOption.setDuid(duid);
856 options.add(clientIdOption);
857 dhcp6.setOptions(options);
858
859 UDP udp = new UDP();
860 udp.setPayload(dhcp6);
861 udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
862 udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
863 IPv6 ipv6 = new IPv6();
864 ipv6.setPayload(udp);
865 ipv6.setDestinationAddress(Ip6Address.ZERO.toOctets());
866 ipv6.setSourceAddress(Ip6Address.ZERO.toOctets());
867 ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
868 Ethernet eth = new Ethernet();
869 eth.setEtherType(Ethernet.TYPE_IPV6)
870 .setVlanID(VLAN.toShort())
871 .setSourceMACAddress(DHCP6_SERVER_MAC)
872 .setDestinationMACAddress(MAC2)
873 .setPayload(ipv6);
874 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
875 portNumber(INPORT2));
876 return new DefaultInboundPacket(receivedFrom, eth,
877 ByteBuffer.wrap(eth.serialize()));
878 }
879 }
880
881 /**
Charles Chan5d5e0622015-09-25 13:00:06 -0700882 * Generates NeighborAdvertisement packet.
883 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300884 private class TestNaPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700885 private final String deviceId;
886
Jonathan Hartb35540a2015-11-17 09:30:56 -0800887 public TestNaPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300888 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700889 this.deviceId = deviceId;
890 }
891
892 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700893 public InboundPacket inPacket() {
894 NeighborAdvertisement na = new NeighborAdvertisement();
895 ICMP6 icmp6 = new ICMP6();
896 icmp6.setPayload(na);
897 IPv6 ipv6 = new IPv6();
898 ipv6.setPayload(icmp6);
899 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
900 ipv6.setSourceAddress(IP2);
901 Ethernet eth = new Ethernet();
902 eth.setEtherType(Ethernet.TYPE_IPV6)
903 .setVlanID(VLAN.toShort())
904 .setSourceMACAddress(MAC2.toBytes())
905 .setDestinationMACAddress(BCMAC2)
906 .setPayload(ipv6);
907 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
908 portNumber(INPORT));
909 return new DefaultInboundPacket(receivedFrom, eth,
910 ByteBuffer.wrap(eth.serialize()));
911 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700912 }
913
914 /**
915 * Generates NeighborSolicitation packet.
916 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300917 private class TestNsPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700918 private final String deviceId;
919
Jonathan Hartb35540a2015-11-17 09:30:56 -0800920 public TestNsPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300921 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700922 this.deviceId = deviceId;
923 }
924
925 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700926 public InboundPacket inPacket() {
927 NeighborSolicitation ns = new NeighborSolicitation();
928 ICMP6 icmp6 = new ICMP6();
929 icmp6.setPayload(ns);
930 IPv6 ipv6 = new IPv6();
931 ipv6.setPayload(icmp6);
932 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1:ff00:0000").toOctets());
933 ipv6.setSourceAddress(IP2);
934 Ethernet eth = new Ethernet();
935 eth.setEtherType(Ethernet.TYPE_IPV6)
936 .setVlanID(VLAN.toShort())
937 .setSourceMACAddress(MAC2.toBytes())
938 .setDestinationMACAddress(BCMAC2)
939 .setPayload(ipv6);
940 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
941 portNumber(INPORT));
942 return new DefaultInboundPacket(receivedFrom, eth,
943 ByteBuffer.wrap(eth.serialize()));
944 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700945 }
946
947 /**
948 * Generates Duplicate Address Detection packet.
949 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300950 private class TestDadPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700951 private final String deviceId;
952
Jonathan Hartb35540a2015-11-17 09:30:56 -0800953 public TestDadPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300954 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700955 this.deviceId = deviceId;
956 }
957
958 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700959 public InboundPacket inPacket() {
960 NeighborSolicitation ns = new NeighborSolicitation();
961 ICMP6 icmp6 = new ICMP6();
962 icmp6.setPayload(ns);
963 IPv6 ipv6 = new IPv6();
964 ipv6.setPayload(icmp6);
965 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
966 ipv6.setSourceAddress(Ip6Address.valueOf("::").toOctets());
967 Ethernet eth = new Ethernet();
968 eth.setEtherType(Ethernet.TYPE_IPV6)
969 .setVlanID(VLAN.toShort())
970 .setSourceMACAddress(MAC2.toBytes())
971 .setDestinationMACAddress(BCMAC2)
972 .setPayload(ipv6);
973 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
974 portNumber(INPORT));
975 return new DefaultInboundPacket(receivedFrom, eth,
976 ByteBuffer.wrap(eth.serialize()));
977 }
Charles Chan5d5e0622015-09-25 13:00:06 -0700978 }
979
980 /**
981 * Generates Router Solicitation packet.
982 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300983 private class TestRSPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -0700984 private final String deviceId;
985
986 public TestRSPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300987 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -0700988 this.deviceId = deviceId;
989 }
990
991 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -0700992 public InboundPacket inPacket() {
993 RouterSolicitation ns = new RouterSolicitation();
994 ICMP6 icmp6 = new ICMP6();
995 icmp6.setPayload(ns);
996 IPv6 ipv6 = new IPv6();
997 ipv6.setPayload(icmp6);
998 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::2").toOctets());
999 ipv6.setSourceAddress(Ip6Address.valueOf("::").toOctets());
1000 Ethernet eth = new Ethernet();
1001 eth.setEtherType(Ethernet.TYPE_IPV6)
1002 .setVlanID(VLAN.toShort())
1003 .setSourceMACAddress(MAC2.toBytes())
1004 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:02"))
1005 .setPayload(ipv6);
1006 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
1007 portNumber(INPORT));
1008 return new DefaultInboundPacket(receivedFrom, eth,
1009 ByteBuffer.wrap(eth.serialize()));
1010 }
Charles Chan5d5e0622015-09-25 13:00:06 -07001011 }
1012
1013 /**
1014 * Generates Router Advertisement packet.
1015 */
Andrey Komarov2398d962016-09-26 15:11:23 +03001016 private class TestRAPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -07001017 private final String deviceId;
1018
1019 public TestRAPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +03001020 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -07001021 this.deviceId = deviceId;
1022 }
1023
1024 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -07001025 public InboundPacket inPacket() {
1026 RouterAdvertisement ns = new RouterAdvertisement();
1027 ICMP6 icmp6 = new ICMP6();
1028 icmp6.setPayload(ns);
1029 IPv6 ipv6 = new IPv6();
1030 ipv6.setPayload(icmp6);
1031 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
1032 ipv6.setSourceAddress(IP2);
1033 Ethernet eth = new Ethernet();
1034 eth.setEtherType(Ethernet.TYPE_IPV6)
1035 .setVlanID(VLAN.toShort())
1036 .setSourceMACAddress(MAC2.toBytes())
1037 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:01"))
1038 .setPayload(ipv6);
1039 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
1040 portNumber(INPORT));
1041 return new DefaultInboundPacket(receivedFrom, eth,
1042 ByteBuffer.wrap(eth.serialize()));
1043 }
Charles Chan5d5e0622015-09-25 13:00:06 -07001044 }
1045
1046 /**
1047 * Generates IPv6 Multicast packet.
1048 */
Andrey Komarov2398d962016-09-26 15:11:23 +03001049 private class TestIpv6McastPacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -07001050 private final String deviceId;
1051
1052 public TestIpv6McastPacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +03001053 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -07001054 this.deviceId = deviceId;
1055 }
1056
1057 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -07001058 public InboundPacket inPacket() {
1059 IPv6 ipv6 = new IPv6();
1060 ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
1061 ipv6.setSourceAddress(IP2);
1062 Ethernet eth = new Ethernet();
1063 eth.setEtherType(Ethernet.TYPE_IPV6)
1064 .setVlanID(VLAN.toShort())
1065 .setSourceMACAddress(MAC2.toBytes())
1066 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:00:00:01"))
1067 .setPayload(ipv6);
1068 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
1069 portNumber(INPORT));
1070 return new DefaultInboundPacket(receivedFrom, eth,
1071 ByteBuffer.wrap(eth.serialize()));
1072 }
Charles Chan5d5e0622015-09-25 13:00:06 -07001073 }
1074
1075 /**
1076 * Generates IPv6 Unicast packet.
1077 */
Andrey Komarov2398d962016-09-26 15:11:23 +03001078 private class TestIpv6PacketContext extends PacketContextAdapter {
Charles Chan5d5e0622015-09-25 13:00:06 -07001079 private final String deviceId;
1080
1081 public TestIpv6PacketContext(String deviceId) {
Andrey Komarov2398d962016-09-26 15:11:23 +03001082 super(0, null, null, false);
Charles Chan5d5e0622015-09-25 13:00:06 -07001083 this.deviceId = deviceId;
1084 }
1085
1086 @Override
Charles Chan5d5e0622015-09-25 13:00:06 -07001087 public InboundPacket inPacket() {
1088 IPv6 ipv6 = new IPv6();
1089 ipv6.setDestinationAddress(Ip6Address.valueOf("1000::1").toOctets());
1090 ipv6.setSourceAddress(IP2);
1091 Ethernet eth = new Ethernet();
1092 eth.setEtherType(Ethernet.TYPE_IPV6)
1093 .setVlanID(VLAN.toShort())
1094 .setSourceMACAddress(MAC2)
1095 .setDestinationMACAddress(MacAddress.valueOf("00:00:00:00:00:01"))
1096 .setPayload(ipv6);
1097 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
1098 portNumber(INPORT));
1099 return new DefaultInboundPacket(receivedFrom, eth,
1100 ByteBuffer.wrap(eth.serialize()));
1101 }
Charles Chan5d5e0622015-09-25 13:00:06 -07001102 }
1103
Thomas Vachuska33601602014-11-19 03:32:15 -08001104 private class TestDeviceService extends DeviceServiceAdapter {
1105 private DeviceListener listener;
1106
1107 @Override
1108 public void addListener(DeviceListener listener) {
1109 this.listener = listener;
1110 }
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -08001111
1112 @Override
1113 public Iterable<Device> getDevices() {
1114 return Collections.emptyList();
1115 }
Thomas Vachuska33601602014-11-19 03:32:15 -08001116 }
1117
1118 private class TestHostService extends HostServiceAdapter {
1119 @Override
1120 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Charles Chan5d5e0622015-09-25 13:00:06 -07001121 ConnectPoint cp1 = new ConnectPoint(deviceId(DEV1), portNumber(INPORT));
1122 ConnectPoint cp2 = new ConnectPoint(deviceId(DEV4), portNumber(INPORT));
Charles Chane6067892016-11-17 10:23:46 -08001123 ConnectPoint cp3 = new ConnectPoint(deviceId(DEV1), portNumber(INPORT2));
Charles Chan5d5e0622015-09-25 13:00:06 -07001124 if (connectPoint.equals(cp1)) {
1125 return ImmutableSet.of(HOST);
1126 } else if (connectPoint.equals(cp2)) {
1127 return ImmutableSet.of(HOST2);
Charles Chane6067892016-11-17 10:23:46 -08001128 } else if (connectPoint.equals(cp3)) {
1129 return ImmutableSet.of(HOST3);
Charles Chan5d5e0622015-09-25 13:00:06 -07001130 } else {
1131 return ImmutableSet.of();
1132 }
Thomas Vachuska33601602014-11-19 03:32:15 -08001133 }
1134
1135 @Override
1136 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Charles Chan5d5e0622015-09-25 13:00:06 -07001137 if (deviceId.equals(deviceId(DEV1))) {
Charles Chane6067892016-11-17 10:23:46 -08001138 return ImmutableSet.of(HOST, HOST3);
Charles Chan5d5e0622015-09-25 13:00:06 -07001139 } else if (deviceId.equals(deviceId(DEV4))) {
1140 return ImmutableSet.of(HOST2);
1141 } else {
1142 return ImmutableSet.of();
1143 }
Thomas Vachuska33601602014-11-19 03:32:15 -08001144 }
1145
Charles Chane6067892016-11-17 10:23:46 -08001146 @Override
1147 public Host getHost(HostId hostId) {
1148 if (hostId.equals(HostId.hostId(MAC, VLAN))) {
1149 return HOST;
1150 } else if (hostId.equals(HostId.hostId(MAC2, VLAN))) {
1151 return HOST2;
1152 } else if (hostId.equals(HostId.hostId(MAC3, VLAN))) {
1153 return HOST3;
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001154 } else if (hostId.equals(HostId.hostId(MAC, VLAN_100))) {
1155 return HOST_VLAN_100;
Charles Chane6067892016-11-17 10:23:46 -08001156 }
1157 return null;
1158 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001159 }
Charles Chane6067892016-11-17 10:23:46 -08001160
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001161 private class TestInterfaceService implements InterfaceService {
1162 @Override
1163 public Set<Interface> getInterfaces() {
1164 return null;
1165 }
1166
1167 @Override
1168 public Interface getInterfaceByName(ConnectPoint connectPoint, String name) {
1169 return null;
1170 }
1171
1172 @Override
1173 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
1174 return null;
1175 }
1176
1177 public Set<Interface> getInterfacesByIp(IpAddress ip) {
1178 if (ip.equals(GW_IFACE_ADDR.ipAddress())) {
1179 return ImmutableSet.of(GW_IFACE);
1180 } else {
1181 return ImmutableSet.of();
1182 }
1183 }
1184
1185 @Override
1186 public Set<Interface> getInterfacesByVlan(VlanId vlan) {
1187 return null;
1188 }
1189
1190 @Override
1191 public Interface getMatchingInterface(IpAddress ip) {
1192 return null;
1193 }
1194
1195 @Override
1196 public Set<Interface> getMatchingInterfaces(IpAddress ip) {
1197 return null;
1198 }
1199
1200 @Override
1201 public void addListener(InterfaceListener listener) {
1202
1203 }
1204
1205 @Override
1206 public void removeListener(InterfaceListener listener) {
1207
1208 }
Thomas Vachuska33601602014-11-19 03:32:15 -08001209 }
alshabib4a179dc2014-10-17 17:17:01 -07001210}