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