blob: cbbbcfc0f488d0e3ff138b6e38364650ff1e99fd [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
Ray Milkey269ffb92014-04-03 14:43:30 -07002 * 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 **/
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080017
Jonathan Hart284e70f2014-07-05 12:32:51 -070018package net.onrc.onos.core.linkdiscovery;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080019
Sho SHIMIZU107344e2014-08-13 16:11:53 -070020import static org.easymock.EasyMock.anyLong;
21import static org.easymock.EasyMock.anyObject;
22import static org.easymock.EasyMock.anyShort;
23import static org.easymock.EasyMock.createMock;
Jonathan Hart2fa28062013-11-25 20:16:28 -080024import static org.easymock.EasyMock.createNiceMock;
25import static org.easymock.EasyMock.expect;
Sho SHIMIZU107344e2014-08-13 16:11:53 -070026import static org.easymock.EasyMock.expectLastCall;
Jonathan Hart2fa28062013-11-25 20:16:28 -080027import static org.easymock.EasyMock.replay;
Sho SHIMIZU107344e2014-08-13 16:11:53 -070028import static org.easymock.EasyMock.reportMatcher;
Jonathan Hart2fa28062013-11-25 20:16:28 -080029import static org.easymock.EasyMock.verify;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080030
srikanth9f383342014-06-12 11:49:00 -070031import java.io.IOException;
Jonathan Hart2fa28062013-11-25 20:16:28 -080032import java.util.Collections;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080033import java.util.HashMap;
34import java.util.Map;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070035import java.util.Set;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080036
srikanth9f383342014-06-12 11:49:00 -070037import net.floodlightcontroller.core.FloodlightContext;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080038import net.floodlightcontroller.core.IFloodlightProviderService;
Jonathan Hart0f383542014-07-09 11:38:03 -070039import net.floodlightcontroller.core.IListener.Command;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080040import net.floodlightcontroller.core.IOFSwitch;
41import net.floodlightcontroller.core.module.FloodlightModuleContext;
42import net.floodlightcontroller.core.test.MockThreadPoolService;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080043import net.floodlightcontroller.restserver.IRestApiService;
44import net.floodlightcontroller.restserver.RestApiServer;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080045import net.floodlightcontroller.test.FloodlightTestCase;
46import net.floodlightcontroller.threadpool.IThreadPoolService;
Jonathan Hart0f383542014-07-09 11:38:03 -070047import net.onrc.onos.core.packet.Ethernet;
48import net.onrc.onos.core.packet.OnosLldp;
Jonathan Hartcd1ab172014-07-03 14:59:48 -070049import net.onrc.onos.core.registry.IControllerRegistryService;
Jonathan Hart2fa28062013-11-25 20:16:28 -080050
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070051import org.easymock.IArgumentMatcher;
Jonathan Hart2fa28062013-11-25 20:16:28 -080052import org.junit.Before;
53import org.junit.Test;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070054import org.projectfloodlight.openflow.protocol.OFFactories;
55import org.projectfloodlight.openflow.protocol.OFFactory;
56import org.projectfloodlight.openflow.protocol.OFPacketIn;
57import org.projectfloodlight.openflow.protocol.OFPacketOut;
58import org.projectfloodlight.openflow.protocol.OFPortConfig;
59import org.projectfloodlight.openflow.protocol.OFPortDesc;
60import org.projectfloodlight.openflow.protocol.OFPortReason;
61import org.projectfloodlight.openflow.protocol.OFPortState;
62import org.projectfloodlight.openflow.protocol.OFPortStatus;
63import org.projectfloodlight.openflow.protocol.OFVersion;
64import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
65import org.projectfloodlight.openflow.types.MacAddress;
66import org.projectfloodlight.openflow.types.OFPort;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080067
Yuta HIGUCHIaa132f52014-06-26 10:18:39 -070068// CHECKSTYLE IGNORE WriteTag FOR NEXT 2 LINES
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080069/**
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080070 * @author David Erickson (daviderickson@cs.stanford.edu)
71 */
72public class LinkDiscoveryManagerTest extends FloodlightTestCase {
73
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070074 private LinkDiscoveryManager ldm;
Ray Milkey269ffb92014-04-03 14:43:30 -070075
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070076 private static final Set<OFPortState> EMPTY_PORT_STATE =
77 Collections.<OFPortState>emptySet();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080078
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070079 // Arbitrary MAC address that we can feed in to our mock objects. This
80 // value is never actually checked during the tests so it doesn't matter if
81 // all ports have the same MAC address.
82 private static final byte[] DEFAULT_MAC_ADDRESS =
83 new byte[] {0x0, 0x0, 0x0, 0x0, 0x0, 0x1};
84
85 private OFFactory factory10 = OFFactories.getFactory(OFVersion.OF_10);
86
87 /**
88 * EasyMock matcher to verify the value of the output port of a packet out.
89 * This is used to verify that the packet out messages generated by
90 * LinkDiscoveryManager contain the correct output port.
91 *
92 */
93 private static final class PacketOutPortMatcher implements IArgumentMatcher {
94 private final int portNumber;
95
96 public PacketOutPortMatcher(int portNumber) {
97 this.portNumber = portNumber;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080098 }
99
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700100 @Override
101 public void appendTo(StringBuffer strBuffer) {
102 strBuffer.append("PacketOutPortMatcher failed to verify output port");
103 }
104
105 @Override
106 public boolean matches(Object object) {
107 if (!(object instanceof OFPacketOut)) {
108 return false;
109 }
110
111 OFPacketOut po = (OFPacketOut) object;
112
113 if (po.getActions().size() != 1
114 || !(po.getActions().get(0) instanceof OFActionOutput)) {
115 return false;
116 }
117
118 OFActionOutput action = (OFActionOutput) po.getActions().get(0);
119
120 return action.getPort().getPortNumber() == portNumber;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800121 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800122 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700123
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700124 /**
125 * Matcher method to match a given output port against a packet out message
126 * passed as an argument to a mock switch.
127 *
128 * @param outPort the output port to check in the packet out
129 * @return anything of type OFPacketOut
130 */
131 private static OFPacketOut matchOutPort(int outPort) {
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700132 reportMatcher(new PacketOutPortMatcher(outPort));
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700133 return null;
134 }
135
136 private LinkDiscoveryManager getLinkDiscoveryManager() {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800137 return ldm;
138 }
139
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700140 private IOFSwitch createMockSwitch(Long id) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800141 IOFSwitch mockSwitch = createNiceMock(IOFSwitch.class);
142 expect(mockSwitch.getId()).andReturn(id).anyTimes();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700143 expect(mockSwitch.portEnabled(anyShort())).andReturn(true).anyTimes();
Jonathan Harta213bce2014-08-11 15:44:07 -0700144 expect(mockSwitch.getFactory()).andReturn(factory10).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800145 return mockSwitch;
146 }
147
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700148 private OFPortDesc createMockPort(short portNumber) {
149 return createMockPortWithState(portNumber,
150 Collections.<OFPortState>emptySet());
151 }
152
153 private OFPortDesc createMockPortWithState(short portNumber,
154 Set<OFPortState> state) {
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700155 OFPort ofPort = createMock(OFPort.class);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700156 expect(ofPort.getShortPortNumber()).andReturn(portNumber).anyTimes();
157
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700158 OFPortDesc ofPortDesc = createMock(OFPortDesc.class);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700159 expect(ofPortDesc.getPortNo()).andReturn(ofPort).anyTimes();
160 expect(ofPortDesc.getHwAddr()).andReturn(
161 MacAddress.of(DEFAULT_MAC_ADDRESS)).anyTimes();
162 expect(ofPortDesc.getConfig()).
163 andReturn(Collections.<OFPortConfig>emptySet()).anyTimes();
164 expect(ofPortDesc.getState()).andReturn(state).anyTimes();
165
166 replay(ofPort);
167 replay(ofPortDesc);
168
169 return ofPortDesc;
170 }
171
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700172 @Override
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800173 @Before
174 public void setUp() throws Exception {
175 super.setUp();
176 FloodlightModuleContext cntx = new FloodlightModuleContext();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700177 ldm = new LinkDiscoveryManager();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800178 MockThreadPoolService tp = new MockThreadPoolService();
179 RestApiServer restApi = new RestApiServer();
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700180 IControllerRegistryService registry =
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700181 createMock(IControllerRegistryService.class);
182 expect(registry.hasControl(anyLong())).andReturn(true).anyTimes();
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700183 replay(registry);
184 cntx.addService(IControllerRegistryService.class, registry);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800185 cntx.addService(IRestApiService.class, restApi);
186 cntx.addService(IThreadPoolService.class, tp);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800187 cntx.addService(ILinkDiscoveryService.class, ldm);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800188 cntx.addService(IFloodlightProviderService.class, getMockFloodlightProvider());
189 restApi.init(cntx);
190 tp.init(cntx);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800191 ldm.init(cntx);
192 restApi.startUp(cntx);
193 tp.startUp(cntx);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800194 ldm.startUp(cntx);
195
196 IOFSwitch sw1 = createMockSwitch(1L);
197 IOFSwitch sw2 = createMockSwitch(2L);
198 Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>();
199 switches.put(1L, sw1);
200 switches.put(2L, sw2);
201 getMockFloodlightProvider().setSwitches(switches);
202 replay(sw1, sw2);
203 }
204
205 @Test
206 public void testAddOrUpdateLink() throws Exception {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700207 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800208
209 Link lt = new Link(1L, 2, 2L, 1);
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700210 long firstSeenTime = System.currentTimeMillis();
211 LinkInfo info = new LinkInfo(firstSeenTime,
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700212 System.currentTimeMillis(), EMPTY_PORT_STATE,
213 EMPTY_PORT_STATE);
214 linkDiscovery.addOrUpdateLink(lt, info);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800215
216 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
217 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
218
219 // check invariants hold
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700220 assertNotNull(linkDiscovery.switchLinks.get(lt.getSrc()));
221 assertTrue(linkDiscovery.switchLinks.get(lt.getSrc()).contains(lt));
222 assertNotNull(linkDiscovery.portLinks.get(srcNpt));
223 assertTrue(linkDiscovery.portLinks.get(srcNpt).contains(lt));
224 assertNotNull(linkDiscovery.portLinks.get(dstNpt));
225 assertTrue(linkDiscovery.portLinks.get(dstNpt).contains(lt));
226 assertTrue(linkDiscovery.links.containsKey(lt));
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700227
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700228 LinkInfo infoToVerify = linkDiscovery.links.get(lt);
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700229 assertEquals(firstSeenTime, infoToVerify.getFirstSeenTime());
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700230 assertEquals(EMPTY_PORT_STATE, infoToVerify.getSrcPortState());
231 assertEquals(EMPTY_PORT_STATE, infoToVerify.getDstPortState());
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700232
233 // Arbitrary new port states to verify that the port state is updated
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700234 final Set<OFPortState> newSrcPortState =
235 Collections.singleton(OFPortState.STP_BLOCK);
236 final Set<OFPortState> newDstPortState =
237 Collections.singleton(OFPortState.LINK_DOWN);
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700238
239 // Update the last received probe timestamp and the port states
240 LinkInfo infoWithStateChange = new LinkInfo(System.currentTimeMillis(),
241 System.currentTimeMillis(), newSrcPortState, newDstPortState);
242
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700243 linkDiscovery.addOrUpdateLink(lt, infoWithStateChange);
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700244
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700245 assertNotNull(linkDiscovery.links.get(lt));
246 infoToVerify = linkDiscovery.links.get(lt);
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700247 // First seen time should be the original time, not the second update time
248 assertEquals(firstSeenTime, infoToVerify.getFirstSeenTime());
249 // Both port states should have been updated
250 assertEquals(newSrcPortState, infoToVerify.getSrcPortState());
251 assertEquals(newDstPortState, infoToVerify.getDstPortState());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800252 }
253
254 @Test
255 public void testDeleteLink() throws Exception {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700256 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800257
258 Link lt = new Link(1L, 2, 2L, 1);
259 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700260 System.currentTimeMillis(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
261 linkDiscovery.addOrUpdateLink(lt, info);
262 linkDiscovery.deleteLinks(Collections.singletonList(lt));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800263
264 // check invariants hold
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700265 assertNull(linkDiscovery.switchLinks.get(lt.getSrc()));
266 assertNull(linkDiscovery.switchLinks.get(lt.getDst()));
267 assertNull(linkDiscovery.portLinks.get(lt.getSrc()));
268 assertNull(linkDiscovery.portLinks.get(lt.getDst()));
269 assertTrue(linkDiscovery.links.isEmpty());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800270 }
271
272 @Test
273 public void testAddOrUpdateLinkToSelf() throws Exception {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700274 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800275
276 Link lt = new Link(1L, 2, 2L, 3);
277 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
278 NodePortTuple dstNpt = new NodePortTuple(2L, 3);
279
280 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700281 System.currentTimeMillis(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
282 linkDiscovery.addOrUpdateLink(lt, info);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800283
284 // check invariants hold
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700285 assertNotNull(linkDiscovery.switchLinks.get(lt.getSrc()));
286 assertTrue(linkDiscovery.switchLinks.get(lt.getSrc()).contains(lt));
287 assertNotNull(linkDiscovery.portLinks.get(srcNpt));
288 assertTrue(linkDiscovery.portLinks.get(srcNpt).contains(lt));
289 assertNotNull(linkDiscovery.portLinks.get(dstNpt));
290 assertTrue(linkDiscovery.portLinks.get(dstNpt).contains(lt));
291 assertTrue(linkDiscovery.links.containsKey(lt));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800292 }
293
294 @Test
295 public void testDeleteLinkToSelf() throws Exception {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700296 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800297
298 Link lt = new Link(1L, 2, 1L, 3);
299 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
300 NodePortTuple dstNpt = new NodePortTuple(2L, 3);
301
302 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700303 System.currentTimeMillis(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
304 linkDiscovery.addOrUpdateLink(lt, info);
305 linkDiscovery.deleteLinks(Collections.singletonList(lt));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800306
307 // check invariants hold
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700308 assertNull(linkDiscovery.switchLinks.get(lt.getSrc()));
309 assertNull(linkDiscovery.switchLinks.get(lt.getDst()));
310 assertNull(linkDiscovery.portLinks.get(srcNpt));
311 assertNull(linkDiscovery.portLinks.get(dstNpt));
312 assertTrue(linkDiscovery.links.isEmpty());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800313 }
314
315 @Test
316 public void testRemovedSwitch() {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700317 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800318
319 Link lt = new Link(1L, 2, 2L, 1);
320 NodePortTuple srcNpt = new NodePortTuple(1L, 2);
321 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
322 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700323 System.currentTimeMillis(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
324 linkDiscovery.addOrUpdateLink(lt, info);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800325
326 IOFSwitch sw1 = getMockFloodlightProvider().getSwitches().get(1L);
327 IOFSwitch sw2 = getMockFloodlightProvider().getSwitches().get(2L);
328 // Mock up our expected behavior
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700329 linkDiscovery.switchDisconnected(sw1.getId());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800330 verify(sw1, sw2);
331
332 // check invariants hold
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700333 assertNull(linkDiscovery.switchLinks.get(lt.getSrc()));
334 assertNull(linkDiscovery.switchLinks.get(lt.getDst()));
335 assertNull(linkDiscovery.portLinks.get(srcNpt));
336 assertNull(linkDiscovery.portLinks.get(dstNpt));
337 assertTrue(linkDiscovery.links.isEmpty());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800338 }
339
340 @Test
341 public void testRemovedSwitchSelf() {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700342 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800343 IOFSwitch sw1 = createMockSwitch(1L);
344 replay(sw1);
345 Link lt = new Link(1L, 2, 1L, 3);
346 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700347 System.currentTimeMillis(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
348 linkDiscovery.addOrUpdateLink(lt, info);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800349
350 // Mock up our expected behavior
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700351 linkDiscovery.switchDisconnected(sw1.getId());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800352
353 verify(sw1);
354 // check invariants hold
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700355 assertNull(linkDiscovery.switchLinks.get(lt.getSrc()));
356 assertNull(linkDiscovery.portLinks.get(lt.getSrc()));
357 assertNull(linkDiscovery.portLinks.get(lt.getDst()));
358 assertTrue(linkDiscovery.links.isEmpty());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800359 }
360
361 @Test
362 public void testAddUpdateLinks() throws Exception {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700363 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800364
365 Link lt = new Link(1L, 1, 2L, 1);
366 NodePortTuple srcNpt = new NodePortTuple(1L, 1);
367 NodePortTuple dstNpt = new NodePortTuple(2L, 1);
Ray Milkey269ffb92014-04-03 14:43:30 -0700368
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800369 LinkInfo info;
370
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700371 // Setting the last LLDP reception time to be 40 seconds old, so we
372 // can use this to test that an old link times out correctly
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800373 info = new LinkInfo(System.currentTimeMillis() - 40000,
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700374 System.currentTimeMillis() - 40000,
375 EMPTY_PORT_STATE, EMPTY_PORT_STATE);
376 linkDiscovery.addOrUpdateLink(lt, info);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800377
378 // check invariants hold
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700379 assertNotNull(linkDiscovery.switchLinks.get(lt.getSrc()));
380 assertTrue(linkDiscovery.switchLinks.get(lt.getSrc()).contains(lt));
381 assertNotNull(linkDiscovery.portLinks.get(srcNpt));
382 assertTrue(linkDiscovery.portLinks.get(srcNpt).contains(lt));
383 assertNotNull(linkDiscovery.portLinks.get(dstNpt));
384 assertTrue(linkDiscovery.portLinks.get(dstNpt).contains(lt));
385 assertTrue(linkDiscovery.links.containsKey(lt));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800386
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700387 linkDiscovery.timeOutLinks();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800388
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700389 // Setting the last LLDP reception time to be 40 seconds old, so we
390 // can use this to test that an old link times out correctly
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800391 info = new LinkInfo(System.currentTimeMillis() - 40000,
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700392 System.currentTimeMillis() - 40000,
393 EMPTY_PORT_STATE, EMPTY_PORT_STATE);
394 linkDiscovery.addOrUpdateLink(lt, info);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800395
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700396 // Expect to timeout the unicast Valid Time, so the link should disappear
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700397 linkDiscovery.timeOutLinks();
398 assertTrue(linkDiscovery.links.get(lt) == null);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800399 }
srikanth9f383342014-06-12 11:49:00 -0700400
401 /**
402 * This test case verifies that LinkDiscoveryManager.sendDiscoveryMessage()
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700403 * performs "write" operation on the specified IOFSwitch object
404 * with a LLDP packet.
405 *
srikanth9f383342014-06-12 11:49:00 -0700406 * @throws IOException
407 */
408 @Test
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700409 public void testSendDiscoveryMessage() throws IOException {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700410 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
srikanth9f383342014-06-12 11:49:00 -0700411
412 // Mock up our expected behavior
413 IOFSwitch swTest = createMockSwitch(3L);
414 getMockFloodlightProvider().getSwitches().put(3L, swTest);
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700415
srikanth9f383342014-06-12 11:49:00 -0700416 short portNum = 1;
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700417
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700418 OFPortDesc ofPortDesc = createMockPort(portNum);
419
420 expect(swTest.getPort(portNum)).andReturn(ofPortDesc).atLeastOnce();
421 swTest.write(matchOutPort(portNum),
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700422 anyObject(FloodlightContext.class));
423 expectLastCall().times(1);
srikanth9f383342014-06-12 11:49:00 -0700424 swTest.flush();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700425 expectLastCall().once();
srikanth9f383342014-06-12 11:49:00 -0700426 replay(swTest);
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700427
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700428 linkDiscovery.sendDiscoveryMessage(3L, portNum, false);
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700429
srikanth9f383342014-06-12 11:49:00 -0700430 verify(swTest);
431 }
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700432
433 @Test
434 public void testHandlePortStatusForNewPort() throws IOException {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700435 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700436
437 long dpid = 3L;
438 IOFSwitch sw = createMockSwitch(dpid);
439 getMockFloodlightProvider().getSwitches().put(dpid, sw);
440
441 short portNum = 1;
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700442
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700443 OFPortDesc ofPortDesc = createMockPort(portNum);
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700444
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700445 OFPortStatus portStatus = factory10.buildPortStatus()
446 .setDesc(ofPortDesc)
447 .setReason(OFPortReason.ADD)
448 .build();
449
450 expect(sw.getPort(portNum)).andReturn(ofPortDesc).once();
451
452 sw.write(matchOutPort(portNum),
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700453 anyObject(FloodlightContext.class));
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700454 sw.flush();
455
456 replay(sw);
457
458 linkDiscovery.handlePortStatus(sw, portStatus);
459
460 verify(sw);
461 }
462
463 @Test
464 public void testHandlePortStatusForExistingPort() {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700465 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700466
467 // Add a link that we can update later during the test
468 Link lt = new Link(1L, 1, 2L, 1);
469 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700470 System.currentTimeMillis(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700471 linkDiscovery.addOrUpdateLink(lt, info);
472
473 short portNum = 1;
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700474
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700475 // Arbitrary states to test state changes
476 Set<OFPortState> srcPortState =
477 Collections.singleton(OFPortState.STP_FORWARD);
478 Set<OFPortState> dstPortState =
479 Collections.singleton(OFPortState.STP_LISTEN);
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700480
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700481 OFPortDesc srcPortDesc = createMockPortWithState(portNum, srcPortState);
482 OFPortDesc dstPortDesc = createMockPortWithState(portNum, dstPortState);
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700483
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700484 OFPortStatus srcPortStatus = factory10.buildPortStatus()
485 .setDesc(srcPortDesc)
486 .setReason(OFPortReason.MODIFY)
487 .build();
488
489 OFPortStatus dstPortStatus = factory10.buildPortStatus()
490 .setDesc(dstPortDesc)
491 .setReason(OFPortReason.MODIFY)
492 .build();
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700493
494 linkDiscovery.handlePortStatus(
495 getMockFloodlightProvider().getSwitches().get(1L), srcPortStatus);
496
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700497 LinkInfo newInfo = linkDiscovery.links.get(lt);
498 assertEquals(srcPortState, newInfo.getSrcPortState());
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700499 assertEquals(EMPTY_PORT_STATE, newInfo.getDstPortState());
Jonathan Hartcd1ab172014-07-03 14:59:48 -0700500
501 linkDiscovery.handlePortStatus(
502 getMockFloodlightProvider().getSwitches().get(2L), dstPortStatus);
503
504 newInfo = linkDiscovery.links.get(lt);
505 assertEquals(srcPortState, newInfo.getSrcPortState());
506 assertEquals(dstPortState, newInfo.getDstPortState());
507 }
Jonathan Hart0f383542014-07-09 11:38:03 -0700508
509 @Test
510 public void testHandlePortStatusForDeletePort() {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700511 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Jonathan Hart0f383542014-07-09 11:38:03 -0700512
513 // Add a link that we can delete later during the test
514 Link lt = new Link(1L, 1, 2L, 2);
515 LinkInfo info = new LinkInfo(System.currentTimeMillis(),
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700516 System.currentTimeMillis(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
Jonathan Hart0f383542014-07-09 11:38:03 -0700517 linkDiscovery.addOrUpdateLink(lt, info);
518
519 short portNum = 1;
Jonathan Hart0f383542014-07-09 11:38:03 -0700520
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700521 OFPortDesc srcPortDesc = createMockPort(portNum);
522 OFPortStatus srcPortStatus = factory10.buildPortStatus()
523 .setDesc(srcPortDesc)
524 .setReason(OFPortReason.DELETE)
525 .build();
Jonathan Hart0f383542014-07-09 11:38:03 -0700526
527 assertNotNull(linkDiscovery.getLinks().get(lt));
528
529 // Send a delete port status for the source port, which should result
530 // in the link being deleted
531 linkDiscovery.handlePortStatus(
532 getMockFloodlightProvider().getSwitches().get(1L), srcPortStatus);
533
534 assertNull(linkDiscovery.getLinks().get(lt));
535 }
536
537 @Test
538 public void testReceive() {
Jonathan Hart0f383542014-07-09 11:38:03 -0700539 OnosLldp lldpPacket = new OnosLldp();
540 lldpPacket.setPort((short) 1);
541 lldpPacket.setSwitch(1L);
542 lldpPacket.setReverse(false);
543
544 Ethernet ethPacket = new Ethernet();
545 ethPacket.setEtherType(Ethernet.TYPE_LLDP);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700546 ethPacket.setSourceMACAddress(DEFAULT_MAC_ADDRESS);
Jonathan Hart0f383542014-07-09 11:38:03 -0700547 ethPacket.setDestinationMACAddress(
548 LinkDiscoveryManager.LLDP_STANDARD_DST_MAC_STRING);
549 ethPacket.setPayload(lldpPacket);
550 ethPacket.setPad(true);
551
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700552 OFPacketIn pi = createMock(OFPacketIn.class);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700553 expect(pi.getData()).andReturn(ethPacket.serialize()).anyTimes();
554 replay(pi);
Jonathan Hart0f383542014-07-09 11:38:03 -0700555
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700556 LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();
Jonathan Hart0f383542014-07-09 11:38:03 -0700557
558 Link expectedLink = new Link(1L, 1, 2L, 2);
559
560 assertNull(linkDiscovery.links.get(expectedLink));
561
562 // Sending in the LLDP packet should cause the link to be created
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700563 Command command = linkDiscovery.handleLldp(lldpPacket, 2L, pi, (short) 2);
Jonathan Hart0f383542014-07-09 11:38:03 -0700564
565 assertEquals(Command.STOP, command);
566 assertNotNull(linkDiscovery.links.get(expectedLink));
567 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800568}