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