blob: c048b8ab19320a81db75ee7e07994275fa941b21 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 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
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080018import static org.easymock.EasyMock.createMock;
19import static org.easymock.EasyMock.expect;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080020import static org.easymock.EasyMock.replay;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080021import static org.junit.Assert.assertEquals;
22import static org.junit.Assert.assertNotNull;
23import static org.junit.Assert.assertNull;
24import static org.onlab.packet.VlanId.vlanId;
25import static org.onosproject.net.Device.Type.SWITCH;
26import static org.onosproject.net.DeviceId.deviceId;
27import static org.onosproject.net.HostId.hostId;
28import static org.onosproject.net.PortNumber.portNumber;
29import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
30import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
31import static org.onosproject.net.device.DeviceEvent.Type.PORT_UPDATED;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080032
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080033import java.nio.ByteBuffer;
34import java.util.Collections;
35import java.util.Dictionary;
36import java.util.Hashtable;
37import java.util.Set;
38
alshabib4a179dc2014-10-17 17:17:01 -070039import org.junit.After;
40import org.junit.Before;
41import org.junit.Test;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080042import org.onlab.osgi.ComponentContextAdapter;
43import org.onlab.packet.ARP;
44import org.onlab.packet.ChassisId;
45import org.onlab.packet.Ethernet;
46import org.onlab.packet.IpAddress;
47import org.onlab.packet.MacAddress;
48import org.onlab.packet.VlanId;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080049import org.onosproject.core.ApplicationId;
50import org.onosproject.core.CoreService;
51import org.onosproject.core.DefaultApplicationId;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.net.ConnectPoint;
53import org.onosproject.net.DefaultDevice;
54import org.onosproject.net.DefaultHost;
55import org.onosproject.net.DefaultPort;
56import org.onosproject.net.Device;
57import org.onosproject.net.DeviceId;
58import org.onosproject.net.Host;
59import org.onosproject.net.HostId;
60import org.onosproject.net.HostLocation;
61import org.onosproject.net.device.DeviceEvent;
62import org.onosproject.net.device.DeviceListener;
63import org.onosproject.net.device.DeviceServiceAdapter;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080064import org.onosproject.net.flow.TrafficSelector;
Brian O'Connorabafb502014-12-02 22:26:20 -080065import org.onosproject.net.flow.TrafficTreatment;
66import org.onosproject.net.host.HostDescription;
67import org.onosproject.net.host.HostProvider;
68import org.onosproject.net.host.HostProviderRegistry;
69import org.onosproject.net.host.HostProviderService;
70import org.onosproject.net.host.HostServiceAdapter;
71import org.onosproject.net.packet.DefaultInboundPacket;
72import org.onosproject.net.packet.InboundPacket;
73import org.onosproject.net.packet.OutboundPacket;
74import org.onosproject.net.packet.PacketContext;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080075import org.onosproject.net.packet.PacketPriority;
Brian O'Connorabafb502014-12-02 22:26:20 -080076import org.onosproject.net.packet.PacketProcessor;
77import org.onosproject.net.packet.PacketService;
78import org.onosproject.net.provider.AbstractProviderService;
79import org.onosproject.net.provider.ProviderId;
80import org.onosproject.net.topology.Topology;
81import org.onosproject.net.topology.TopologyServiceAdapter;
alshabib4a179dc2014-10-17 17:17:01 -070082
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080083import com.google.common.collect.ImmutableSet;
Thomas Vachuska33601602014-11-19 03:32:15 -080084
alshabib4a179dc2014-10-17 17:17:01 -070085public class HostLocationProviderTest {
86
87 private static final Integer INPORT = 10;
88 private static final String DEV1 = "of:1";
89 private static final String DEV2 = "of:2";
90 private static final String DEV3 = "of:3";
91
Thomas Vachuska33601602014-11-19 03:32:15 -080092 private static final VlanId VLAN = vlanId();
alshabib4a179dc2014-10-17 17:17:01 -070093 private static final MacAddress MAC = MacAddress.valueOf("00:00:11:00:00:01");
94 private static final MacAddress BCMAC = MacAddress.valueOf("ff:ff:ff:ff:ff:ff");
95 private static final byte[] IP = new byte[]{10, 0, 0, 1};
96
Thomas Vachuska33601602014-11-19 03:32:15 -080097 private static final IpAddress IP_ADDRESS =
98 IpAddress.valueOf(IpAddress.Version.INET, IP);
99 private static final HostLocation LOCATION =
100 new HostLocation(deviceId(DEV1), portNumber(INPORT), 0L);
101
102 private static final DefaultHost HOST =
103 new DefaultHost(ProviderId.NONE, hostId(MAC), MAC,
104 vlanId(VlanId.UNTAGGED), LOCATION,
105 ImmutableSet.of(IP_ADDRESS));
106
107 private static final ComponentContextAdapter CTX_FOR_REMOVE =
108 new ComponentContextAdapter() {
109 @Override
110 public Dictionary getProperties() {
111 Hashtable<String, String> props = new Hashtable<>();
112 props.put("hostRemovalEnabled", "true");
113 return props;
114 }
115 };
116
117 public static final ComponentContextAdapter CTX_FOR_NO_REMOVE =
118 new ComponentContextAdapter() {
119 @Override
120 public Dictionary getProperties() {
121 return new Hashtable();
122 }
123 };
124
alshabib4a179dc2014-10-17 17:17:01 -0700125 private final HostLocationProvider provider = new HostLocationProvider();
Thomas Vachuska33601602014-11-19 03:32:15 -0800126 private final TestHostRegistry hostRegistry = new TestHostRegistry();
alshabib4a179dc2014-10-17 17:17:01 -0700127 private final TestTopologyService topoService = new TestTopologyService();
Thomas Vachuska33601602014-11-19 03:32:15 -0800128 private final TestDeviceService deviceService = new TestDeviceService();
129 private final TestHostService hostService = new TestHostService();
alshabib4a179dc2014-10-17 17:17:01 -0700130 private final TestPacketService packetService = new TestPacketService();
131
132 private PacketProcessor testProcessor;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800133 private CoreService coreService;
alshabib4a179dc2014-10-17 17:17:01 -0700134 private TestHostProviderService providerService;
135
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800136 private ApplicationId appId =
137 new DefaultApplicationId(100, "org.onosproject.provider.host");
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800138
alshabib4a179dc2014-10-17 17:17:01 -0700139 @Before
140 public void setUp() {
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800141
142 coreService = createMock(CoreService.class);
143 expect(coreService.registerApplication(appId.name()))
144 .andReturn(appId).anyTimes();
145 replay(coreService);
146
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800147 provider.coreService = coreService;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800148
Thomas Vachuska33601602014-11-19 03:32:15 -0800149 provider.providerRegistry = hostRegistry;
alshabib4a179dc2014-10-17 17:17:01 -0700150 provider.topologyService = topoService;
151 provider.pktService = packetService;
Thomas Vachuska33601602014-11-19 03:32:15 -0800152 provider.deviceService = deviceService;
153 provider.hostService = hostService;
alshabib4a179dc2014-10-17 17:17:01 -0700154
Thomas Vachuska33601602014-11-19 03:32:15 -0800155 provider.activate(CTX_FOR_NO_REMOVE);
alshabib4a179dc2014-10-17 17:17:01 -0700156 }
157
158 @Test
159 public void basics() {
160 assertNotNull("registration expected", providerService);
161 assertEquals("incorrect provider", provider, providerService.provider());
162 }
163
164 @Test
165 public void events() {
166 // new host
alshabib4a179dc2014-10-17 17:17:01 -0700167 testProcessor.process(new TestPacketContext(DEV1));
168 assertNotNull("new host expected", providerService.added);
169 assertNull("host motion unexpected", providerService.moved);
170
171 // the host moved to new switch
172 testProcessor.process(new TestPacketContext(DEV2));
173 assertNotNull("host motion expected", providerService.moved);
174
175 // the host was misheard on a spine
176 testProcessor.process(new TestPacketContext(DEV3));
177 assertNull("host misheard on spine switch", providerService.spine);
178 }
179
Thomas Vachuska33601602014-11-19 03:32:15 -0800180 @Test
181 public void removeHostByDeviceRemove() {
182 provider.modified(CTX_FOR_REMOVE);
183 testProcessor.process(new TestPacketContext(DEV1));
184 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
185 "m", "h", "s", "n", new ChassisId(0L));
186 deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
187 assertEquals("incorrect remove count", 1, providerService.removeCount);
188 }
189
190 @Test
191 public void removeHostByDeviceOffline() {
192 provider.modified(CTX_FOR_REMOVE);
193 testProcessor.process(new TestPacketContext(DEV1));
194 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
195 "m", "h", "s", "n", new ChassisId(0L));
196 deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
197 assertEquals("incorrect remove count", 1, providerService.removeCount);
198 }
199
200 @Test
201 public void removeHostByDevicePortDown() {
202 provider.modified(CTX_FOR_REMOVE);
203 testProcessor.process(new TestPacketContext(DEV1));
204 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
205 "m", "h", "s", "n", new ChassisId(0L));
206 deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
207 new DefaultPort(device, portNumber(INPORT),
208 false)));
209 assertEquals("incorrect remove count", 1, providerService.removeCount);
210 }
211
212
alshabib4a179dc2014-10-17 17:17:01 -0700213 @After
214 public void tearDown() {
215 provider.deactivate();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800216 provider.coreService = null;
alshabib4a179dc2014-10-17 17:17:01 -0700217 provider.providerRegistry = null;
alshabib4a179dc2014-10-17 17:17:01 -0700218 }
219
220 private class TestHostRegistry implements HostProviderRegistry {
221
222 @Override
223 public HostProviderService register(HostProvider provider) {
224 providerService = new TestHostProviderService(provider);
225 return providerService;
226 }
227
228 @Override
229 public void unregister(HostProvider provider) {
230 }
231
232 @Override
233 public Set<ProviderId> getProviders() {
234 return null;
235 }
236
237 }
238
239 private class TestHostProviderService
240 extends AbstractProviderService<HostProvider>
241 implements HostProviderService {
242
243 DeviceId added = null;
244 DeviceId moved = null;
245 DeviceId spine = null;
Thomas Vachuska33601602014-11-19 03:32:15 -0800246 public int removeCount;
alshabib4a179dc2014-10-17 17:17:01 -0700247
248 protected TestHostProviderService(HostProvider provider) {
249 super(provider);
250 }
251
252 @Override
253 public void hostDetected(HostId hostId, HostDescription hostDescription) {
254 DeviceId descr = hostDescription.location().deviceId();
255 if (added == null) {
256 added = descr;
257 } else if ((moved == null) && !descr.equals(added)) {
258 moved = descr;
259 } else {
260 spine = descr;
261 }
262 }
263
264 @Override
265 public void hostVanished(HostId hostId) {
Thomas Vachuska33601602014-11-19 03:32:15 -0800266 removeCount++;
alshabib4a179dc2014-10-17 17:17:01 -0700267 }
268
269 }
270
271 private class TestPacketService implements PacketService {
272
273 @Override
274 public void addProcessor(PacketProcessor processor, int priority) {
275 testProcessor = processor;
276 }
277
278 @Override
279 public void removeProcessor(PacketProcessor processor) {
alshabib4a179dc2014-10-17 17:17:01 -0700280 }
281
282 @Override
283 public void emit(OutboundPacket packet) {
alshabib4a179dc2014-10-17 17:17:01 -0700284 }
Jonathan Hart3cfce8e2015-01-14 16:43:27 -0800285
286 @Override
287 public void requestPackets(TrafficSelector selector,
288 PacketPriority priority, ApplicationId appId) {
289 }
alshabib4a179dc2014-10-17 17:17:01 -0700290 }
291
292
293 private class TestTopologyService extends TopologyServiceAdapter {
294 @Override
295 public boolean isInfrastructure(Topology topology,
296 ConnectPoint connectPoint) {
297 //simulate DPID3 as an infrastructure switch
Thomas Vachuska33601602014-11-19 03:32:15 -0800298 if ((connectPoint.deviceId()).equals(deviceId(DEV3))) {
alshabib4a179dc2014-10-17 17:17:01 -0700299 return true;
300 }
301 return false;
302 }
303 }
304
305 private class TestPacketContext implements PacketContext {
306
307 private final String deviceId;
308
309 public TestPacketContext(String deviceId) {
310 this.deviceId = deviceId;
311 }
312
313 @Override
314 public long time() {
315 return 0;
316 }
317
318 @Override
319 public InboundPacket inPacket() {
320 ARP arp = new ARP();
321 arp.setSenderProtocolAddress(IP)
322 .setSenderHardwareAddress(MAC.toBytes())
323 .setTargetHardwareAddress(BCMAC.toBytes())
324 .setTargetProtocolAddress(IP);
325
326 Ethernet eth = new Ethernet();
327 eth.setEtherType(Ethernet.TYPE_ARP)
328 .setVlanID(VLAN.toShort())
329 .setSourceMACAddress(MAC.toBytes())
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800330 .setDestinationMACAddress(BCMAC)
alshabib4a179dc2014-10-17 17:17:01 -0700331 .setPayload(arp);
Thomas Vachuska33601602014-11-19 03:32:15 -0800332 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
333 portNumber(INPORT));
alshabib4a179dc2014-10-17 17:17:01 -0700334 return new DefaultInboundPacket(receivedFrom, eth,
335 ByteBuffer.wrap(eth.serialize()));
336 }
337
338 @Override
339 public OutboundPacket outPacket() {
340 return null;
341 }
342
343 @Override
344 public TrafficTreatment.Builder treatmentBuilder() {
345 return null;
346 }
347
348 @Override
349 public void send() {
350
351 }
352
353 @Override
354 public boolean block() {
355 return false;
356 }
357
358 @Override
359 public boolean isHandled() {
360 return false;
361 }
362 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800363
364 private class TestDeviceService extends DeviceServiceAdapter {
365 private DeviceListener listener;
366
367 @Override
368 public void addListener(DeviceListener listener) {
369 this.listener = listener;
370 }
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800371
372 @Override
373 public Iterable<Device> getDevices() {
374 return Collections.emptyList();
375 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800376 }
377
378 private class TestHostService extends HostServiceAdapter {
379 @Override
380 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
381 return ImmutableSet.of(HOST);
382 }
383
384 @Override
385 public Set<Host> getConnectedHosts(DeviceId deviceId) {
386 return ImmutableSet.of(HOST);
387 }
388
389 }
alshabib4a179dc2014-10-17 17:17:01 -0700390}