blob: 4db62b4bb20297cdc32d08db3f2c79baa3f45965 [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.anyObject;
19import static org.easymock.EasyMock.createMock;
20import static org.easymock.EasyMock.expect;
21import static org.easymock.EasyMock.expectLastCall;
22import static org.easymock.EasyMock.replay;
23
Thomas Vachuska33601602014-11-19 03:32:15 -080024import com.google.common.collect.ImmutableSet;
alshabib4a179dc2014-10-17 17:17:01 -070025import org.junit.After;
26import org.junit.Before;
27import org.junit.Test;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080028import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
30import org.onosproject.core.DefaultApplicationId;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.ConnectPoint;
32import org.onosproject.net.DefaultDevice;
33import org.onosproject.net.DefaultHost;
34import org.onosproject.net.DefaultPort;
35import org.onosproject.net.Device;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.Host;
38import org.onosproject.net.HostId;
39import org.onosproject.net.HostLocation;
40import org.onosproject.net.device.DeviceEvent;
41import org.onosproject.net.device.DeviceListener;
42import org.onosproject.net.device.DeviceServiceAdapter;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080043import org.onosproject.net.flow.FlowRule;
44import org.onosproject.net.flow.FlowRuleService;
Brian O'Connorabafb502014-12-02 22:26:20 -080045import org.onosproject.net.flow.TrafficTreatment;
46import org.onosproject.net.host.HostDescription;
47import org.onosproject.net.host.HostProvider;
48import org.onosproject.net.host.HostProviderRegistry;
49import org.onosproject.net.host.HostProviderService;
50import org.onosproject.net.host.HostServiceAdapter;
51import org.onosproject.net.packet.DefaultInboundPacket;
52import org.onosproject.net.packet.InboundPacket;
53import org.onosproject.net.packet.OutboundPacket;
54import org.onosproject.net.packet.PacketContext;
55import org.onosproject.net.packet.PacketProcessor;
56import org.onosproject.net.packet.PacketService;
57import org.onosproject.net.provider.AbstractProviderService;
58import org.onosproject.net.provider.ProviderId;
59import org.onosproject.net.topology.Topology;
60import org.onosproject.net.topology.TopologyServiceAdapter;
Thomas Vachuska33601602014-11-19 03:32:15 -080061import org.onlab.osgi.ComponentContextAdapter;
alshabib4a179dc2014-10-17 17:17:01 -070062import org.onlab.packet.ARP;
Thomas Vachuska33601602014-11-19 03:32:15 -080063import org.onlab.packet.ChassisId;
alshabib4a179dc2014-10-17 17:17:01 -070064import org.onlab.packet.Ethernet;
Thomas Vachuska33601602014-11-19 03:32:15 -080065import org.onlab.packet.IpAddress;
alshabib4a179dc2014-10-17 17:17:01 -070066import org.onlab.packet.MacAddress;
67import org.onlab.packet.VlanId;
68
Thomas Vachuska33601602014-11-19 03:32:15 -080069import java.nio.ByteBuffer;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080070import java.util.Collections;
Thomas Vachuska33601602014-11-19 03:32:15 -080071import java.util.Dictionary;
72import java.util.Hashtable;
73import java.util.Set;
74
75import static org.junit.Assert.*;
Brian O'Connorabafb502014-12-02 22:26:20 -080076import static org.onosproject.net.Device.Type.SWITCH;
77import static org.onosproject.net.DeviceId.deviceId;
78import static org.onosproject.net.HostId.hostId;
79import static org.onosproject.net.PortNumber.portNumber;
80import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
81import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
82import static org.onosproject.net.device.DeviceEvent.Type.PORT_UPDATED;
Thomas Vachuska33601602014-11-19 03:32:15 -080083import static org.onlab.packet.VlanId.vlanId;
84
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;
134 private FlowRuleService flowRuleService;
alshabib4a179dc2014-10-17 17:17:01 -0700135 private TestHostProviderService providerService;
136
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800137 private ApplicationId appId = new DefaultApplicationId((short) 100,
138 "org.onosproject.provider.host");
139
alshabib4a179dc2014-10-17 17:17:01 -0700140 @Before
141 public void setUp() {
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800142
143 coreService = createMock(CoreService.class);
144 expect(coreService.registerApplication(appId.name()))
145 .andReturn(appId).anyTimes();
146 replay(coreService);
147
148 flowRuleService = createMock(FlowRuleService.class);
149 flowRuleService.applyFlowRules(anyObject(FlowRule.class));
150 expectLastCall().anyTimes();
151 replay(flowRuleService);
152
153 provider.coreService = coreService;
154 provider.flowRuleService = flowRuleService;
155
Thomas Vachuska33601602014-11-19 03:32:15 -0800156 provider.providerRegistry = hostRegistry;
alshabib4a179dc2014-10-17 17:17:01 -0700157 provider.topologyService = topoService;
158 provider.pktService = packetService;
Thomas Vachuska33601602014-11-19 03:32:15 -0800159 provider.deviceService = deviceService;
160 provider.hostService = hostService;
alshabib4a179dc2014-10-17 17:17:01 -0700161
Thomas Vachuska33601602014-11-19 03:32:15 -0800162 provider.activate(CTX_FOR_NO_REMOVE);
alshabib4a179dc2014-10-17 17:17:01 -0700163 }
164
165 @Test
166 public void basics() {
167 assertNotNull("registration expected", providerService);
168 assertEquals("incorrect provider", provider, providerService.provider());
169 }
170
171 @Test
172 public void events() {
173 // new host
alshabib4a179dc2014-10-17 17:17:01 -0700174 testProcessor.process(new TestPacketContext(DEV1));
175 assertNotNull("new host expected", providerService.added);
176 assertNull("host motion unexpected", providerService.moved);
177
178 // the host moved to new switch
179 testProcessor.process(new TestPacketContext(DEV2));
180 assertNotNull("host motion expected", providerService.moved);
181
182 // the host was misheard on a spine
183 testProcessor.process(new TestPacketContext(DEV3));
184 assertNull("host misheard on spine switch", providerService.spine);
185 }
186
Thomas Vachuska33601602014-11-19 03:32:15 -0800187 @Test
188 public void removeHostByDeviceRemove() {
189 provider.modified(CTX_FOR_REMOVE);
190 testProcessor.process(new TestPacketContext(DEV1));
191 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
192 "m", "h", "s", "n", new ChassisId(0L));
193 deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
194 assertEquals("incorrect remove count", 1, providerService.removeCount);
195 }
196
197 @Test
198 public void removeHostByDeviceOffline() {
199 provider.modified(CTX_FOR_REMOVE);
200 testProcessor.process(new TestPacketContext(DEV1));
201 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
202 "m", "h", "s", "n", new ChassisId(0L));
203 deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
204 assertEquals("incorrect remove count", 1, providerService.removeCount);
205 }
206
207 @Test
208 public void removeHostByDevicePortDown() {
209 provider.modified(CTX_FOR_REMOVE);
210 testProcessor.process(new TestPacketContext(DEV1));
211 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
212 "m", "h", "s", "n", new ChassisId(0L));
213 deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
214 new DefaultPort(device, portNumber(INPORT),
215 false)));
216 assertEquals("incorrect remove count", 1, providerService.removeCount);
217 }
218
219
alshabib4a179dc2014-10-17 17:17:01 -0700220 @After
221 public void tearDown() {
222 provider.deactivate();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800223 provider.coreService = null;
224 provider.flowRuleService = null;
alshabib4a179dc2014-10-17 17:17:01 -0700225 provider.providerRegistry = null;
alshabib4a179dc2014-10-17 17:17:01 -0700226 }
227
228 private class TestHostRegistry implements HostProviderRegistry {
229
230 @Override
231 public HostProviderService register(HostProvider provider) {
232 providerService = new TestHostProviderService(provider);
233 return providerService;
234 }
235
236 @Override
237 public void unregister(HostProvider provider) {
238 }
239
240 @Override
241 public Set<ProviderId> getProviders() {
242 return null;
243 }
244
245 }
246
247 private class TestHostProviderService
248 extends AbstractProviderService<HostProvider>
249 implements HostProviderService {
250
251 DeviceId added = null;
252 DeviceId moved = null;
253 DeviceId spine = null;
Thomas Vachuska33601602014-11-19 03:32:15 -0800254 public int removeCount;
alshabib4a179dc2014-10-17 17:17:01 -0700255
256 protected TestHostProviderService(HostProvider provider) {
257 super(provider);
258 }
259
260 @Override
261 public void hostDetected(HostId hostId, HostDescription hostDescription) {
262 DeviceId descr = hostDescription.location().deviceId();
263 if (added == null) {
264 added = descr;
265 } else if ((moved == null) && !descr.equals(added)) {
266 moved = descr;
267 } else {
268 spine = descr;
269 }
270 }
271
272 @Override
273 public void hostVanished(HostId hostId) {
Thomas Vachuska33601602014-11-19 03:32:15 -0800274 removeCount++;
alshabib4a179dc2014-10-17 17:17:01 -0700275 }
276
277 }
278
279 private class TestPacketService implements PacketService {
280
281 @Override
282 public void addProcessor(PacketProcessor processor, int priority) {
283 testProcessor = processor;
284 }
285
286 @Override
287 public void removeProcessor(PacketProcessor processor) {
alshabib4a179dc2014-10-17 17:17:01 -0700288 }
289
290 @Override
291 public void emit(OutboundPacket packet) {
alshabib4a179dc2014-10-17 17:17:01 -0700292 }
293 }
294
295
296 private class TestTopologyService extends TopologyServiceAdapter {
297 @Override
298 public boolean isInfrastructure(Topology topology,
299 ConnectPoint connectPoint) {
300 //simulate DPID3 as an infrastructure switch
Thomas Vachuska33601602014-11-19 03:32:15 -0800301 if ((connectPoint.deviceId()).equals(deviceId(DEV3))) {
alshabib4a179dc2014-10-17 17:17:01 -0700302 return true;
303 }
304 return false;
305 }
306 }
307
308 private class TestPacketContext implements PacketContext {
309
310 private final String deviceId;
311
312 public TestPacketContext(String deviceId) {
313 this.deviceId = deviceId;
314 }
315
316 @Override
317 public long time() {
318 return 0;
319 }
320
321 @Override
322 public InboundPacket inPacket() {
323 ARP arp = new ARP();
324 arp.setSenderProtocolAddress(IP)
325 .setSenderHardwareAddress(MAC.toBytes())
326 .setTargetHardwareAddress(BCMAC.toBytes())
327 .setTargetProtocolAddress(IP);
328
329 Ethernet eth = new Ethernet();
330 eth.setEtherType(Ethernet.TYPE_ARP)
331 .setVlanID(VLAN.toShort())
332 .setSourceMACAddress(MAC.toBytes())
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800333 .setDestinationMACAddress(BCMAC)
alshabib4a179dc2014-10-17 17:17:01 -0700334 .setPayload(arp);
Thomas Vachuska33601602014-11-19 03:32:15 -0800335 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
336 portNumber(INPORT));
alshabib4a179dc2014-10-17 17:17:01 -0700337 return new DefaultInboundPacket(receivedFrom, eth,
338 ByteBuffer.wrap(eth.serialize()));
339 }
340
341 @Override
342 public OutboundPacket outPacket() {
343 return null;
344 }
345
346 @Override
347 public TrafficTreatment.Builder treatmentBuilder() {
348 return null;
349 }
350
351 @Override
352 public void send() {
353
354 }
355
356 @Override
357 public boolean block() {
358 return false;
359 }
360
361 @Override
362 public boolean isHandled() {
363 return false;
364 }
365 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800366
367 private class TestDeviceService extends DeviceServiceAdapter {
368 private DeviceListener listener;
369
370 @Override
371 public void addListener(DeviceListener listener) {
372 this.listener = listener;
373 }
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800374
375 @Override
376 public Iterable<Device> getDevices() {
377 return Collections.emptyList();
378 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800379 }
380
381 private class TestHostService extends HostServiceAdapter {
382 @Override
383 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
384 return ImmutableSet.of(HOST);
385 }
386
387 @Override
388 public Set<Host> getConnectedHosts(DeviceId deviceId) {
389 return ImmutableSet.of(HOST);
390 }
391
392 }
alshabib4a179dc2014-10-17 17:17:01 -0700393}