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