blob: 00c467a8363a009923600c9fcb29f57f6e0511c1 [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 */
alshabib4a179dc2014-10-17 17:17:01 -070016package org.onlab.onos.provider.host.impl;
17
Thomas Vachuska33601602014-11-19 03:32:15 -080018import com.google.common.collect.ImmutableSet;
alshabib4a179dc2014-10-17 17:17:01 -070019import org.junit.After;
20import org.junit.Before;
21import org.junit.Test;
22import org.onlab.onos.net.ConnectPoint;
Thomas Vachuska33601602014-11-19 03:32:15 -080023import org.onlab.onos.net.DefaultDevice;
24import org.onlab.onos.net.DefaultHost;
25import org.onlab.onos.net.DefaultPort;
26import org.onlab.onos.net.Device;
alshabib4a179dc2014-10-17 17:17:01 -070027import org.onlab.onos.net.DeviceId;
Thomas Vachuska33601602014-11-19 03:32:15 -080028import org.onlab.onos.net.Host;
alshabib4a179dc2014-10-17 17:17:01 -070029import org.onlab.onos.net.HostId;
Thomas Vachuska33601602014-11-19 03:32:15 -080030import org.onlab.onos.net.HostLocation;
31import org.onlab.onos.net.device.DeviceEvent;
32import org.onlab.onos.net.device.DeviceListener;
33import org.onlab.onos.net.device.DeviceServiceAdapter;
alshabib4a179dc2014-10-17 17:17:01 -070034import org.onlab.onos.net.flow.TrafficTreatment;
35import org.onlab.onos.net.host.HostDescription;
36import org.onlab.onos.net.host.HostProvider;
37import org.onlab.onos.net.host.HostProviderRegistry;
38import org.onlab.onos.net.host.HostProviderService;
Thomas Vachuska33601602014-11-19 03:32:15 -080039import org.onlab.onos.net.host.HostServiceAdapter;
alshabib4a179dc2014-10-17 17:17:01 -070040import org.onlab.onos.net.packet.DefaultInboundPacket;
41import org.onlab.onos.net.packet.InboundPacket;
42import org.onlab.onos.net.packet.OutboundPacket;
43import org.onlab.onos.net.packet.PacketContext;
44import org.onlab.onos.net.packet.PacketProcessor;
45import org.onlab.onos.net.packet.PacketService;
46import org.onlab.onos.net.provider.AbstractProviderService;
47import org.onlab.onos.net.provider.ProviderId;
48import org.onlab.onos.net.topology.Topology;
alshabib4a179dc2014-10-17 17:17:01 -070049import org.onlab.onos.net.topology.TopologyServiceAdapter;
Thomas Vachuska33601602014-11-19 03:32:15 -080050import org.onlab.osgi.ComponentContextAdapter;
alshabib4a179dc2014-10-17 17:17:01 -070051import org.onlab.packet.ARP;
Thomas Vachuska33601602014-11-19 03:32:15 -080052import org.onlab.packet.ChassisId;
alshabib4a179dc2014-10-17 17:17:01 -070053import org.onlab.packet.Ethernet;
Thomas Vachuska33601602014-11-19 03:32:15 -080054import org.onlab.packet.IpAddress;
alshabib4a179dc2014-10-17 17:17:01 -070055import org.onlab.packet.MacAddress;
56import org.onlab.packet.VlanId;
57
Thomas Vachuska33601602014-11-19 03:32:15 -080058import java.nio.ByteBuffer;
59import java.util.Dictionary;
60import java.util.Hashtable;
61import java.util.Set;
62
63import static org.junit.Assert.*;
64import static org.onlab.onos.net.Device.Type.SWITCH;
65import static org.onlab.onos.net.DeviceId.deviceId;
66import static org.onlab.onos.net.HostId.hostId;
67import static org.onlab.onos.net.PortNumber.portNumber;
68import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
69import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_REMOVED;
70import static org.onlab.onos.net.device.DeviceEvent.Type.PORT_UPDATED;
71import static org.onlab.packet.VlanId.vlanId;
72
alshabib4a179dc2014-10-17 17:17:01 -070073public class HostLocationProviderTest {
74
75 private static final Integer INPORT = 10;
76 private static final String DEV1 = "of:1";
77 private static final String DEV2 = "of:2";
78 private static final String DEV3 = "of:3";
79
Thomas Vachuska33601602014-11-19 03:32:15 -080080 private static final VlanId VLAN = vlanId();
alshabib4a179dc2014-10-17 17:17:01 -070081 private static final MacAddress MAC = MacAddress.valueOf("00:00:11:00:00:01");
82 private static final MacAddress BCMAC = MacAddress.valueOf("ff:ff:ff:ff:ff:ff");
83 private static final byte[] IP = new byte[]{10, 0, 0, 1};
84
Thomas Vachuska33601602014-11-19 03:32:15 -080085 private static final IpAddress IP_ADDRESS =
86 IpAddress.valueOf(IpAddress.Version.INET, IP);
87 private static final HostLocation LOCATION =
88 new HostLocation(deviceId(DEV1), portNumber(INPORT), 0L);
89
90 private static final DefaultHost HOST =
91 new DefaultHost(ProviderId.NONE, hostId(MAC), MAC,
92 vlanId(VlanId.UNTAGGED), LOCATION,
93 ImmutableSet.of(IP_ADDRESS));
94
95 private static final ComponentContextAdapter CTX_FOR_REMOVE =
96 new ComponentContextAdapter() {
97 @Override
98 public Dictionary getProperties() {
99 Hashtable<String, String> props = new Hashtable<>();
100 props.put("hostRemovalEnabled", "true");
101 return props;
102 }
103 };
104
105 public static final ComponentContextAdapter CTX_FOR_NO_REMOVE =
106 new ComponentContextAdapter() {
107 @Override
108 public Dictionary getProperties() {
109 return new Hashtable();
110 }
111 };
112
alshabib4a179dc2014-10-17 17:17:01 -0700113 private final HostLocationProvider provider = new HostLocationProvider();
Thomas Vachuska33601602014-11-19 03:32:15 -0800114 private final TestHostRegistry hostRegistry = new TestHostRegistry();
alshabib4a179dc2014-10-17 17:17:01 -0700115 private final TestTopologyService topoService = new TestTopologyService();
Thomas Vachuska33601602014-11-19 03:32:15 -0800116 private final TestDeviceService deviceService = new TestDeviceService();
117 private final TestHostService hostService = new TestHostService();
alshabib4a179dc2014-10-17 17:17:01 -0700118 private final TestPacketService packetService = new TestPacketService();
119
120 private PacketProcessor testProcessor;
121 private TestHostProviderService providerService;
122
123 @Before
124 public void setUp() {
Thomas Vachuska33601602014-11-19 03:32:15 -0800125 provider.providerRegistry = hostRegistry;
alshabib4a179dc2014-10-17 17:17:01 -0700126 provider.topologyService = topoService;
127 provider.pktService = packetService;
Thomas Vachuska33601602014-11-19 03:32:15 -0800128 provider.deviceService = deviceService;
129 provider.hostService = hostService;
alshabib4a179dc2014-10-17 17:17:01 -0700130
Thomas Vachuska33601602014-11-19 03:32:15 -0800131 provider.activate(CTX_FOR_NO_REMOVE);
alshabib4a179dc2014-10-17 17:17:01 -0700132 }
133
134 @Test
135 public void basics() {
136 assertNotNull("registration expected", providerService);
137 assertEquals("incorrect provider", provider, providerService.provider());
138 }
139
140 @Test
141 public void events() {
142 // new host
alshabib4a179dc2014-10-17 17:17:01 -0700143 testProcessor.process(new TestPacketContext(DEV1));
144 assertNotNull("new host expected", providerService.added);
145 assertNull("host motion unexpected", providerService.moved);
146
147 // the host moved to new switch
148 testProcessor.process(new TestPacketContext(DEV2));
149 assertNotNull("host motion expected", providerService.moved);
150
151 // the host was misheard on a spine
152 testProcessor.process(new TestPacketContext(DEV3));
153 assertNull("host misheard on spine switch", providerService.spine);
154 }
155
Thomas Vachuska33601602014-11-19 03:32:15 -0800156 @Test
157 public void removeHostByDeviceRemove() {
158 provider.modified(CTX_FOR_REMOVE);
159 testProcessor.process(new TestPacketContext(DEV1));
160 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
161 "m", "h", "s", "n", new ChassisId(0L));
162 deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
163 assertEquals("incorrect remove count", 1, providerService.removeCount);
164 }
165
166 @Test
167 public void removeHostByDeviceOffline() {
168 provider.modified(CTX_FOR_REMOVE);
169 testProcessor.process(new TestPacketContext(DEV1));
170 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
171 "m", "h", "s", "n", new ChassisId(0L));
172 deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
173 assertEquals("incorrect remove count", 1, providerService.removeCount);
174 }
175
176 @Test
177 public void removeHostByDevicePortDown() {
178 provider.modified(CTX_FOR_REMOVE);
179 testProcessor.process(new TestPacketContext(DEV1));
180 Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
181 "m", "h", "s", "n", new ChassisId(0L));
182 deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
183 new DefaultPort(device, portNumber(INPORT),
184 false)));
185 assertEquals("incorrect remove count", 1, providerService.removeCount);
186 }
187
188
alshabib4a179dc2014-10-17 17:17:01 -0700189 @After
190 public void tearDown() {
191 provider.deactivate();
192 provider.providerRegistry = null;
193
194 }
195
196 private class TestHostRegistry implements HostProviderRegistry {
197
198 @Override
199 public HostProviderService register(HostProvider provider) {
200 providerService = new TestHostProviderService(provider);
201 return providerService;
202 }
203
204 @Override
205 public void unregister(HostProvider provider) {
206 }
207
208 @Override
209 public Set<ProviderId> getProviders() {
210 return null;
211 }
212
213 }
214
215 private class TestHostProviderService
216 extends AbstractProviderService<HostProvider>
217 implements HostProviderService {
218
219 DeviceId added = null;
220 DeviceId moved = null;
221 DeviceId spine = null;
Thomas Vachuska33601602014-11-19 03:32:15 -0800222 public int removeCount;
alshabib4a179dc2014-10-17 17:17:01 -0700223
224 protected TestHostProviderService(HostProvider provider) {
225 super(provider);
226 }
227
228 @Override
229 public void hostDetected(HostId hostId, HostDescription hostDescription) {
230 DeviceId descr = hostDescription.location().deviceId();
231 if (added == null) {
232 added = descr;
233 } else if ((moved == null) && !descr.equals(added)) {
234 moved = descr;
235 } else {
236 spine = descr;
237 }
238 }
239
240 @Override
241 public void hostVanished(HostId hostId) {
Thomas Vachuska33601602014-11-19 03:32:15 -0800242 removeCount++;
alshabib4a179dc2014-10-17 17:17:01 -0700243 }
244
245 }
246
247 private class TestPacketService implements PacketService {
248
249 @Override
250 public void addProcessor(PacketProcessor processor, int priority) {
251 testProcessor = processor;
252 }
253
254 @Override
255 public void removeProcessor(PacketProcessor processor) {
alshabib4a179dc2014-10-17 17:17:01 -0700256 }
257
258 @Override
259 public void emit(OutboundPacket packet) {
alshabib4a179dc2014-10-17 17:17:01 -0700260 }
261 }
262
263
264 private class TestTopologyService extends TopologyServiceAdapter {
265 @Override
266 public boolean isInfrastructure(Topology topology,
267 ConnectPoint connectPoint) {
268 //simulate DPID3 as an infrastructure switch
Thomas Vachuska33601602014-11-19 03:32:15 -0800269 if ((connectPoint.deviceId()).equals(deviceId(DEV3))) {
alshabib4a179dc2014-10-17 17:17:01 -0700270 return true;
271 }
272 return false;
273 }
274 }
275
276 private class TestPacketContext implements PacketContext {
277
278 private final String deviceId;
279
280 public TestPacketContext(String deviceId) {
281 this.deviceId = deviceId;
282 }
283
284 @Override
285 public long time() {
286 return 0;
287 }
288
289 @Override
290 public InboundPacket inPacket() {
291 ARP arp = new ARP();
292 arp.setSenderProtocolAddress(IP)
293 .setSenderHardwareAddress(MAC.toBytes())
294 .setTargetHardwareAddress(BCMAC.toBytes())
295 .setTargetProtocolAddress(IP);
296
297 Ethernet eth = new Ethernet();
298 eth.setEtherType(Ethernet.TYPE_ARP)
299 .setVlanID(VLAN.toShort())
300 .setSourceMACAddress(MAC.toBytes())
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800301 .setDestinationMACAddress(BCMAC)
alshabib4a179dc2014-10-17 17:17:01 -0700302 .setPayload(arp);
Thomas Vachuska33601602014-11-19 03:32:15 -0800303 ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
304 portNumber(INPORT));
alshabib4a179dc2014-10-17 17:17:01 -0700305 return new DefaultInboundPacket(receivedFrom, eth,
306 ByteBuffer.wrap(eth.serialize()));
307 }
308
309 @Override
310 public OutboundPacket outPacket() {
311 return null;
312 }
313
314 @Override
315 public TrafficTreatment.Builder treatmentBuilder() {
316 return null;
317 }
318
319 @Override
320 public void send() {
321
322 }
323
324 @Override
325 public boolean block() {
326 return false;
327 }
328
329 @Override
330 public boolean isHandled() {
331 return false;
332 }
333 }
Thomas Vachuska33601602014-11-19 03:32:15 -0800334
335 private class TestDeviceService extends DeviceServiceAdapter {
336 private DeviceListener listener;
337
338 @Override
339 public void addListener(DeviceListener listener) {
340 this.listener = listener;
341 }
342 }
343
344 private class TestHostService extends HostServiceAdapter {
345 @Override
346 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
347 return ImmutableSet.of(HOST);
348 }
349
350 @Override
351 public Set<Host> getConnectedHosts(DeviceId deviceId) {
352 return ImmutableSet.of(HOST);
353 }
354
355 }
alshabib4a179dc2014-10-17 17:17:01 -0700356}