blob: 0bf9ba0ba18b39e5ba615282ea271785e419fa51 [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
2* Copyright 2011, Big Switch Networks, Inc.
3* Originally created by David Erickson, Stanford University
4*
5* Licensed under the Apache License, Version 2.0 (the "License"); you may
6* not use this file except in compliance with the License. You may obtain
7* a copy of the License at
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14* License for the specific language governing permissions and limitations
15* under the License.
16**/
17
18package net.floodlightcontroller.linkdiscovery.internal;
19
20import static org.easymock.EasyMock.*;
21
22import java.util.Collections;
23import java.util.ArrayList;
24import java.util.HashMap;
25import java.util.Map;
26
27import org.junit.Before;
28import org.junit.Test;
29
30import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
33import net.floodlightcontroller.core.IFloodlightProviderService;
34import net.floodlightcontroller.core.IFloodlightProviderService.Role;
35import net.floodlightcontroller.core.IOFSwitch;
36import net.floodlightcontroller.core.module.FloodlightModuleContext;
37import net.floodlightcontroller.core.test.MockThreadPoolService;
38import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener;
39import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
40import net.floodlightcontroller.linkdiscovery.LinkInfo;
41import net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager;
42import net.floodlightcontroller.restserver.IRestApiService;
43import net.floodlightcontroller.restserver.RestApiServer;
44import net.floodlightcontroller.routing.IRoutingService;
45import net.floodlightcontroller.routing.Link;
46import net.floodlightcontroller.storage.IStorageSourceService;
47import net.floodlightcontroller.storage.memory.MemoryStorageSource;
48import net.floodlightcontroller.test.FloodlightTestCase;
49import net.floodlightcontroller.threadpool.IThreadPoolService;
50import net.floodlightcontroller.topology.ITopologyService;
51import net.floodlightcontroller.topology.NodePortTuple;
52import net.floodlightcontroller.topology.TopologyManager;
mininet37dc5892013-06-04 10:58:44 -070053import net.onrc.onos.registry.controller.IControllerRegistryService;
54import net.onrc.onos.registry.controller.StandaloneRegistry;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080055
56/**
57 *
58 * @author David Erickson (daviderickson@cs.stanford.edu)
59 */
60public class LinkDiscoveryManagerTest extends FloodlightTestCase {
61
62 private TestLinkDiscoveryManager ldm;
mininet37dc5892013-06-04 10:58:44 -070063 private StandaloneRegistry srs;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080064 protected static Logger log = LoggerFactory.getLogger(LinkDiscoveryManagerTest.class);
65
66 public class TestLinkDiscoveryManager extends LinkDiscoveryManager {
67 public boolean isSendLLDPsCalled = false;
68 public boolean isClearLinksCalled = false;
69
70 @Override
71 protected void discoverOnAllPorts() {
72 isSendLLDPsCalled = true;
73 super.discoverOnAllPorts();
74 }
75
76 public void reset() {
77 isSendLLDPsCalled = false;
78 isClearLinksCalled = false;
79 }
80
81 @Override
82 protected void clearAllLinks() {
83 isClearLinksCalled = true;
84 super.clearAllLinks();
85 }
86 }
87
88 public LinkDiscoveryManager getTopology() {
89 return ldm;
90 }
91
92 public IOFSwitch createMockSwitch(Long id) {
93 IOFSwitch mockSwitch = createNiceMock(IOFSwitch.class);
94 expect(mockSwitch.getId()).andReturn(id).anyTimes();
95 return mockSwitch;
96 }
97
98 @Before
99 public void setUp() throws Exception {
100 super.setUp();
101 FloodlightModuleContext cntx = new FloodlightModuleContext();
102 ldm = new TestLinkDiscoveryManager();
103 TopologyManager routingEngine = new TopologyManager();
104 ldm.linkDiscoveryAware = new ArrayList<ILinkDiscoveryListener>();
mininet37dc5892013-06-04 10:58:44 -0700105 srs = new StandaloneRegistry();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800106 MockThreadPoolService tp = new MockThreadPoolService();
107 RestApiServer restApi = new RestApiServer();
108 cntx.addService(IRestApiService.class, restApi);
109 cntx.addService(IThreadPoolService.class, tp);
110 cntx.addService(IRoutingService.class, routingEngine);
111 cntx.addService(ILinkDiscoveryService.class, ldm);
112 cntx.addService(ITopologyService.class, ldm);
113 cntx.addService(IStorageSourceService.class, new MemoryStorageSource());
114 cntx.addService(IFloodlightProviderService.class, getMockFloodlightProvider());
mininet37dc5892013-06-04 10:58:44 -0700115 cntx.addService(IControllerRegistryService.class, srs);
116
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800117 restApi.init(cntx);
118 tp.init(cntx);
119 routingEngine.init(cntx);
mininet37dc5892013-06-04 10:58:44 -0700120 srs.init(cntx);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800121 ldm.init(cntx);
122 restApi.startUp(cntx);
123 tp.startUp(cntx);
124 routingEngine.startUp(cntx);
mininet37dc5892013-06-04 10:58:44 -0700125 srs.startUp(cntx);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800126 ldm.startUp(cntx);
127
128 IOFSwitch sw1 = createMockSwitch(1L);
129 IOFSwitch sw2 = createMockSwitch(2L);
130 Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>();
131 switches.put(1L, sw1);
132 switches.put(2L, sw2);
133 getMockFloodlightProvider().setSwitches(switches);
134 replay(sw1, sw2);
135 }
136
137 @Test
138 public void testAddOrUpdateLink() throws Exception {
139 LinkDiscoveryManager topology = getTopology();
140
141 Link lt = new Link(1L, 2, 2L, 1);
142 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
143 System.currentTimeMillis(), null,
144 0, 0);
145 topology.addOrUpdateLink(lt, info);
146
147
148 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
149 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
150
151 // check invariants hold
152 assertNotNull(topology.switchLinks.get(lt.getSrc()));
153 assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
154 assertNotNull(topology.portLinks.get(srcNpt));
155 assertTrue(topology.portLinks.get(srcNpt).contains(lt));
156 assertNotNull(topology.portLinks.get(dstNpt));
157 assertTrue(topology.portLinks.get(dstNpt).contains(lt));
158 assertTrue(topology.links.containsKey(lt));
159 }
160
161 @Test
162 public void testDeleteLink() throws Exception {
163 LinkDiscoveryManager topology = getTopology();
164
165 Link lt = new Link(1L, 2, 2L, 1);
166 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
167 System.currentTimeMillis(), null,
168 0, 0);
169 topology.addOrUpdateLink(lt, info);
170 topology.deleteLinks(Collections.singletonList(lt), "Test");
171
172 // check invariants hold
173 assertNull(topology.switchLinks.get(lt.getSrc()));
174 assertNull(topology.switchLinks.get(lt.getDst()));
175 assertNull(topology.portLinks.get(lt.getSrc()));
176 assertNull(topology.portLinks.get(lt.getDst()));
177 assertTrue(topology.links.isEmpty());
178 }
179
180 @Test
181 public void testAddOrUpdateLinkToSelf() throws Exception {
182 LinkDiscoveryManager topology = getTopology();
183
184 Link lt = new Link(1L, 2, 2L, 3);
185 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
186 NodePortTuple dstNpt = new NodePortTuple(2L, 3);
187
188 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
189 System.currentTimeMillis(), null,
190 0, 0);
191 topology.addOrUpdateLink(lt, info);
192
193 // check invariants hold
194 assertNotNull(topology.switchLinks.get(lt.getSrc()));
195 assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
196 assertNotNull(topology.portLinks.get(srcNpt));
197 assertTrue(topology.portLinks.get(srcNpt).contains(lt));
198 assertNotNull(topology.portLinks.get(dstNpt));
199 assertTrue(topology.portLinks.get(dstNpt).contains(lt));
200 assertTrue(topology.links.containsKey(lt));
201 }
202
203 @Test
204 public void testDeleteLinkToSelf() throws Exception {
205 LinkDiscoveryManager topology = getTopology();
206
207 Link lt = new Link(1L, 2, 1L, 3);
208 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
209 NodePortTuple dstNpt = new NodePortTuple(2L, 3);
210
211 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
212 System.currentTimeMillis(), null,
213 0, 0);
214 topology.addOrUpdateLink(lt, info);
215 topology.deleteLinks(Collections.singletonList(lt), "Test to self");
216
217 // check invariants hold
218 assertNull(topology.switchLinks.get(lt.getSrc()));
219 assertNull(topology.switchLinks.get(lt.getDst()));
220 assertNull(topology.portLinks.get(srcNpt));
221 assertNull(topology.portLinks.get(dstNpt));
222 assertTrue(topology.links.isEmpty());
223 }
224
225 @Test
226 public void testRemovedSwitch() {
227 LinkDiscoveryManager topology = getTopology();
228
229 Link lt = new Link(1L, 2, 2L, 1);
230 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
231 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
232 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
233 System.currentTimeMillis(), null,
234 0, 0);
235 topology.addOrUpdateLink(lt, info);
236
237 IOFSwitch sw1 = getMockFloodlightProvider().getSwitches().get(1L);
238 IOFSwitch sw2 = getMockFloodlightProvider().getSwitches().get(2L);
239 // Mock up our expected behavior
240 topology.removedSwitch(sw1);
241 verify(sw1, sw2);
242
243 // check invariants hold
244 assertNull(topology.switchLinks.get(lt.getSrc()));
245 assertNull(topology.switchLinks.get(lt.getDst()));
246 assertNull(topology.portLinks.get(srcNpt));
247 assertNull(topology.portLinks.get(dstNpt));
248 assertTrue(topology.links.isEmpty());
249 }
250
251 @Test
252 public void testRemovedSwitchSelf() {
253 LinkDiscoveryManager topology = getTopology();
254 IOFSwitch sw1 = createMockSwitch(1L);
255 replay(sw1);
256 Link lt = new Link(1L, 2, 1L, 3);
257 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
258 System.currentTimeMillis(), null,
259 0, 0);
260 topology.addOrUpdateLink(lt, info);
261
262 // Mock up our expected behavior
263 topology.removedSwitch(sw1);
264
265 verify(sw1);
266 // check invariants hold
267 assertNull(topology.switchLinks.get(lt.getSrc()));
268 assertNull(topology.portLinks.get(lt.getSrc()));
269 assertNull(topology.portLinks.get(lt.getDst()));
270 assertTrue(topology.links.isEmpty());
271 }
272
273 @Test
274 public void testAddUpdateLinks() throws Exception {
275 LinkDiscoveryManager topology = getTopology();
276
277 Link lt = new Link(1L, 1, 2L, 1);
278 NodePortTuple srcNpt = new NodePortTuple(1L, 1);
279 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
280
281 LinkInfo info;
282
283 info = new LinkInfo(System.currentTimeMillis() - 40000,
284 System.currentTimeMillis() - 40000, null,
285 0, 0);
286 topology.addOrUpdateLink(lt, info);
287
288 // check invariants hold
289 assertNotNull(topology.switchLinks.get(lt.getSrc()));
290 assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
291 assertNotNull(topology.portLinks.get(srcNpt));
292 assertTrue(topology.portLinks.get(srcNpt).contains(lt));
293 assertNotNull(topology.portLinks.get(dstNpt));
294 assertTrue(topology.portLinks.get(dstNpt).contains(lt));
295 assertTrue(topology.links.containsKey(lt));
296 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt) == null ||
297 topology.portBroadcastDomainLinks.get(srcNpt).contains(lt) == false);
298 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt) == null ||
299 topology.portBroadcastDomainLinks.get(dstNpt).contains(lt) == false);
300
301 topology.timeoutLinks();
302
303
304 info = new LinkInfo(System.currentTimeMillis(),/* firstseen */
305 null,/* unicast */
306 System.currentTimeMillis(), 0, 0);
307 topology.addOrUpdateLink(lt, info);
308 assertTrue(topology.links.get(lt).getUnicastValidTime() == null);
309 assertTrue(topology.links.get(lt).getMulticastValidTime() != null);
310 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
311 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
312
313
314 // Add a link info based on info that woudld be obtained from unicast LLDP
315 // Setting the unicast LLDP reception time to be 40 seconds old, so we can use
316 // this to test timeout after this test. Although the info is initialized
317 // with LT_OPENFLOW_LINK, the link property should be changed to LT_NON_OPENFLOW
318 // by the addOrUpdateLink method.
319 info = new LinkInfo(System.currentTimeMillis() - 40000,
320 System.currentTimeMillis() - 40000, null, 0, 0);
321 topology.addOrUpdateLink(lt, info);
322 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt) == null ||
323 topology.portBroadcastDomainLinks.get(srcNpt).contains(lt) == false);
324 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt) == null ||
325 topology.portBroadcastDomainLinks.get(dstNpt).contains(lt) == false);
326
327 // Expect to timeout the unicast Valid Time, but not the multicast Valid time
328 // So the link type should go back to non-openflow link.
329 topology.timeoutLinks();
330 assertTrue(topology.links.get(lt).getUnicastValidTime() == null);
331 assertTrue(topology.links.get(lt).getMulticastValidTime() != null);
332 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
333 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
334
335 // Set the multicastValidTime to be old and see if that also times out.
336 info = new LinkInfo(System.currentTimeMillis() - 40000,
337 null, System.currentTimeMillis() - 40000, 0, 0);
338 topology.addOrUpdateLink(lt, info);
339 topology.timeoutLinks();
340 assertTrue(topology.links.get(lt) == null);
341 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt) == null ||
342 topology.portBroadcastDomainLinks.get(srcNpt).contains(lt) == false);
343 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt) == null ||
344 topology.portBroadcastDomainLinks.get(dstNpt).contains(lt) == false);
345
346
347 // Test again only with multicast LLDP
348 info = new LinkInfo(System.currentTimeMillis() - 40000,
349 null, System.currentTimeMillis() - 40000, 0, 0);
350 topology.addOrUpdateLink(lt, info);
351 assertTrue(topology.links.get(lt).getUnicastValidTime() == null);
352 assertTrue(topology.links.get(lt).getMulticastValidTime() != null);
353 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
354 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
355
356 // Call timeout and check if link is no longer present.
357 topology.timeoutLinks();
358 assertTrue(topology.links.get(lt) == null);
359 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt) == null ||
360 topology.portBroadcastDomainLinks.get(srcNpt).contains(lt) == false);
361 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt) == null ||
362 topology.portBroadcastDomainLinks.get(dstNpt).contains(lt) == false);
363
364 // Start clean and see if loops are also added.
365 lt = new Link(1L, 1, 1L, 2);
366 srcNpt = new NodePortTuple(1L, 1);
367 dstNpt = new NodePortTuple(1L, 2);
368 info = new LinkInfo(System.currentTimeMillis() - 40000,
369 null, System.currentTimeMillis() - 40000, 0, 0);
370 topology.addOrUpdateLink(lt, info);
371 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
372 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
373
374
375 // Start clean and see if loops are also added.
376 lt = new Link(1L, 1, 1L, 3);
377 srcNpt = new NodePortTuple(1L, 1);
378 dstNpt = new NodePortTuple(1L, 3);
379 info = new LinkInfo(System.currentTimeMillis() - 40000,
380 null, System.currentTimeMillis() - 40000, 0, 0);
381 topology.addOrUpdateLink(lt, info);
382 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
383 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
384
385
386 // Start clean and see if loops are also added.
387 lt = new Link(1L, 4, 1L, 5);
388 srcNpt = new NodePortTuple(1L, 4);
389 dstNpt = new NodePortTuple(1L, 5);
390 info = new LinkInfo(System.currentTimeMillis() - 40000,
391 null, System.currentTimeMillis() - 40000, 0, 0);
392 topology.addOrUpdateLink(lt, info);
393 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
394 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
395
396
397 // Start clean and see if loops are also added.
398 lt = new Link(1L, 3, 1L, 5);
399 srcNpt = new NodePortTuple(1L, 3);
400 dstNpt = new NodePortTuple(1L, 5);
401 info = new LinkInfo(System.currentTimeMillis() - 40000,
402 null, System.currentTimeMillis() - 40000, 0, 0);
403 topology.addOrUpdateLink(lt, info);
404 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
405 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
406 }
407
408 @Test
409 public void testHARoleChange() throws Exception {
410 LinkDiscoveryManager topology = getTopology();
411 IOFSwitch sw1 = createMockSwitch(1L);
412 IOFSwitch sw2 = createMockSwitch(2L);
413 replay(sw1, sw2);
414 Link lt = new Link(1L, 2, 2L, 1);
415 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
416 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
417 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
418 System.currentTimeMillis(), null,
419 0, 0);
420 topology.addOrUpdateLink(lt, info);
421
422 // check invariants hold
423 assertNotNull(topology.switchLinks.get(lt.getSrc()));
424 assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
425 assertNotNull(topology.portLinks.get(srcNpt));
426 assertTrue(topology.portLinks.get(srcNpt).contains(lt));
427 assertNotNull(topology.portLinks.get(dstNpt));
428 assertTrue(topology.portLinks.get(dstNpt).contains(lt));
429 assertTrue(topology.links.containsKey(lt));
430
431 // check that it clears from memory
432 getMockFloodlightProvider().dispatchRoleChanged(null, Role.SLAVE);
433 assertTrue(topology.switchLinks.isEmpty());
434 getMockFloodlightProvider().dispatchRoleChanged(Role.SLAVE, Role.MASTER);
435 // check that lldps were sent
436 assertTrue(ldm.isSendLLDPsCalled);
437 assertTrue(ldm.isClearLinksCalled);
438 ldm.reset();
439 }
440}