b9d90976e9af51b3fe1f64dd7600b2f91ca0c067
[onosfw.git] /
1 /*
2  * Copyright 2014-2015 Open Networking Laboratory
3  *
4  * 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
7  *
8  *     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.
15  */
16 package org.onosproject.provider.host.impl;
17
18 import com.google.common.collect.ImmutableSet;
19 import org.junit.After;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.onlab.osgi.ComponentContextAdapter;
23 import org.onlab.packet.ARP;
24 import org.onlab.packet.ChassisId;
25 import org.onlab.packet.Ethernet;
26 import org.onlab.packet.IpAddress;
27 import org.onlab.packet.MacAddress;
28 import org.onlab.packet.VlanId;
29 import org.onosproject.cfg.ComponentConfigAdapter;
30 import org.onosproject.core.ApplicationId;
31 import org.onosproject.core.CoreService;
32 import org.onosproject.core.DefaultApplicationId;
33 import org.onosproject.net.ConnectPoint;
34 import org.onosproject.net.DefaultDevice;
35 import org.onosproject.net.DefaultHost;
36 import org.onosproject.net.DefaultPort;
37 import org.onosproject.net.Device;
38 import org.onosproject.net.DeviceId;
39 import org.onosproject.net.Host;
40 import org.onosproject.net.HostId;
41 import org.onosproject.net.HostLocation;
42 import org.onosproject.net.device.DeviceEvent;
43 import org.onosproject.net.device.DeviceListener;
44 import org.onosproject.net.device.DeviceServiceAdapter;
45 import org.onosproject.net.flow.TrafficTreatment;
46 import org.onosproject.net.host.HostDescription;
47 import org.onosproject.net.host.HostProvider;
48 import org.onosproject.net.host.HostProviderRegistry;
49 import org.onosproject.net.host.HostProviderService;
50 import org.onosproject.net.host.HostServiceAdapter;
51 import org.onosproject.net.packet.DefaultInboundPacket;
52 import org.onosproject.net.packet.InboundPacket;
53 import org.onosproject.net.packet.OutboundPacket;
54 import org.onosproject.net.packet.PacketContext;
55 import org.onosproject.net.packet.PacketProcessor;
56 import org.onosproject.net.packet.PacketServiceAdapter;
57 import org.onosproject.net.provider.AbstractProviderService;
58 import org.onosproject.net.provider.ProviderId;
59 import org.onosproject.net.topology.Topology;
60 import org.onosproject.net.topology.TopologyServiceAdapter;
61
62 import java.nio.ByteBuffer;
63 import java.util.Collections;
64 import java.util.Dictionary;
65 import java.util.Hashtable;
66 import java.util.Set;
67
68 import static org.easymock.EasyMock.*;
69 import static org.junit.Assert.*;
70 import static org.onlab.packet.VlanId.vlanId;
71 import static org.onosproject.net.Device.Type.SWITCH;
72 import static org.onosproject.net.DeviceId.deviceId;
73 import static org.onosproject.net.HostId.hostId;
74 import static org.onosproject.net.PortNumber.portNumber;
75 import static org.onosproject.net.device.DeviceEvent.Type.*;
76
77 public class HostLocationProviderTest {
78
79     private static final Integer INPORT = 10;
80     private static final String DEV1 = "of:1";
81     private static final String DEV2 = "of:2";
82     private static final String DEV3 = "of:3";
83
84     private static final VlanId VLAN = vlanId();
85     private static final MacAddress MAC = MacAddress.valueOf("00:00:11:00:00:01");
86     private static final MacAddress BCMAC = MacAddress.valueOf("ff:ff:ff:ff:ff:ff");
87     private static final byte[] IP = new byte[]{10, 0, 0, 1};
88
89     private static final IpAddress IP_ADDRESS =
90             IpAddress.valueOf(IpAddress.Version.INET, IP);
91     private static final HostLocation LOCATION =
92             new HostLocation(deviceId(DEV1), portNumber(INPORT), 0L);
93
94     private static final DefaultHost HOST =
95             new DefaultHost(ProviderId.NONE, hostId(MAC), MAC,
96                             vlanId(VlanId.UNTAGGED), LOCATION,
97                             ImmutableSet.of(IP_ADDRESS));
98
99     private static final ComponentContextAdapter CTX_FOR_REMOVE =
100             new ComponentContextAdapter() {
101                 @Override
102                 public Dictionary getProperties() {
103                     Hashtable<String, String> props = new Hashtable<>();
104                     props.put("hostRemovalEnabled", "true");
105                     return props;
106                 }
107             };
108
109     public static final ComponentContextAdapter CTX_FOR_NO_REMOVE =
110             new ComponentContextAdapter() {
111                 @Override
112                 public Dictionary getProperties() {
113                     return new Hashtable();
114                 }
115             };
116
117     private final HostLocationProvider provider = new HostLocationProvider();
118     private final TestHostRegistry hostRegistry = new TestHostRegistry();
119     private final TestTopologyService topoService = new TestTopologyService();
120     private final TestDeviceService deviceService = new TestDeviceService();
121     private final TestHostService hostService = new TestHostService();
122     private final TestPacketService packetService = new TestPacketService();
123
124     private PacketProcessor testProcessor;
125     private CoreService coreService;
126     private TestHostProviderService providerService;
127
128     private ApplicationId appId =
129             new DefaultApplicationId(100, "org.onosproject.provider.host");
130
131     @Before
132     public void setUp() {
133
134         coreService = createMock(CoreService.class);
135         expect(coreService.registerApplication(appId.name()))
136                 .andReturn(appId).anyTimes();
137         replay(coreService);
138
139         provider.cfgService = new ComponentConfigAdapter();
140         provider.coreService = coreService;
141
142         provider.providerRegistry = hostRegistry;
143         provider.topologyService = topoService;
144         provider.packetService = packetService;
145         provider.deviceService = deviceService;
146         provider.hostService = hostService;
147
148         provider.activate(CTX_FOR_NO_REMOVE);
149     }
150
151     @Test
152     public void basics() {
153         assertNotNull("registration expected", providerService);
154         assertEquals("incorrect provider", provider, providerService.provider());
155     }
156
157     @Test
158     public void events() {
159         // new host
160         testProcessor.process(new TestPacketContext(DEV1));
161         assertNotNull("new host expected", providerService.added);
162         assertNull("host motion unexpected", providerService.moved);
163
164         // the host moved to new switch
165         testProcessor.process(new TestPacketContext(DEV2));
166         assertNotNull("host motion expected", providerService.moved);
167
168         // the host was misheard on a spine
169         testProcessor.process(new TestPacketContext(DEV3));
170         assertNull("host misheard on spine switch", providerService.spine);
171     }
172
173     @Test
174     public void removeHostByDeviceRemove() {
175         provider.modified(CTX_FOR_REMOVE);
176         testProcessor.process(new TestPacketContext(DEV1));
177         Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
178                                           "m", "h", "s", "n", new ChassisId(0L));
179         deviceService.listener.event(new DeviceEvent(DEVICE_REMOVED, device));
180         assertEquals("incorrect remove count", 1, providerService.removeCount);
181     }
182
183     @Test
184     public void removeHostByDeviceOffline() {
185         provider.modified(CTX_FOR_REMOVE);
186         testProcessor.process(new TestPacketContext(DEV1));
187         Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
188                                           "m", "h", "s", "n", new ChassisId(0L));
189         deviceService.listener.event(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device));
190         assertEquals("incorrect remove count", 1, providerService.removeCount);
191     }
192
193     @Test
194     public void removeHostByDevicePortDown() {
195         provider.modified(CTX_FOR_REMOVE);
196         testProcessor.process(new TestPacketContext(DEV1));
197         Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH,
198                                           "m", "h", "s", "n", new ChassisId(0L));
199         deviceService.listener.event(new DeviceEvent(PORT_UPDATED, device,
200                                                      new DefaultPort(device, portNumber(INPORT),
201                                                                      false)));
202         assertEquals("incorrect remove count", 1, providerService.removeCount);
203     }
204
205
206     @After
207     public void tearDown() {
208         provider.deactivate();
209         provider.coreService = null;
210         provider.providerRegistry = null;
211     }
212
213     private class TestHostRegistry implements HostProviderRegistry {
214
215         @Override
216         public HostProviderService register(HostProvider provider) {
217             providerService = new TestHostProviderService(provider);
218             return providerService;
219         }
220
221         @Override
222         public void unregister(HostProvider provider) {
223         }
224
225         @Override
226         public Set<ProviderId> getProviders() {
227             return null;
228         }
229
230     }
231
232     private class TestHostProviderService
233             extends AbstractProviderService<HostProvider>
234             implements HostProviderService {
235
236         DeviceId added = null;
237         DeviceId moved = null;
238         DeviceId spine = null;
239         public int removeCount;
240
241         protected TestHostProviderService(HostProvider provider) {
242             super(provider);
243         }
244
245         @Override
246         public void hostDetected(HostId hostId, HostDescription hostDescription) {
247             DeviceId descr = hostDescription.location().deviceId();
248             if (added == null) {
249                 added = descr;
250             } else if ((moved == null) && !descr.equals(added)) {
251                 moved = descr;
252             } else {
253                 spine = descr;
254             }
255         }
256
257         @Override
258         public void hostVanished(HostId hostId) {
259             removeCount++;
260         }
261
262     }
263
264     private class TestPacketService extends PacketServiceAdapter {
265         @Override
266         public void addProcessor(PacketProcessor processor, int priority) {
267             testProcessor = processor;
268         }
269     }
270
271
272     private class TestTopologyService extends TopologyServiceAdapter {
273         @Override
274         public boolean isInfrastructure(Topology topology,
275                                         ConnectPoint connectPoint) {
276             //simulate DPID3 as an infrastructure switch
277             if ((connectPoint.deviceId()).equals(deviceId(DEV3))) {
278                 return true;
279             }
280             return false;
281         }
282     }
283
284     private class TestPacketContext implements PacketContext {
285
286         private final String deviceId;
287
288         public TestPacketContext(String deviceId) {
289             this.deviceId = deviceId;
290         }
291
292         @Override
293         public long time() {
294             return 0;
295         }
296
297         @Override
298         public InboundPacket inPacket() {
299             ARP arp = new ARP();
300             arp.setSenderProtocolAddress(IP)
301                     .setSenderHardwareAddress(MAC.toBytes())
302                     .setTargetHardwareAddress(BCMAC.toBytes())
303                     .setTargetProtocolAddress(IP);
304
305             Ethernet eth = new Ethernet();
306             eth.setEtherType(Ethernet.TYPE_ARP)
307                     .setVlanID(VLAN.toShort())
308                     .setSourceMACAddress(MAC.toBytes())
309                     .setDestinationMACAddress(BCMAC)
310                     .setPayload(arp);
311             ConnectPoint receivedFrom = new ConnectPoint(deviceId(deviceId),
312                                                          portNumber(INPORT));
313             return new DefaultInboundPacket(receivedFrom, eth,
314                                             ByteBuffer.wrap(eth.serialize()));
315         }
316
317         @Override
318         public OutboundPacket outPacket() {
319             return null;
320         }
321
322         @Override
323         public TrafficTreatment.Builder treatmentBuilder() {
324             return null;
325         }
326
327         @Override
328         public void send() {
329
330         }
331
332         @Override
333         public boolean block() {
334             return false;
335         }
336
337         @Override
338         public boolean isHandled() {
339             return false;
340         }
341     }
342
343     private class TestDeviceService extends DeviceServiceAdapter {
344         private DeviceListener listener;
345
346         @Override
347         public void addListener(DeviceListener listener) {
348             this.listener = listener;
349         }
350
351         @Override
352         public Iterable<Device> getDevices() {
353             return Collections.emptyList();
354         }
355     }
356
357     private class TestHostService extends HostServiceAdapter {
358         @Override
359         public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
360             return ImmutableSet.of(HOST);
361         }
362
363         @Override
364         public Set<Host> getConnectedHosts(DeviceId deviceId) {
365             return ImmutableSet.of(HOST);
366         }
367
368     }
369 }