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