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