blob: 6e99acdd14d4a70a2143a66becc0e4b9a7dba8fc [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;
53
54/**
55 *
56 * @author David Erickson (daviderickson@cs.stanford.edu)
57 */
58public class LinkDiscoveryManagerTest extends FloodlightTestCase {
59
60 private TestLinkDiscoveryManager ldm;
61 protected static Logger log = LoggerFactory.getLogger(LinkDiscoveryManagerTest.class);
62
63 public class TestLinkDiscoveryManager extends LinkDiscoveryManager {
64 public boolean isSendLLDPsCalled = false;
65 public boolean isClearLinksCalled = false;
66
67 @Override
68 protected void discoverOnAllPorts() {
69 isSendLLDPsCalled = true;
70 super.discoverOnAllPorts();
71 }
72
73 public void reset() {
74 isSendLLDPsCalled = false;
75 isClearLinksCalled = false;
76 }
77
78 @Override
79 protected void clearAllLinks() {
80 isClearLinksCalled = true;
81 super.clearAllLinks();
82 }
83 }
84
85 public LinkDiscoveryManager getTopology() {
86 return ldm;
87 }
88
89 public IOFSwitch createMockSwitch(Long id) {
90 IOFSwitch mockSwitch = createNiceMock(IOFSwitch.class);
91 expect(mockSwitch.getId()).andReturn(id).anyTimes();
92 return mockSwitch;
93 }
94
95 @Before
96 public void setUp() throws Exception {
97 super.setUp();
98 FloodlightModuleContext cntx = new FloodlightModuleContext();
99 ldm = new TestLinkDiscoveryManager();
100 TopologyManager routingEngine = new TopologyManager();
101 ldm.linkDiscoveryAware = new ArrayList<ILinkDiscoveryListener>();
102 MockThreadPoolService tp = new MockThreadPoolService();
103 RestApiServer restApi = new RestApiServer();
104 cntx.addService(IRestApiService.class, restApi);
105 cntx.addService(IThreadPoolService.class, tp);
106 cntx.addService(IRoutingService.class, routingEngine);
107 cntx.addService(ILinkDiscoveryService.class, ldm);
108 cntx.addService(ITopologyService.class, ldm);
109 cntx.addService(IStorageSourceService.class, new MemoryStorageSource());
110 cntx.addService(IFloodlightProviderService.class, getMockFloodlightProvider());
111 restApi.init(cntx);
112 tp.init(cntx);
113 routingEngine.init(cntx);
114 ldm.init(cntx);
115 restApi.startUp(cntx);
116 tp.startUp(cntx);
117 routingEngine.startUp(cntx);
118 ldm.startUp(cntx);
119
120 IOFSwitch sw1 = createMockSwitch(1L);
121 IOFSwitch sw2 = createMockSwitch(2L);
122 Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>();
123 switches.put(1L, sw1);
124 switches.put(2L, sw2);
125 getMockFloodlightProvider().setSwitches(switches);
126 replay(sw1, sw2);
127 }
128
129 @Test
130 public void testAddOrUpdateLink() throws Exception {
131 LinkDiscoveryManager topology = getTopology();
132
133 Link lt = new Link(1L, 2, 2L, 1);
134 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
135 System.currentTimeMillis(), null,
136 0, 0);
137 topology.addOrUpdateLink(lt, info);
138
139
140 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
141 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
142
143 // check invariants hold
144 assertNotNull(topology.switchLinks.get(lt.getSrc()));
145 assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
146 assertNotNull(topology.portLinks.get(srcNpt));
147 assertTrue(topology.portLinks.get(srcNpt).contains(lt));
148 assertNotNull(topology.portLinks.get(dstNpt));
149 assertTrue(topology.portLinks.get(dstNpt).contains(lt));
150 assertTrue(topology.links.containsKey(lt));
151 }
152
153 @Test
154 public void testDeleteLink() throws Exception {
155 LinkDiscoveryManager topology = getTopology();
156
157 Link lt = new Link(1L, 2, 2L, 1);
158 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
159 System.currentTimeMillis(), null,
160 0, 0);
161 topology.addOrUpdateLink(lt, info);
162 topology.deleteLinks(Collections.singletonList(lt), "Test");
163
164 // check invariants hold
165 assertNull(topology.switchLinks.get(lt.getSrc()));
166 assertNull(topology.switchLinks.get(lt.getDst()));
167 assertNull(topology.portLinks.get(lt.getSrc()));
168 assertNull(topology.portLinks.get(lt.getDst()));
169 assertTrue(topology.links.isEmpty());
170 }
171
172 @Test
173 public void testAddOrUpdateLinkToSelf() throws Exception {
174 LinkDiscoveryManager topology = getTopology();
175
176 Link lt = new Link(1L, 2, 2L, 3);
177 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
178 NodePortTuple dstNpt = new NodePortTuple(2L, 3);
179
180 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
181 System.currentTimeMillis(), null,
182 0, 0);
183 topology.addOrUpdateLink(lt, info);
184
185 // check invariants hold
186 assertNotNull(topology.switchLinks.get(lt.getSrc()));
187 assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
188 assertNotNull(topology.portLinks.get(srcNpt));
189 assertTrue(topology.portLinks.get(srcNpt).contains(lt));
190 assertNotNull(topology.portLinks.get(dstNpt));
191 assertTrue(topology.portLinks.get(dstNpt).contains(lt));
192 assertTrue(topology.links.containsKey(lt));
193 }
194
195 @Test
196 public void testDeleteLinkToSelf() throws Exception {
197 LinkDiscoveryManager topology = getTopology();
198
199 Link lt = new Link(1L, 2, 1L, 3);
200 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
201 NodePortTuple dstNpt = new NodePortTuple(2L, 3);
202
203 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
204 System.currentTimeMillis(), null,
205 0, 0);
206 topology.addOrUpdateLink(lt, info);
207 topology.deleteLinks(Collections.singletonList(lt), "Test to self");
208
209 // check invariants hold
210 assertNull(topology.switchLinks.get(lt.getSrc()));
211 assertNull(topology.switchLinks.get(lt.getDst()));
212 assertNull(topology.portLinks.get(srcNpt));
213 assertNull(topology.portLinks.get(dstNpt));
214 assertTrue(topology.links.isEmpty());
215 }
216
217 @Test
218 public void testRemovedSwitch() {
219 LinkDiscoveryManager topology = getTopology();
220
221 Link lt = new Link(1L, 2, 2L, 1);
222 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
223 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
224 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
225 System.currentTimeMillis(), null,
226 0, 0);
227 topology.addOrUpdateLink(lt, info);
228
229 IOFSwitch sw1 = getMockFloodlightProvider().getSwitches().get(1L);
230 IOFSwitch sw2 = getMockFloodlightProvider().getSwitches().get(2L);
231 // Mock up our expected behavior
232 topology.removedSwitch(sw1);
233 verify(sw1, sw2);
234
235 // check invariants hold
236 assertNull(topology.switchLinks.get(lt.getSrc()));
237 assertNull(topology.switchLinks.get(lt.getDst()));
238 assertNull(topology.portLinks.get(srcNpt));
239 assertNull(topology.portLinks.get(dstNpt));
240 assertTrue(topology.links.isEmpty());
241 }
242
243 @Test
244 public void testRemovedSwitchSelf() {
245 LinkDiscoveryManager topology = getTopology();
246 IOFSwitch sw1 = createMockSwitch(1L);
247 replay(sw1);
248 Link lt = new Link(1L, 2, 1L, 3);
249 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
250 System.currentTimeMillis(), null,
251 0, 0);
252 topology.addOrUpdateLink(lt, info);
253
254 // Mock up our expected behavior
255 topology.removedSwitch(sw1);
256
257 verify(sw1);
258 // check invariants hold
259 assertNull(topology.switchLinks.get(lt.getSrc()));
260 assertNull(topology.portLinks.get(lt.getSrc()));
261 assertNull(topology.portLinks.get(lt.getDst()));
262 assertTrue(topology.links.isEmpty());
263 }
264
265 @Test
266 public void testAddUpdateLinks() throws Exception {
267 LinkDiscoveryManager topology = getTopology();
268
269 Link lt = new Link(1L, 1, 2L, 1);
270 NodePortTuple srcNpt = new NodePortTuple(1L, 1);
271 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
272
273 LinkInfo info;
274
275 info = new LinkInfo(System.currentTimeMillis() - 40000,
276 System.currentTimeMillis() - 40000, null,
277 0, 0);
278 topology.addOrUpdateLink(lt, info);
279
280 // check invariants hold
281 assertNotNull(topology.switchLinks.get(lt.getSrc()));
282 assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
283 assertNotNull(topology.portLinks.get(srcNpt));
284 assertTrue(topology.portLinks.get(srcNpt).contains(lt));
285 assertNotNull(topology.portLinks.get(dstNpt));
286 assertTrue(topology.portLinks.get(dstNpt).contains(lt));
287 assertTrue(topology.links.containsKey(lt));
288 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt) == null ||
289 topology.portBroadcastDomainLinks.get(srcNpt).contains(lt) == false);
290 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt) == null ||
291 topology.portBroadcastDomainLinks.get(dstNpt).contains(lt) == false);
292
293 topology.timeoutLinks();
294
295
296 info = new LinkInfo(System.currentTimeMillis(),/* firstseen */
297 null,/* unicast */
298 System.currentTimeMillis(), 0, 0);
299 topology.addOrUpdateLink(lt, info);
300 assertTrue(topology.links.get(lt).getUnicastValidTime() == null);
301 assertTrue(topology.links.get(lt).getMulticastValidTime() != null);
302 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
303 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
304
305
306 // Add a link info based on info that woudld be obtained from unicast LLDP
307 // Setting the unicast LLDP reception time to be 40 seconds old, so we can use
308 // this to test timeout after this test. Although the info is initialized
309 // with LT_OPENFLOW_LINK, the link property should be changed to LT_NON_OPENFLOW
310 // by the addOrUpdateLink method.
311 info = new LinkInfo(System.currentTimeMillis() - 40000,
312 System.currentTimeMillis() - 40000, null, 0, 0);
313 topology.addOrUpdateLink(lt, info);
314 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt) == null ||
315 topology.portBroadcastDomainLinks.get(srcNpt).contains(lt) == false);
316 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt) == null ||
317 topology.portBroadcastDomainLinks.get(dstNpt).contains(lt) == false);
318
319 // Expect to timeout the unicast Valid Time, but not the multicast Valid time
320 // So the link type should go back to non-openflow link.
321 topology.timeoutLinks();
322 assertTrue(topology.links.get(lt).getUnicastValidTime() == null);
323 assertTrue(topology.links.get(lt).getMulticastValidTime() != null);
324 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
325 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
326
327 // Set the multicastValidTime to be old and see if that also times out.
328 info = new LinkInfo(System.currentTimeMillis() - 40000,
329 null, System.currentTimeMillis() - 40000, 0, 0);
330 topology.addOrUpdateLink(lt, info);
331 topology.timeoutLinks();
332 assertTrue(topology.links.get(lt) == null);
333 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt) == null ||
334 topology.portBroadcastDomainLinks.get(srcNpt).contains(lt) == false);
335 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt) == null ||
336 topology.portBroadcastDomainLinks.get(dstNpt).contains(lt) == false);
337
338
339 // Test again only with multicast LLDP
340 info = new LinkInfo(System.currentTimeMillis() - 40000,
341 null, System.currentTimeMillis() - 40000, 0, 0);
342 topology.addOrUpdateLink(lt, info);
343 assertTrue(topology.links.get(lt).getUnicastValidTime() == null);
344 assertTrue(topology.links.get(lt).getMulticastValidTime() != null);
345 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
346 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
347
348 // Call timeout and check if link is no longer present.
349 topology.timeoutLinks();
350 assertTrue(topology.links.get(lt) == null);
351 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt) == null ||
352 topology.portBroadcastDomainLinks.get(srcNpt).contains(lt) == false);
353 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt) == null ||
354 topology.portBroadcastDomainLinks.get(dstNpt).contains(lt) == false);
355
356 // Start clean and see if loops are also added.
357 lt = new Link(1L, 1, 1L, 2);
358 srcNpt = new NodePortTuple(1L, 1);
359 dstNpt = new NodePortTuple(1L, 2);
360 info = new LinkInfo(System.currentTimeMillis() - 40000,
361 null, System.currentTimeMillis() - 40000, 0, 0);
362 topology.addOrUpdateLink(lt, info);
363 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
364 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
365
366
367 // Start clean and see if loops are also added.
368 lt = new Link(1L, 1, 1L, 3);
369 srcNpt = new NodePortTuple(1L, 1);
370 dstNpt = new NodePortTuple(1L, 3);
371 info = new LinkInfo(System.currentTimeMillis() - 40000,
372 null, System.currentTimeMillis() - 40000, 0, 0);
373 topology.addOrUpdateLink(lt, info);
374 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
375 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
376
377
378 // Start clean and see if loops are also added.
379 lt = new Link(1L, 4, 1L, 5);
380 srcNpt = new NodePortTuple(1L, 4);
381 dstNpt = new NodePortTuple(1L, 5);
382 info = new LinkInfo(System.currentTimeMillis() - 40000,
383 null, System.currentTimeMillis() - 40000, 0, 0);
384 topology.addOrUpdateLink(lt, info);
385 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
386 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
387
388
389 // Start clean and see if loops are also added.
390 lt = new Link(1L, 3, 1L, 5);
391 srcNpt = new NodePortTuple(1L, 3);
392 dstNpt = new NodePortTuple(1L, 5);
393 info = new LinkInfo(System.currentTimeMillis() - 40000,
394 null, System.currentTimeMillis() - 40000, 0, 0);
395 topology.addOrUpdateLink(lt, info);
396 assertTrue(topology.portBroadcastDomainLinks.get(srcNpt).contains(lt));
397 assertTrue(topology.portBroadcastDomainLinks.get(dstNpt).contains(lt));
398 }
399
400 @Test
401 public void testHARoleChange() throws Exception {
402 LinkDiscoveryManager topology = getTopology();
403 IOFSwitch sw1 = createMockSwitch(1L);
404 IOFSwitch sw2 = createMockSwitch(2L);
405 replay(sw1, sw2);
406 Link lt = new Link(1L, 2, 2L, 1);
407 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
408 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
409 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
410 System.currentTimeMillis(), null,
411 0, 0);
412 topology.addOrUpdateLink(lt, info);
413
414 // check invariants hold
415 assertNotNull(topology.switchLinks.get(lt.getSrc()));
416 assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
417 assertNotNull(topology.portLinks.get(srcNpt));
418 assertTrue(topology.portLinks.get(srcNpt).contains(lt));
419 assertNotNull(topology.portLinks.get(dstNpt));
420 assertTrue(topology.portLinks.get(dstNpt).contains(lt));
421 assertTrue(topology.links.containsKey(lt));
422
423 // check that it clears from memory
424 getMockFloodlightProvider().dispatchRoleChanged(null, Role.SLAVE);
425 assertTrue(topology.switchLinks.isEmpty());
426 getMockFloodlightProvider().dispatchRoleChanged(Role.SLAVE, Role.MASTER);
427 // check that lldps were sent
428 assertTrue(ldm.isSendLLDPsCalled);
429 assertTrue(ldm.isClearLinksCalled);
430 ldm.reset();
431 }
432}