blob: a0dc06ba503b63a68e2cb75fde31e445cc0eadae [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.core.internal;
19
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070020import static org.easymock.EasyMock.anyObject;
21import static org.easymock.EasyMock.capture;
22import static org.easymock.EasyMock.createMock;
23import static org.easymock.EasyMock.createNiceMock;
24import static org.easymock.EasyMock.eq;
25import static org.easymock.EasyMock.expect;
26import static org.easymock.EasyMock.expectLastCall;
27import static org.easymock.EasyMock.isA;
28import static org.easymock.EasyMock.replay;
29import static org.easymock.EasyMock.reset;
30import static org.easymock.EasyMock.same;
31import static org.easymock.EasyMock.verify;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080032
33import java.util.ArrayList;
34import java.util.Collection;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080035import java.util.List;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080036import java.util.concurrent.ConcurrentHashMap;
37import java.util.concurrent.Future;
38import java.util.concurrent.TimeUnit;
39
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080040import net.floodlightcontroller.core.FloodlightContext;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070041import net.floodlightcontroller.core.FloodlightProvider;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080042import net.floodlightcontroller.core.IFloodlightProviderService;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080043import net.floodlightcontroller.core.IFloodlightProviderService.Role;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080044import net.floodlightcontroller.core.IListener.Command;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070045import net.floodlightcontroller.core.IOFMessageListener;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080046import net.floodlightcontroller.core.IOFSwitch;
47import net.floodlightcontroller.core.IOFSwitchListener;
Pankaj Berde6e421732013-08-14 15:17:52 -070048import net.floodlightcontroller.core.IUpdate;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080049import net.floodlightcontroller.core.internal.Controller.SwitchUpdate;
50import net.floodlightcontroller.core.internal.Controller.SwitchUpdateType;
51import net.floodlightcontroller.core.internal.OFChannelState.HandshakeState;
52import net.floodlightcontroller.core.module.FloodlightModuleContext;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080053import net.floodlightcontroller.core.test.MockThreadPoolService;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080054import net.floodlightcontroller.restserver.IRestApiService;
55import net.floodlightcontroller.restserver.RestApiServer;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080056import net.floodlightcontroller.test.FloodlightTestCase;
57import net.floodlightcontroller.threadpool.IThreadPoolService;
HIGUCHI Yuta36cf0762013-06-14 14:25:38 -070058import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
Jonathan Hart220b8292013-12-07 19:25:11 -080059import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
60import net.onrc.onos.ofcontroller.linkdiscovery.internal.LinkDiscoveryManager;
Jonathan Hart96892d12014-03-26 20:21:29 -070061import net.onrc.onos.packet.ARP;
62import net.onrc.onos.packet.Ethernet;
63import net.onrc.onos.packet.IPacket;
64import net.onrc.onos.packet.IPv4;
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -070065import net.onrc.onos.registry.controller.IControllerRegistryService;
66import net.onrc.onos.registry.controller.StandaloneRegistry;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080067
68import org.easymock.Capture;
69import org.easymock.EasyMock;
70import org.jboss.netty.channel.Channel;
71import org.junit.Test;
72import org.openflow.protocol.OFError;
73import org.openflow.protocol.OFError.OFBadRequestCode;
74import org.openflow.protocol.OFError.OFErrorType;
75import org.openflow.protocol.OFFeaturesReply;
76import org.openflow.protocol.OFPacketIn;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070077import org.openflow.protocol.OFPacketIn.OFPacketInReason;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080078import org.openflow.protocol.OFPhysicalPort;
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -070079import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
80import org.openflow.protocol.OFPhysicalPort.OFPortState;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080081import org.openflow.protocol.OFPortStatus;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070082import org.openflow.protocol.OFPortStatus.OFPortReason;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080083import org.openflow.protocol.OFStatisticsReply;
84import org.openflow.protocol.OFType;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080085import org.openflow.protocol.OFVendor;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080086import org.openflow.protocol.factory.BasicFactory;
87import org.openflow.protocol.statistics.OFFlowStatisticsReply;
88import org.openflow.protocol.statistics.OFStatistics;
89import org.openflow.protocol.statistics.OFStatisticsType;
90import org.openflow.util.HexString;
91import org.openflow.vendor.nicira.OFNiciraVendorData;
92import org.openflow.vendor.nicira.OFRoleReplyVendorData;
93
94/**
95 *
96 * @author David Erickson (daviderickson@cs.stanford.edu)
97 */
98public class ControllerTest extends FloodlightTestCase {
99
100 private Controller controller;
101 private MockThreadPoolService tp;
102
103 @Override
104 public void setUp() throws Exception {
105 super.setUp();
106 FloodlightModuleContext fmc = new FloodlightModuleContext();
107
108 FloodlightProvider cm = new FloodlightProvider();
109 controller = (Controller)cm.getServiceImpls().get(IFloodlightProviderService.class);
110 fmc.addService(IFloodlightProviderService.class, controller);
111
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800112 RestApiServer restApi = new RestApiServer();
113 fmc.addService(IRestApiService.class, restApi);
mininet73e7fb72013-12-03 14:25:53 -0800114
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800115 tp = new MockThreadPoolService();
116 fmc.addService(IThreadPoolService.class, tp);
117
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700118 // Following added by ONOS
119 // TODO replace with mock if further testing is needed.
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700120 StandaloneRegistry sr = new StandaloneRegistry();
121 fmc.addService(IControllerRegistryService.class, sr );
Jonathan Hart220b8292013-12-07 19:25:11 -0800122 LinkDiscoveryManager linkDiscovery = new LinkDiscoveryManager();
123 fmc.addService(ILinkDiscoveryService.class, linkDiscovery);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700124
125
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800126 restApi.init(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800127 cm.init(fmc);
128 tp.init(fmc);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700129 sr.init(fmc);
Jonathan Hart220b8292013-12-07 19:25:11 -0800130 linkDiscovery.init(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800131 restApi.startUp(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800132 cm.startUp(fmc);
133 tp.startUp(fmc);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700134 sr.startUp(fmc);
Jonathan Hart220b8292013-12-07 19:25:11 -0800135 linkDiscovery.startUp(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800136 }
137
138 public Controller getController() {
139 return controller;
140 }
141
142 protected OFStatisticsReply getStatisticsReply(int transactionId,
143 int count, boolean moreReplies) {
144 OFStatisticsReply sr = new OFStatisticsReply();
145 sr.setXid(transactionId);
146 sr.setStatisticType(OFStatisticsType.FLOW);
147 List<OFStatistics> statistics = new ArrayList<OFStatistics>();
148 for (int i = 0; i < count; ++i) {
149 statistics.add(new OFFlowStatisticsReply());
150 }
151 sr.setStatistics(statistics);
152 if (moreReplies)
153 sr.setFlags((short) 1);
154 return sr;
155 }
156
157 /* Set the mock expectations for sw when sw is passed to addSwitch */
158 protected void setupSwitchForAddSwitch(IOFSwitch sw, long dpid) {
159 String dpidString = HexString.toHexString(dpid);
160
161 expect(sw.getId()).andReturn(dpid).anyTimes();
162 expect(sw.getStringId()).andReturn(dpidString).anyTimes();
Jonathan Hart2fa28062013-11-25 20:16:28 -0800163
164 //Now we don't write to storage these methods aren't called
165 //expect(sw.getConnectedSince()).andReturn(new Date());
166 //Channel channel = createMock(Channel.class);
167 //expect(sw.getChannel()).andReturn(channel);
168 //expect(channel.getRemoteAddress()).andReturn(null);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800169
170 expect(sw.getCapabilities()).andReturn(0).anyTimes();
171 expect(sw.getBuffers()).andReturn(0).anyTimes();
172 expect(sw.getTables()).andReturn((byte)0).anyTimes();
173 expect(sw.getActions()).andReturn(0).anyTimes();
174 expect(sw.getPorts()).andReturn(new ArrayList<OFPhysicalPort>()).anyTimes();
175 }
176
177 /**
178 * Run the controller's main loop so that updates are processed
179 */
180 protected class ControllerRunThread extends Thread {
181 public void run() {
182 controller.openFlowPort = 0; // Don't listen
183 controller.run();
184 }
185 }
186
187 /**
188 * Verify that a listener that throws an exception halts further
189 * execution, and verify that the Commands STOP and CONTINUE are honored.
190 * @throws Exception
191 */
192 @Test
193 public void testHandleMessages() throws Exception {
194 Controller controller = getController();
195 controller.removeOFMessageListeners(OFType.PACKET_IN);
196
197 IOFSwitch sw = createMock(IOFSwitch.class);
198 expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
199
200 // Build our test packet
201 IPacket testPacket = new Ethernet()
202 .setSourceMACAddress("00:44:33:22:11:00")
203 .setDestinationMACAddress("00:11:22:33:44:55")
204 .setEtherType(Ethernet.TYPE_ARP)
205 .setPayload(
206 new ARP()
207 .setHardwareType(ARP.HW_TYPE_ETHERNET)
208 .setProtocolType(ARP.PROTO_TYPE_IP)
209 .setHardwareAddressLength((byte) 6)
210 .setProtocolAddressLength((byte) 4)
211 .setOpCode(ARP.OP_REPLY)
212 .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:00"))
213 .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1"))
214 .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55"))
215 .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
216 byte[] testPacketSerialized = testPacket.serialize();
217
218 // Build the PacketIn
219 OFPacketIn pi = ((OFPacketIn) new BasicFactory().getMessage(OFType.PACKET_IN))
220 .setBufferId(-1)
221 .setInPort((short) 1)
222 .setPacketData(testPacketSerialized)
223 .setReason(OFPacketInReason.NO_MATCH)
224 .setTotalLength((short) testPacketSerialized.length);
225
226 IOFMessageListener test1 = createMock(IOFMessageListener.class);
227 expect(test1.getName()).andReturn("test1").anyTimes();
228 expect(test1.isCallbackOrderingPrereq((OFType)anyObject(), (String)anyObject())).andReturn(false).anyTimes();
229 expect(test1.isCallbackOrderingPostreq((OFType)anyObject(), (String)anyObject())).andReturn(false).anyTimes();
230 expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andThrow(new RuntimeException("This is NOT an error! We are testing exception catching."));
231 IOFMessageListener test2 = createMock(IOFMessageListener.class);
232 expect(test2.getName()).andReturn("test2").anyTimes();
233 expect(test2.isCallbackOrderingPrereq((OFType)anyObject(), (String)anyObject())).andReturn(false).anyTimes();
234 expect(test2.isCallbackOrderingPostreq((OFType)anyObject(), (String)anyObject())).andReturn(false).anyTimes();
235 // expect no calls to test2.receive() since test1.receive() threw an exception
236
237 replay(test1, test2, sw);
238 controller.addOFMessageListener(OFType.PACKET_IN, test1);
239 controller.addOFMessageListener(OFType.PACKET_IN, test2);
240 try {
241 controller.handleMessage(sw, pi, null);
242 } catch (RuntimeException e) {
243 assertEquals(e.getMessage().startsWith("This is NOT an error!"), true);
244 }
245 verify(test1, test2, sw);
246
247 // verify STOP works
248 reset(test1, test2, sw);
249 expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andReturn(Command.STOP);
250 //expect(test1.getId()).andReturn(0).anyTimes();
251 expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
252 replay(test1, test2, sw);
253 controller.handleMessage(sw, pi, null);
254 verify(test1, test2, sw);
255 }
256
257 public class FutureFetcher<E> implements Runnable {
258 public E value;
259 public Future<E> future;
260
261 public FutureFetcher(Future<E> future) {
262 this.future = future;
263 }
264
265 @Override
266 public void run() {
267 try {
268 value = future.get();
269 } catch (Exception e) {
270 throw new RuntimeException(e);
271 }
272 }
273
274 /**
275 * @return the value
276 */
277 public E getValue() {
278 return value;
279 }
280
281 /**
282 * @return the future
283 */
284 public Future<E> getFuture() {
285 return future;
286 }
287 }
288
289 /**
290 *
291 * @throws Exception
292 */
293 @Test
294 public void testOFStatisticsFuture() throws Exception {
295 // Test for a single stats reply
296 IOFSwitch sw = createMock(IOFSwitch.class);
297 sw.cancelStatisticsReply(1);
298 OFStatisticsFuture sf = new OFStatisticsFuture(tp, sw, 1);
299
300 replay(sw);
301 List<OFStatistics> stats;
302 FutureFetcher<List<OFStatistics>> ff = new FutureFetcher<List<OFStatistics>>(sf);
303 Thread t = new Thread(ff);
304 t.start();
305 sf.deliverFuture(sw, getStatisticsReply(1, 10, false));
306
307 t.join();
308 stats = ff.getValue();
309 verify(sw);
310 assertEquals(10, stats.size());
311
312 // Test multiple stats replies
313 reset(sw);
314 sw.cancelStatisticsReply(1);
315
316 sf = new OFStatisticsFuture(tp, sw, 1);
317
318 replay(sw);
319 ff = new FutureFetcher<List<OFStatistics>>(sf);
320 t = new Thread(ff);
321 t.start();
322 sf.deliverFuture(sw, getStatisticsReply(1, 10, true));
323 sf.deliverFuture(sw, getStatisticsReply(1, 5, false));
324 t.join();
325
326 stats = sf.get();
327 verify(sw);
328 assertEquals(15, stats.size());
329
330 // Test cancellation
331 reset(sw);
332 sw.cancelStatisticsReply(1);
333 sf = new OFStatisticsFuture(tp, sw, 1);
334
335 replay(sw);
336 ff = new FutureFetcher<List<OFStatistics>>(sf);
337 t = new Thread(ff);
338 t.start();
339 sf.cancel(true);
340 t.join();
341
342 stats = sf.get();
343 verify(sw);
344 assertEquals(0, stats.size());
345
346 // Test self timeout
347 reset(sw);
348 sw.cancelStatisticsReply(1);
349 sf = new OFStatisticsFuture(tp, sw, 1, 75, TimeUnit.MILLISECONDS);
350
351 replay(sw);
352 ff = new FutureFetcher<List<OFStatistics>>(sf);
353 t = new Thread(ff);
354 t.start();
355 t.join(2000);
356
357 stats = sf.get();
358 verify(sw);
359 assertEquals(0, stats.size());
360 }
361
362 @Test
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800363 public void testAddSwitch() throws Exception {
364 controller.activeSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
365
366 //OFSwitchImpl oldsw = createMock(OFSwitchImpl.class);
367 OFSwitchImpl oldsw = new OFSwitchImpl();
368 OFFeaturesReply featuresReply = new OFFeaturesReply();
369 featuresReply.setDatapathId(0L);
370 featuresReply.setPorts(new ArrayList<OFPhysicalPort>());
371 oldsw.setFeaturesReply(featuresReply);
372 //expect(oldsw.getId()).andReturn(0L).anyTimes();
373 //expect(oldsw.asyncRemoveSwitchLock()).andReturn(rwlock.writeLock()).anyTimes();
374 //oldsw.setConnected(false);
375 //expect(oldsw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
376
377 Channel channel = createNiceMock(Channel.class);
378 //expect(oldsw.getChannel()).andReturn(channel);
379 oldsw.setChannel(channel);
380 expect(channel.close()).andReturn(null);
381
382 IOFSwitch newsw = createMock(IOFSwitch.class);
383 expect(newsw.getId()).andReturn(0L).anyTimes();
384 expect(newsw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
Jonathan Hart2fa28062013-11-25 20:16:28 -0800385 //Now we don't write to storage, these methods aren't called
386 //expect(newsw.getConnectedSince()).andReturn(new Date());
387 //Channel channel2 = createMock(Channel.class);
388 //expect(newsw.getChannel()).andReturn(channel2);
389 //expect(channel2.getRemoteAddress()).andReturn(null);
Jonathan Hart535325c2013-12-12 09:29:32 -0800390 expect(newsw.getPorts()).andReturn(new ArrayList<OFPhysicalPort>());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800391 expect(newsw.getCapabilities()).andReturn(0).anyTimes();
392 expect(newsw.getBuffers()).andReturn(0).anyTimes();
393 expect(newsw.getTables()).andReturn((byte)0).anyTimes();
394 expect(newsw.getActions()).andReturn(0).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800395 controller.activeSwitches.put(0L, oldsw);
Jonathan Hart2fa28062013-11-25 20:16:28 -0800396 replay(newsw, channel);//, channel2);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800397
398 controller.addSwitch(newsw);
399
Jonathan Hart2fa28062013-11-25 20:16:28 -0800400 verify(newsw, channel);//, channel2);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800401 }
402
403 @Test
404 public void testUpdateQueue() throws Exception {
HIGUCHI Yuta36cf0762013-06-14 14:25:38 -0700405 class DummySwitchListener implements IOFSwitchListener, IOFSwitchPortListener {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800406 public int nAdded;
407 public int nRemoved;
408 public int nPortChanged;
409 public DummySwitchListener() {
410 nAdded = 0;
411 nRemoved = 0;
412 nPortChanged = 0;
413 }
414 public synchronized void addedSwitch(IOFSwitch sw) {
415 nAdded++;
416 notifyAll();
417 }
418 public synchronized void removedSwitch(IOFSwitch sw) {
419 nRemoved++;
420 notifyAll();
421 }
422 public String getName() {
423 return "dummy";
424 }
425 @Override
426 public void switchPortChanged(Long switchId) {
427 nPortChanged++;
428 notifyAll();
429 }
Pankaj Berde3ee2bfe2013-06-10 21:30:14 -0700430 @Override
431 public void switchPortAdded(Long switchId, OFPhysicalPort port) {
432 // TODO Auto-generated method stub
433
434 }
435 @Override
436 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
437 // TODO Auto-generated method stub
438
439 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800440 }
441 DummySwitchListener switchListener = new DummySwitchListener();
442 IOFSwitch sw = createMock(IOFSwitch.class);
Jonathan Hart220b8292013-12-07 19:25:11 -0800443 expect(sw.getId()).andReturn(1L).anyTimes();
444 expect(sw.getEnabledPorts()).andReturn(null);
445 expect(sw.getChannel()).andReturn(null).anyTimes();
446 replay(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800447 ControllerRunThread t = new ControllerRunThread();
448 t.start();
449
450 controller.addOFSwitchListener(switchListener);
451 synchronized(switchListener) {
452 controller.updates.put(controller.new SwitchUpdate(sw,
453 Controller.SwitchUpdateType.ADDED));
454 switchListener.wait(500);
455 assertTrue("IOFSwitchListener.addedSwitch() was not called",
456 switchListener.nAdded == 1);
457 controller.updates.put(controller.new SwitchUpdate(sw,
458 Controller.SwitchUpdateType.REMOVED));
459 switchListener.wait(500);
460 assertTrue("IOFSwitchListener.removedSwitch() was not called",
461 switchListener.nRemoved == 1);
462 controller.updates.put(controller.new SwitchUpdate(sw,
463 Controller.SwitchUpdateType.PORTCHANGED));
464 switchListener.wait(500);
465 assertTrue("IOFSwitchListener.switchPortChanged() was not called",
466 switchListener.nPortChanged == 1);
467 }
468 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800469
470 /**
471 * Test notifications for controller node IP changes. This requires
472 * synchronization between the main test thread and another thread
473 * that runs Controller's main loop and takes / handles updates. We
474 * synchronize with wait(timeout) / notifyAll(). We check for the
475 * expected condition after the wait returns. However, if wait returns
476 * due to the timeout (or due to spurious awaking) and the check fails we
477 * might just not have waited long enough. Using a long enough timeout
478 * mitigates this but we cannot get rid of the fundamental "issue".
479 *
480 * @throws Exception
481 */
Jonathan Hart2fa28062013-11-25 20:16:28 -0800482 /*
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800483 @Test
484 public void testControllerNodeIPChanges() throws Exception {
485 class DummyHAListener implements IHAListener {
486 public Map<String, String> curControllerNodeIPs;
487 public Map<String, String> addedControllerNodeIPs;
488 public Map<String, String> removedControllerNodeIPs;
489 public int nCalled;
490
491 public DummyHAListener() {
492 this.nCalled = 0;
493 }
494
495 @Override
496 public void roleChanged(Role oldRole, Role newRole) {
497 // ignore
498 }
499
500 @Override
501 public synchronized void controllerNodeIPsChanged(
502 Map<String, String> curControllerNodeIPs,
503 Map<String, String> addedControllerNodeIPs,
504 Map<String, String> removedControllerNodeIPs) {
505 this.curControllerNodeIPs = curControllerNodeIPs;
506 this.addedControllerNodeIPs = addedControllerNodeIPs;
507 this.removedControllerNodeIPs = removedControllerNodeIPs;
508 this.nCalled++;
509 notifyAll();
510 }
511
512 public void do_assert(int nCalled,
513 Map<String, String> curControllerNodeIPs,
514 Map<String, String> addedControllerNodeIPs,
515 Map<String, String> removedControllerNodeIPs) {
516 assertEquals("nCalled is not as expected", nCalled, this.nCalled);
517 assertEquals("curControllerNodeIPs is not as expected",
518 curControllerNodeIPs, this.curControllerNodeIPs);
519 assertEquals("addedControllerNodeIPs is not as expected",
520 addedControllerNodeIPs, this.addedControllerNodeIPs);
521 assertEquals("removedControllerNodeIPs is not as expected",
522 removedControllerNodeIPs, this.removedControllerNodeIPs);
523
524 }
525 }
526 long waitTimeout = 250; // ms
527 DummyHAListener listener = new DummyHAListener();
528 HashMap<String,String> expectedCurMap = new HashMap<String, String>();
529 HashMap<String,String> expectedAddedMap = new HashMap<String, String>();
530 HashMap<String,String> expectedRemovedMap = new HashMap<String, String>();
531
532 controller.addHAListener(listener);
533 ControllerRunThread t = new ControllerRunThread();
534 t.start();
535
536 synchronized(listener) {
537 // Insert a first entry
538 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
539 getFakeControllerIPRow("row1", "c1", "Ethernet", 0, "1.1.1.1"));
540 expectedCurMap.clear();
541 expectedAddedMap.clear();
542 expectedRemovedMap.clear();
543 expectedCurMap.put("c1", "1.1.1.1");
544 expectedAddedMap.put("c1", "1.1.1.1");
545 listener.wait(waitTimeout);
546 listener.do_assert(1, expectedCurMap, expectedAddedMap, expectedRemovedMap);
547
548 // Add an interface that we want to ignore.
549 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
550 getFakeControllerIPRow("row2", "c1", "Ethernet", 1, "1.1.1.2"));
551 listener.wait(waitTimeout); // TODO: do a different check. This call will have to wait for the timeout
552 assertTrue("controllerNodeIPsChanged() should not have been called here",
553 listener.nCalled == 1);
554
555 // Add another entry
556 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
557 getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.2"));
558 expectedCurMap.clear();
559 expectedAddedMap.clear();
560 expectedRemovedMap.clear();
561 expectedCurMap.put("c1", "1.1.1.1");
562 expectedCurMap.put("c2", "2.2.2.2");
563 expectedAddedMap.put("c2", "2.2.2.2");
564 listener.wait(waitTimeout);
565 listener.do_assert(2, expectedCurMap, expectedAddedMap, expectedRemovedMap);
566
567
568 // Update an entry
569 controller.storageSource.updateRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
570 "row3", getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.3"));
571 expectedCurMap.clear();
572 expectedAddedMap.clear();
573 expectedRemovedMap.clear();
574 expectedCurMap.put("c1", "1.1.1.1");
575 expectedCurMap.put("c2", "2.2.2.3");
576 expectedAddedMap.put("c2", "2.2.2.3");
577 expectedRemovedMap.put("c2", "2.2.2.2");
578 listener.wait(waitTimeout);
579 listener.do_assert(3, expectedCurMap, expectedAddedMap, expectedRemovedMap);
580
581 // Delete an entry
582 controller.storageSource.deleteRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
583 "row3");
584 expectedCurMap.clear();
585 expectedAddedMap.clear();
586 expectedRemovedMap.clear();
587 expectedCurMap.put("c1", "1.1.1.1");
588 expectedRemovedMap.put("c2", "2.2.2.3");
589 listener.wait(waitTimeout);
590 listener.do_assert(4, expectedCurMap, expectedAddedMap, expectedRemovedMap);
591 }
592 }
Jonathan Hart2fa28062013-11-25 20:16:28 -0800593 */
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800594
Jonathan Hart2fa28062013-11-25 20:16:28 -0800595 /*
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800596 @Test
597 public void testGetControllerNodeIPs() {
598 HashMap<String,String> expectedCurMap = new HashMap<String, String>();
599
600 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
601 getFakeControllerIPRow("row1", "c1", "Ethernet", 0, "1.1.1.1"));
602 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
603 getFakeControllerIPRow("row2", "c1", "Ethernet", 1, "1.1.1.2"));
604 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
605 getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.2"));
606 expectedCurMap.put("c1", "1.1.1.1");
607 expectedCurMap.put("c2", "2.2.2.2");
608 assertEquals("expectedControllerNodeIPs is not as expected",
609 expectedCurMap, controller.getControllerNodeIPs());
610 }
Jonathan Hart2fa28062013-11-25 20:16:28 -0800611 */
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800612
613 @Test
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800614 public void testCheckSwitchReady() {
615 OFChannelState state = new OFChannelState();
616 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
617 chdlr.sw = createMock(OFSwitchImpl.class);
618
619 // Wrong current state
620 // Should not go to READY
621 state.hsState = OFChannelState.HandshakeState.HELLO;
622 state.hasDescription = true;
623 state.hasGetConfigReply = true;
624 replay(chdlr.sw); // nothing called on sw
625 chdlr.checkSwitchReady();
626 verify(chdlr.sw);
627 assertSame(OFChannelState.HandshakeState.HELLO, state.hsState);
628 reset(chdlr.sw);
629
630 // Have only config reply
631 state.hsState = OFChannelState.HandshakeState.FEATURES_REPLY;
632 state.hasDescription = false;
633 state.hasGetConfigReply = true;
634 replay(chdlr.sw);
635 chdlr.checkSwitchReady();
636 verify(chdlr.sw);
637 assertSame(OFChannelState.HandshakeState.FEATURES_REPLY, state.hsState);
638 assertTrue(controller.connectedSwitches.isEmpty());
639 assertTrue(controller.activeSwitches.isEmpty());
640 reset(chdlr.sw);
641
642 // Have only desc reply
643 state.hsState = OFChannelState.HandshakeState.FEATURES_REPLY;
644 state.hasDescription = true;
645 state.hasGetConfigReply = false;
646 replay(chdlr.sw);
647 chdlr.checkSwitchReady();
648 verify(chdlr.sw);
649 assertSame(OFChannelState.HandshakeState.FEATURES_REPLY, state.hsState);
650 assertTrue(controller.connectedSwitches.isEmpty());
651 assertTrue(controller.activeSwitches.isEmpty());
652 reset(chdlr.sw);
653
654 //////////////////////////////////////////
655 // Finally, everything is right. Should advance to READY
656 //////////////////////////////////////////
657 controller.roleChanger = createMock(RoleChanger.class);
658 state.hsState = OFChannelState.HandshakeState.FEATURES_REPLY;
659 state.hasDescription = true;
660 state.hasGetConfigReply = true;
661 // Role support disabled. Switch should be promoted to active switch
662 // list.
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700663// FIXME: ONOS modified the behavior to always submit Role Request to trigger OFS error.
664// setupSwitchForAddSwitch(chdlr.sw, 0L);
665// chdlr.sw.clearAllFlowMods();
666// replay(controller.roleChanger, chdlr.sw);
667// chdlr.checkSwitchReady();
668// verify(controller.roleChanger, chdlr.sw);
669// assertSame(OFChannelState.HandshakeState.READY, state.hsState);
670// assertSame(chdlr.sw, controller.activeSwitches.get(0L));
671// assertTrue(controller.connectedSwitches.contains(chdlr.sw));
672// assertTrue(state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800673 reset(chdlr.sw);
674 reset(controller.roleChanger);
675 controller.connectedSwitches.clear();
676 controller.activeSwitches.clear();
677
678
679 // Role support enabled.
680 state.hsState = OFChannelState.HandshakeState.FEATURES_REPLY;
681 controller.role = Role.MASTER;
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700682 expect(chdlr.sw.getStringId()).andReturn("SomeID").anyTimes();
683 expect(chdlr.sw.getId()).andReturn(42L).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800684 Capture<Collection<OFSwitchImpl>> swListCapture =
685 new Capture<Collection<OFSwitchImpl>>();
686 controller.roleChanger.submitRequest(capture(swListCapture),
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700687 same(Role.SLAVE));
688 Capture<Collection<OFSwitchImpl>> swListCapture2 =
689 new Capture<Collection<OFSwitchImpl>>();
690 controller.roleChanger.submitRequest(capture(swListCapture2),
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800691 same(Role.MASTER));
692 replay(controller.roleChanger, chdlr.sw);
693 chdlr.checkSwitchReady();
694 verify(controller.roleChanger, chdlr.sw);
695 assertSame(OFChannelState.HandshakeState.READY, state.hsState);
696 assertTrue(controller.activeSwitches.isEmpty());
697 assertTrue(controller.connectedSwitches.contains(chdlr.sw));
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700698// assertTrue(state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800699 Collection<OFSwitchImpl> swList = swListCapture.getValue();
700 assertEquals(1, swList.size());
701 assertTrue("swList must contain this switch", swList.contains(chdlr.sw));
702 }
703
704
705 @Test
706 public void testChannelDisconnected() throws Exception {
707 OFChannelState state = new OFChannelState();
708 state.hsState = OFChannelState.HandshakeState.READY;
709 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
710 chdlr.sw = createMock(OFSwitchImpl.class);
711
712 // Switch is active
713 expect(chdlr.sw.getId()).andReturn(0L).anyTimes();
714 expect(chdlr.sw.getStringId()).andReturn("00:00:00:00:00:00:00:00")
715 .anyTimes();
716 chdlr.sw.cancelAllStatisticsReplies();
717 chdlr.sw.setConnected(false);
718 expect(chdlr.sw.isConnected()).andReturn(true);
719
720 controller.connectedSwitches.add(chdlr.sw);
721 controller.activeSwitches.put(0L, chdlr.sw);
722
723 replay(chdlr.sw);
724 chdlr.channelDisconnected(null, null);
725 verify(chdlr.sw);
726
727 // Switch is connected but not active
728 reset(chdlr.sw);
729 expect(chdlr.sw.getId()).andReturn(0L).anyTimes();
730 chdlr.sw.setConnected(false);
731 replay(chdlr.sw);
732 chdlr.channelDisconnected(null, null);
733 verify(chdlr.sw);
734
735 // Not in ready state
736 state.hsState = HandshakeState.START;
737 reset(chdlr.sw);
738 replay(chdlr.sw);
739 chdlr.channelDisconnected(null, null);
740 verify(chdlr.sw);
741
742 // Switch is null
743 state.hsState = HandshakeState.READY;
744 chdlr.sw = null;
745 chdlr.channelDisconnected(null, null);
746 }
747
748 /*
749 @Test
750 public void testRoleChangeForSerialFailoverSwitch() throws Exception {
751 OFSwitchImpl newsw = createMock(OFSwitchImpl.class);
752 expect(newsw.getId()).andReturn(0L).anyTimes();
753 expect(newsw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
754 Channel channel2 = createMock(Channel.class);
755 expect(newsw.getChannel()).andReturn(channel2);
756
757 // newsw.role is null because the switch does not support
758 // role request messages
759 expect(newsw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
760 .andReturn(false);
761 // switch is connected
762 controller.connectedSwitches.add(newsw);
763
764 // the switch should get disconnected when role is changed to SLAVE
765 expect(channel2.close()).andReturn(null);
766
767 replay(newsw, channel2);
768 controller.setRole(Role.SLAVE);
769 verify(newsw, channel2);
770 }
771 */
772
773 @Test
774 public void testRoleNotSupportedError() throws Exception {
775 int xid = 424242;
776 OFChannelState state = new OFChannelState();
777 state.hsState = HandshakeState.READY;
778 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
779 chdlr.sw = createMock(OFSwitchImpl.class);
780 Channel ch = createMock(Channel.class);
781
782 // the error returned when role request message is not supported by sw
783 OFError msg = new OFError();
784 msg.setType(OFType.ERROR);
785 msg.setXid(xid);
786 msg.setErrorType(OFErrorType.OFPET_BAD_REQUEST);
787 msg.setErrorCode(OFBadRequestCode.OFPBRC_BAD_VENDOR);
788
789 // the switch connection should get disconnected when the controller is
790 // in SLAVE mode and the switch does not support role-request messages
791 state.firstRoleReplyReceived = false;
792 controller.role = Role.SLAVE;
793 expect(chdlr.sw.checkFirstPendingRoleRequestXid(xid)).andReturn(true);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700794 expect(chdlr.sw.deliverRoleRequestNotSupportedEx(xid)).andReturn(Role.SLAVE);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800795 expect(chdlr.sw.getChannel()).andReturn(ch).anyTimes();
796 expect(ch.close()).andReturn(null);
797
798 replay(ch, chdlr.sw);
799 chdlr.processOFMessage(msg);
800 verify(ch, chdlr.sw);
801 assertTrue("state.firstRoleReplyReceived must be true",
802 state.firstRoleReplyReceived);
803 assertTrue("activeSwitches must be empty",
804 controller.activeSwitches.isEmpty());
805 reset(ch, chdlr.sw);
806
807
808 // a different error message - should also reject role request
809 msg.setErrorType(OFErrorType.OFPET_BAD_REQUEST);
810 msg.setErrorCode(OFBadRequestCode.OFPBRC_EPERM);
811 state.firstRoleReplyReceived = false;
812 controller.role = Role.SLAVE;
813 expect(chdlr.sw.checkFirstPendingRoleRequestXid(xid)).andReturn(true);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700814 expect(chdlr.sw.deliverRoleRequestNotSupportedEx(xid)).andReturn(Role.SLAVE);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800815 expect(chdlr.sw.getChannel()).andReturn(ch).anyTimes();
816 expect(ch.close()).andReturn(null);
817 replay(ch, chdlr.sw);
818
819 chdlr.processOFMessage(msg);
820 verify(ch, chdlr.sw);
821 assertTrue("state.firstRoleReplyReceived must be True even with EPERM",
822 state.firstRoleReplyReceived);
823 assertTrue("activeSwitches must be empty",
824 controller.activeSwitches.isEmpty());
825 reset(ch, chdlr.sw);
826
827
828 // We are MASTER, the switch should be added to the list of active
829 // switches.
830 state.firstRoleReplyReceived = false;
831 controller.role = Role.MASTER;
832 expect(chdlr.sw.checkFirstPendingRoleRequestXid(xid)).andReturn(true);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700833 expect(chdlr.sw.deliverRoleRequestNotSupportedEx(xid)).andReturn(Role.MASTER);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800834 setupSwitchForAddSwitch(chdlr.sw, 0L);
835 chdlr.sw.clearAllFlowMods();
836 replay(ch, chdlr.sw);
837
838 chdlr.processOFMessage(msg);
839 verify(ch, chdlr.sw);
840 assertTrue("state.firstRoleReplyReceived must be true",
841 state.firstRoleReplyReceived);
842 assertSame("activeSwitches must contain this switch",
843 chdlr.sw, controller.activeSwitches.get(0L));
844 reset(ch, chdlr.sw);
845
846 }
847
848
849 @Test
850 public void testVendorMessageUnknown() throws Exception {
851 // Check behavior with an unknown vendor id
852 OFChannelState state = new OFChannelState();
853 state.hsState = HandshakeState.READY;
854 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
855 OFVendor msg = new OFVendor();
856 msg.setVendor(0);
857 chdlr.processOFMessage(msg);
858 }
859
860
861 // Helper function.
862 protected Controller.OFChannelHandler getChannelHandlerForRoleReplyTest() {
863 OFChannelState state = new OFChannelState();
864 state.hsState = HandshakeState.READY;
865 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
866 chdlr.sw = createMock(OFSwitchImpl.class);
867 return chdlr;
868 }
869
870 // Helper function
871 protected OFVendor getRoleReplyMsgForRoleReplyTest(int xid, int nicira_role) {
872 OFVendor msg = new OFVendor();
873 msg.setXid(xid);
874 msg.setVendor(OFNiciraVendorData.NX_VENDOR_ID);
875 OFRoleReplyVendorData roleReplyVendorData =
876 new OFRoleReplyVendorData(OFRoleReplyVendorData.NXT_ROLE_REPLY);
877 msg.setVendorData(roleReplyVendorData);
878 roleReplyVendorData.setRole(nicira_role);
879 return msg;
880 }
881
882 /** invalid role in role reply */
883 @Test
884 public void testNiciraRoleReplyInvalidRole()
885 throws Exception {
886 int xid = 424242;
887 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
888 Channel ch = createMock(Channel.class);
889 expect(chdlr.sw.getChannel()).andReturn(ch);
890 expect(ch.close()).andReturn(null);
891 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid, 232323);
892 replay(chdlr.sw, ch);
893 chdlr.processOFMessage(msg);
894 verify(chdlr.sw, ch);
895 }
896
897 /** First role reply message received: transition from slave to master */
898 @Test
899 public void testNiciraRoleReplySlave2MasterFristTime()
900 throws Exception {
901 int xid = 424242;
902 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
903 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
904 OFRoleReplyVendorData.NX_ROLE_MASTER);
905
906 chdlr.sw.deliverRoleReply(xid, Role.MASTER);
907 expect(chdlr.sw.isActive()).andReturn(true);
908 setupSwitchForAddSwitch(chdlr.sw, 1L);
909 chdlr.sw.clearAllFlowMods();
910 chdlr.state.firstRoleReplyReceived = false;
911 replay(chdlr.sw);
912 chdlr.processOFMessage(msg);
913 verify(chdlr.sw);
914 assertTrue("state.firstRoleReplyReceived must be true",
915 chdlr.state.firstRoleReplyReceived);
916 assertSame("activeSwitches must contain this switch",
917 chdlr.sw, controller.activeSwitches.get(1L));
918 }
919
920
921 /** Not first role reply message received: transition from slave to master */
922 @Test
923 public void testNiciraRoleReplySlave2MasterNotFristTime()
924 throws Exception {
925 int xid = 424242;
926 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
927 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
928 OFRoleReplyVendorData.NX_ROLE_MASTER);
929
930 chdlr.sw.deliverRoleReply(xid, Role.MASTER);
931 expect(chdlr.sw.isActive()).andReturn(true);
932 setupSwitchForAddSwitch(chdlr.sw, 1L);
933 chdlr.state.firstRoleReplyReceived = true;
934 // Flow table shouldn't be wipe
935 replay(chdlr.sw);
936 chdlr.processOFMessage(msg);
937 verify(chdlr.sw);
938 assertTrue("state.firstRoleReplyReceived must be true",
939 chdlr.state.firstRoleReplyReceived);
940 assertSame("activeSwitches must contain this switch",
941 chdlr.sw, controller.activeSwitches.get(1L));
942 }
943
944 /** transition from slave to equal */
945 @Test
946 public void testNiciraRoleReplySlave2Equal()
947 throws Exception {
948 int xid = 424242;
949 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
950 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
951 OFRoleReplyVendorData.NX_ROLE_OTHER);
952
953 chdlr.sw.deliverRoleReply(xid, Role.EQUAL);
954 expect(chdlr.sw.isActive()).andReturn(true);
955 setupSwitchForAddSwitch(chdlr.sw, 1L);
956 chdlr.sw.clearAllFlowMods();
957 chdlr.state.firstRoleReplyReceived = false;
958 replay(chdlr.sw);
959 chdlr.processOFMessage(msg);
960 verify(chdlr.sw);
961 assertTrue("state.firstRoleReplyReceived must be true",
962 chdlr.state.firstRoleReplyReceived);
963 assertSame("activeSwitches must contain this switch",
964 chdlr.sw, controller.activeSwitches.get(1L));
965 };
966
967 @Test
968 /** Slave2Slave transition ==> no change */
969 public void testNiciraRoleReplySlave2Slave() throws Exception{
970 int xid = 424242;
971 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
972 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
973 OFRoleReplyVendorData.NX_ROLE_SLAVE);
974
975 chdlr.sw.deliverRoleReply(xid, Role.SLAVE);
976 expect(chdlr.sw.getId()).andReturn(1L).anyTimes();
977 expect(chdlr.sw.getStringId()).andReturn("00:00:00:00:00:00:00:01")
978 .anyTimes();
979 expect(chdlr.sw.isActive()).andReturn(false);
980 // don't add switch to activeSwitches ==> slave2slave
981 chdlr.state.firstRoleReplyReceived = false;
982 replay(chdlr.sw);
983 chdlr.processOFMessage(msg);
984 verify(chdlr.sw);
985 assertTrue("state.firstRoleReplyReceived must be true",
986 chdlr.state.firstRoleReplyReceived);
987 assertTrue("activeSwitches must be empty",
988 controller.activeSwitches.isEmpty());
989 }
990
991 @Test
992 /** Equal2Master transition ==> no change */
993 public void testNiciraRoleReplyEqual2Master() throws Exception{
994 int xid = 424242;
995 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
996 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
997 OFRoleReplyVendorData.NX_ROLE_MASTER);
998
999 chdlr.sw.deliverRoleReply(xid, Role.MASTER);
1000 expect(chdlr.sw.getId()).andReturn(1L).anyTimes();
1001 expect(chdlr.sw.getStringId()).andReturn("00:00:00:00:00:00:00:01")
1002 .anyTimes();
1003 expect(chdlr.sw.isActive()).andReturn(true);
1004 controller.activeSwitches.put(1L, chdlr.sw);
1005 chdlr.state.firstRoleReplyReceived = false;
1006 replay(chdlr.sw);
1007 chdlr.processOFMessage(msg);
1008 verify(chdlr.sw);
1009 assertTrue("state.firstRoleReplyReceived must be true",
1010 chdlr.state.firstRoleReplyReceived);
1011 assertSame("activeSwitches must contain this switch",
1012 chdlr.sw, controller.activeSwitches.get(1L));
1013 }
1014
1015 @Test
1016 public void testNiciraRoleReplyMaster2Slave()
1017 throws Exception {
1018 int xid = 424242;
1019 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
1020 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
1021 OFRoleReplyVendorData.NX_ROLE_SLAVE);
1022
1023 chdlr.sw.deliverRoleReply(xid, Role.SLAVE);
1024 expect(chdlr.sw.getId()).andReturn(1L).anyTimes();
1025 expect(chdlr.sw.getStringId()).andReturn("00:00:00:00:00:00:00:01")
1026 .anyTimes();
1027 controller.activeSwitches.put(1L, chdlr.sw);
1028 expect(chdlr.sw.isActive()).andReturn(false);
1029 expect(chdlr.sw.isConnected()).andReturn(true);
1030 chdlr.sw.cancelAllStatisticsReplies();
1031 chdlr.state.firstRoleReplyReceived = false;
1032 replay(chdlr.sw);
1033 chdlr.processOFMessage(msg);
1034 verify(chdlr.sw);
1035 assertTrue("state.firstRoleReplyReceived must be true",
1036 chdlr.state.firstRoleReplyReceived);
1037 assertTrue("activeSwitches must be empty",
1038 controller.activeSwitches.isEmpty());
1039 }
1040
1041 /**
1042 * Tests that you can't remove a switch from the active
1043 * switch list.
1044 * @throws Exception
1045 */
1046 @Test
1047 public void testRemoveActiveSwitch() {
1048 IOFSwitch sw = EasyMock.createNiceMock(IOFSwitch.class);
1049 boolean exceptionThrown = false;
1050 expect(sw.getId()).andReturn(1L).anyTimes();
1051 replay(sw);
1052 getController().activeSwitches.put(sw.getId(), sw);
1053 try {
1054 getController().getSwitches().remove(1L);
1055 } catch (UnsupportedOperationException e) {
1056 exceptionThrown = true;
1057 }
1058 assertTrue(exceptionThrown);
1059 verify(sw);
1060 }
1061
1062 public void verifyPortChangedUpdateInQueue(IOFSwitch sw) throws Exception {
1063 assertEquals(1, controller.updates.size());
1064 IUpdate update = controller.updates.take();
1065 assertEquals(true, update instanceof SwitchUpdate);
1066 SwitchUpdate swUpdate = (SwitchUpdate)update;
1067 assertEquals(sw, swUpdate.sw);
1068 assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.switchUpdateType);
1069 }
1070
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001071 public void verifyPortAddedUpdateInQueue(IOFSwitch sw) throws Exception {
1072 assertEquals(2, controller.updates.size());
1073 IUpdate update = controller.updates.take();
1074 assertEquals(true, update instanceof SwitchUpdate);
1075 SwitchUpdate swUpdate = (SwitchUpdate)update;
1076 assertEquals(sw, swUpdate.sw);
1077 assertEquals(SwitchUpdateType.PORTADDED, swUpdate.switchUpdateType);
1078 verifyPortChangedUpdateInQueue(sw);
1079 }
1080
1081 public void verifyPortRemovedUpdateInQueue(IOFSwitch sw) throws Exception {
1082 assertEquals(2, controller.updates.size());
1083 IUpdate update = controller.updates.take();
1084 assertEquals(true, update instanceof SwitchUpdate);
1085 SwitchUpdate swUpdate = (SwitchUpdate)update;
1086 assertEquals(sw, swUpdate.sw);
1087 assertEquals(SwitchUpdateType.PORTREMOVED, swUpdate.switchUpdateType);
1088 verifyPortChangedUpdateInQueue(sw);
1089 }
1090
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001091 /*
1092 * Test handlePortStatus()
1093 * TODO: test correct updateStorage behavior!
1094 */
1095 @Test
1096 public void testHandlePortStatus() throws Exception {
1097 IOFSwitch sw = createMock(IOFSwitch.class);
Jonathan Hart220b8292013-12-07 19:25:11 -08001098 expect(sw.getId()).andReturn(1L).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001099 OFPhysicalPort port = new OFPhysicalPort();
1100 port.setName("myPortName1");
1101 port.setPortNumber((short)42);
1102
1103 OFPortStatus ofps = new OFPortStatus();
1104 ofps.setDesc(port);
1105
1106 ofps.setReason((byte)OFPortReason.OFPPR_ADD.ordinal());
1107 sw.setPort(port);
1108 expectLastCall().once();
1109 replay(sw);
1110 controller.handlePortStatusMessage(sw, ofps, false);
1111 verify(sw);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001112 verifyPortAddedUpdateInQueue(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001113 reset(sw);
1114
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001115 // ONOS:Port is considered added if Link state is not down and not configured to be down
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001116 ofps.setReason((byte)OFPortReason.OFPPR_MODIFY.ordinal());
1117 sw.setPort(port);
1118 expectLastCall().once();
1119 replay(sw);
1120 controller.handlePortStatusMessage(sw, ofps, false);
1121 verify(sw);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001122 verifyPortAddedUpdateInQueue(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001123 reset(sw);
1124
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001125 // ONOS:Port is considered removed if Link state is down
1126 ofps.setReason((byte)OFPortReason.OFPPR_MODIFY.ordinal());
1127 port.setState(OFPortState.OFPPS_LINK_DOWN.getValue());
1128 sw.setPort(port);
1129 expectLastCall().once();
1130 replay(sw);
1131 controller.handlePortStatusMessage(sw, ofps, false);
1132 verify(sw);
1133 verifyPortRemovedUpdateInQueue(sw);
1134 reset(sw);
1135 port.setState(0);// reset
1136
1137 // ONOS: .. or is configured to be down
1138 ofps.setReason((byte)OFPortReason.OFPPR_MODIFY.ordinal());
1139 port.setConfig(OFPortConfig.OFPPC_PORT_DOWN.getValue());
1140 sw.setPort(port);
1141 expectLastCall().once();
1142 replay(sw);
1143 controller.handlePortStatusMessage(sw, ofps, false);
1144 verify(sw);
1145 verifyPortRemovedUpdateInQueue(sw);
1146 reset(sw);
1147 port.setConfig(0);// reset
1148
1149
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001150 ofps.setReason((byte)OFPortReason.OFPPR_DELETE.ordinal());
1151 sw.deletePort(port.getPortNumber());
1152 expectLastCall().once();
1153 replay(sw);
1154 controller.handlePortStatusMessage(sw, ofps, false);
1155 verify(sw);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001156 verifyPortRemovedUpdateInQueue(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001157 reset(sw);
1158 }
1159}