1d63a15dd26a91aae2873c4f7be920ee11eed516
[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.lldp.impl;
17
18 import com.google.common.collect.ArrayListMultimap;
19 import com.google.common.collect.Lists;
20 import com.google.common.collect.Maps;
21 import org.junit.After;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.onlab.packet.ChassisId;
25 import org.onlab.packet.Ethernet;
26 import org.onlab.packet.ONOSLLDP;
27 import org.onosproject.cfg.ComponentConfigAdapter;
28 import org.onosproject.cluster.NodeId;
29 import org.onosproject.cluster.RoleInfo;
30 import org.onosproject.core.ApplicationId;
31 import org.onosproject.core.CoreService;
32 import org.onosproject.core.DefaultApplicationId;
33 import org.onosproject.mastership.MastershipListener;
34 import org.onosproject.mastership.MastershipService;
35 import org.onosproject.net.ConnectPoint;
36 import org.onosproject.net.DefaultDevice;
37 import org.onosproject.net.DefaultPort;
38 import org.onosproject.net.Device;
39 import org.onosproject.net.DeviceId;
40 import org.onosproject.net.MastershipRole;
41 import org.onosproject.net.Port;
42 import org.onosproject.net.PortNumber;
43 import org.onosproject.net.device.DeviceEvent;
44 import org.onosproject.net.device.DeviceListener;
45 import org.onosproject.net.device.DeviceServiceAdapter;
46 import org.onosproject.net.flow.TrafficTreatment;
47 import org.onosproject.net.link.LinkDescription;
48 import org.onosproject.net.link.LinkProvider;
49 import org.onosproject.net.link.LinkProviderRegistry;
50 import org.onosproject.net.link.LinkProviderService;
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
60 import java.nio.ByteBuffer;
61 import java.util.Collections;
62 import java.util.HashMap;
63 import java.util.List;
64 import java.util.Map;
65 import java.util.Set;
66 import java.util.concurrent.CompletableFuture;
67
68 import static org.easymock.EasyMock.*;
69 import static org.junit.Assert.*;
70
71 public class LLDPLinkProviderTest {
72
73     private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
74     private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002");
75
76     private static Port pd1;
77     private static Port pd2;
78     private static Port pd3;
79     private static Port pd4;
80
81     private final LLDPLinkProvider provider = new LLDPLinkProvider();
82     private final TestLinkRegistry linkService = new TestLinkRegistry();
83     private final TestPacketService packetService = new TestPacketService();
84     private final TestDeviceService deviceService = new TestDeviceService();
85     private final TestMasterShipService masterService = new TestMasterShipService();
86
87     private CoreService coreService;
88     private TestLinkProviderService providerService;
89
90     private PacketProcessor testProcessor;
91     private DeviceListener deviceListener;
92
93     private ApplicationId appId =
94             new DefaultApplicationId(100, "org.onosproject.provider.lldp");
95
96     @Before
97     public void setUp() {
98         coreService = createMock(CoreService.class);
99         expect(coreService.registerApplication(appId.name()))
100             .andReturn(appId).anyTimes();
101         replay(coreService);
102
103         provider.cfgService = new ComponentConfigAdapter();
104         provider.coreService = coreService;
105
106         provider.deviceService = deviceService;
107         provider.packetService = packetService;
108         provider.providerRegistry = linkService;
109         provider.masterService = masterService;
110
111
112         provider.activate(null);
113     }
114
115     @Test
116     public void basics() {
117         assertNotNull("registration expected", providerService);
118         assertEquals("incorrect provider", provider, providerService.provider());
119     }
120
121     @Test
122     public void switchAdd() {
123         DeviceEvent de = deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1);
124         deviceListener.event(de);
125
126         assertFalse("Device not added", provider.discoverers.isEmpty());
127     }
128
129     @Test
130     public void switchRemove() {
131         deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
132         deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_REMOVED, DID1));
133
134         assertTrue("Discoverer is not gone", provider.discoverers.get(DID1).isStopped());
135         assertTrue("Device is not gone.", vanishedDpid(DID1));
136     }
137
138     @Test
139     public void portUp() {
140         deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
141         deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
142
143         assertTrue("Port not added to discoverer",
144                    provider.discoverers.get(DID1).containsPort(3L));
145     }
146
147     @Test
148     public void portDown() {
149
150         deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
151         deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 1, false)));
152
153
154
155         assertFalse("Port added to discoverer",
156                     provider.discoverers.get(DID1).containsPort(1L));
157         assertTrue("Port is not gone.", vanishedPort(1L));
158     }
159
160     @Test
161     public void portUnknown() {
162         deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
163         deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID2, port(DID2, 1, false)));
164
165
166         assertNull("DeviceId exists",
167                    provider.discoverers.get(DID2));
168     }
169
170     @Test
171     public void unknownPktCtx() {
172
173         PacketContext pktCtx = new TestPacketContext(deviceService.getDevice(DID2));
174
175         testProcessor.process(pktCtx);
176         assertFalse("Context should still be free", pktCtx.isHandled());
177     }
178
179     @Test
180     public void knownPktCtx() {
181         deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
182         deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2));
183         PacketContext pktCtx = new TestPacketContext(deviceService.getDevice(DID2));
184
185
186         testProcessor.process(pktCtx);
187
188         assertTrue("Link not detected", detectedLink(DID1, DID2));
189
190     }
191
192
193     @After
194     public void tearDown() {
195         provider.deactivate();
196         provider.coreService = null;
197         provider.providerRegistry = null;
198         provider.deviceService = null;
199         provider.packetService = null;
200     }
201
202     private DeviceEvent deviceEvent(DeviceEvent.Type type, DeviceId did) {
203         return new DeviceEvent(type, deviceService.getDevice(did));
204
205     }
206
207     @SuppressWarnings(value = { "unused" })
208     private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, PortNumber port) {
209         return new  DeviceEvent(type, deviceService.getDevice(did),
210                                 deviceService.getPort(did, port));
211     }
212
213     private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, Port port) {
214         return new  DeviceEvent(type, deviceService.getDevice(did), port);
215     }
216
217     private Port port(DeviceId did, long port, boolean enabled) {
218         return new DefaultPort(deviceService.getDevice(did),
219                                PortNumber.portNumber(port), enabled);
220     }
221
222
223     private boolean vanishedDpid(DeviceId... dids) {
224         for (int i = 0; i < dids.length; i++) {
225             if (!providerService.vanishedDpid.contains(dids[i])) {
226                 return false;
227             }
228         }
229         return true;
230     }
231
232     private boolean vanishedPort(Long... ports) {
233         for (int i = 0; i < ports.length; i++) {
234             if (!providerService.vanishedPort.contains(ports[i])) {
235                 return false;
236             }
237         }
238         return true;
239     }
240
241     private boolean detectedLink(DeviceId src, DeviceId dst) {
242         for (DeviceId key : providerService.discoveredLinks.keySet()) {
243             if (key.equals(src)) {
244                 return providerService.discoveredLinks.get(src).equals(dst);
245             }
246         }
247         return false;
248     }
249
250
251     private class TestLinkRegistry implements LinkProviderRegistry {
252
253         @Override
254         public LinkProviderService register(LinkProvider provider) {
255             providerService = new TestLinkProviderService(provider);
256             return providerService;
257         }
258
259         @Override
260         public void unregister(LinkProvider provider) {
261         }
262
263         @Override
264         public Set<ProviderId> getProviders() {
265             return null;
266         }
267
268     }
269
270     private class TestLinkProviderService
271             extends AbstractProviderService<LinkProvider>
272             implements LinkProviderService {
273
274         List<DeviceId> vanishedDpid = Lists.newLinkedList();
275         List<Long> vanishedPort = Lists.newLinkedList();
276         Map<DeviceId, DeviceId> discoveredLinks = Maps.newHashMap();
277
278         protected TestLinkProviderService(LinkProvider provider) {
279             super(provider);
280         }
281
282         @Override
283         public void linkDetected(LinkDescription linkDescription) {
284             DeviceId sDid = linkDescription.src().deviceId();
285             DeviceId dDid = linkDescription.dst().deviceId();
286             discoveredLinks.put(sDid, dDid);
287         }
288
289         @Override
290         public void linkVanished(LinkDescription linkDescription) {
291         }
292
293         @Override
294         public void linksVanished(ConnectPoint connectPoint) {
295             vanishedPort.add(connectPoint.port().toLong());
296
297         }
298
299         @Override
300         public void linksVanished(DeviceId deviceId) {
301             vanishedDpid.add(deviceId);
302         }
303
304
305     }
306
307
308
309     private class TestPacketContext implements PacketContext {
310
311         protected Device device;
312         protected boolean blocked = false;
313
314         public TestPacketContext(Device dev) {
315             device = dev;
316         }
317
318         @Override
319         public long time() {
320             return 0;
321         }
322
323         @Override
324         public InboundPacket inPacket() {
325             ONOSLLDP lldp = new ONOSLLDP();
326             lldp.setChassisId(device.chassisId());
327             lldp.setPortId((int) pd1.number().toLong());
328             lldp.setDevice(deviceService.getDevice(DID1).id().toString());
329
330
331             Ethernet ethPacket = new Ethernet();
332             ethPacket.setEtherType(Ethernet.TYPE_LLDP);
333             ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_NICIRA);
334             ethPacket.setPayload(lldp);
335             ethPacket.setPad(true);
336
337
338
339             ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11");
340
341             ConnectPoint cp = new ConnectPoint(device.id(), pd3.number());
342
343             return new DefaultInboundPacket(cp, ethPacket,
344                                             ByteBuffer.wrap(ethPacket.serialize()));
345
346         }
347
348         @Override
349         public OutboundPacket outPacket() {
350             return null;
351         }
352
353         @Override
354         public TrafficTreatment.Builder treatmentBuilder() {
355             return null;
356         }
357
358         @Override
359         public void send() {
360
361         }
362
363         @Override
364         public boolean block() {
365             blocked = true;
366             return blocked;
367         }
368
369         @Override
370         public boolean isHandled() {
371             return blocked;
372         }
373
374     }
375
376     private class TestPacketService extends PacketServiceAdapter {
377         @Override
378         public void addProcessor(PacketProcessor processor, int priority) {
379             testProcessor = processor;
380         }
381     }
382
383     private class TestDeviceService extends DeviceServiceAdapter {
384
385         private Map<DeviceId, Device> devices = new HashMap<>();
386         private final ArrayListMultimap<DeviceId, Port> ports =
387                 ArrayListMultimap.create();
388
389         public TestDeviceService() {
390             Device d1 = new DefaultDevice(ProviderId.NONE, DID1, Device.Type.SWITCH,
391                                           "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
392             Device d2 = new DefaultDevice(ProviderId.NONE, DID2, Device.Type.SWITCH,
393                                           "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
394             devices.put(DID1, d1);
395             devices.put(DID2, d2);
396
397             pd1 = new DefaultPort(d1, PortNumber.portNumber(1), true);
398             pd2 = new DefaultPort(d1, PortNumber.portNumber(2), true);
399             pd3 = new DefaultPort(d2, PortNumber.portNumber(1), true);
400             pd4 = new DefaultPort(d2, PortNumber.portNumber(2), true);
401
402             ports.putAll(DID1, Lists.newArrayList(pd1, pd2));
403             ports.putAll(DID2, Lists.newArrayList(pd3, pd4));
404         }
405
406         @Override
407         public int getDeviceCount() {
408             return devices.values().size();
409         }
410
411         @Override
412         public Iterable<Device> getDevices() {
413             return Collections.emptyList();
414         }
415
416         @Override
417         public Device getDevice(DeviceId deviceId) {
418             return devices.get(deviceId);
419         }
420
421         @Override
422         public MastershipRole getRole(DeviceId deviceId) {
423             return MastershipRole.MASTER;
424         }
425
426         @Override
427         public List<Port> getPorts(DeviceId deviceId) {
428             return ports.get(deviceId);
429         }
430
431         @Override
432         public Port getPort(DeviceId deviceId, PortNumber portNumber) {
433             for (Port p : ports.get(deviceId)) {
434                 if (p.number().equals(portNumber)) {
435                     return p;
436                 }
437             }
438             return null;
439         }
440
441         @Override
442         public boolean isAvailable(DeviceId deviceId) {
443             return true;
444         }
445
446         @Override
447         public void addListener(DeviceListener listener) {
448             deviceListener = listener;
449
450         }
451
452         @Override
453         public void removeListener(DeviceListener listener) {
454
455         }
456     }
457
458     private final class TestMasterShipService implements MastershipService {
459
460         @Override
461         public MastershipRole getLocalRole(DeviceId deviceId) {
462             return MastershipRole.MASTER;
463         }
464
465         @Override
466         public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
467             return CompletableFuture.completedFuture(null);
468         }
469
470         @Override
471         public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
472             return null;
473         }
474
475         @Override
476         public NodeId getMasterFor(DeviceId deviceId) {
477             return null;
478         }
479
480         @Override
481         public Set<DeviceId> getDevicesOf(NodeId nodeId) {
482             return null;
483         }
484
485         @Override
486         public void addListener(MastershipListener listener) {
487
488         }
489
490         @Override
491         public void removeListener(MastershipListener listener) {
492
493         }
494
495         @Override
496         public RoleInfo getNodesFor(DeviceId deviceId) {
497             return new RoleInfo(new NodeId("foo"), Collections.<NodeId>emptyList());
498         }
499     }
500
501
502 }