blob: eb639049e30b371f6706cbdac3da4fd11da50d5b [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
Ray Milkey269ffb92014-04-03 14:43:30 -07002 * 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 **/
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080017
18package net.floodlightcontroller.core.internal;
19
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070020import static org.easymock.EasyMock.anyObject;
21import static org.easymock.EasyMock.capture;
22import static org.easymock.EasyMock.createMock;
23import static org.easymock.EasyMock.createNiceMock;
24import static org.easymock.EasyMock.eq;
25import static org.easymock.EasyMock.expect;
26import static org.easymock.EasyMock.expectLastCall;
27import static org.easymock.EasyMock.isA;
28import static org.easymock.EasyMock.replay;
29import static org.easymock.EasyMock.reset;
30import static org.easymock.EasyMock.same;
31import static org.easymock.EasyMock.verify;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080032
33import java.util.ArrayList;
34import java.util.Collection;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080035import java.util.List;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080036import java.util.concurrent.ConcurrentHashMap;
37import java.util.concurrent.Future;
38import java.util.concurrent.TimeUnit;
39
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080040import net.floodlightcontroller.core.FloodlightContext;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070041import net.floodlightcontroller.core.FloodlightProvider;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080042import net.floodlightcontroller.core.IFloodlightProviderService;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080043import net.floodlightcontroller.core.IFloodlightProviderService.Role;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080044import net.floodlightcontroller.core.IListener.Command;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070045import net.floodlightcontroller.core.IOFMessageListener;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080046import net.floodlightcontroller.core.IOFSwitch;
47import net.floodlightcontroller.core.IOFSwitchListener;
Pankaj Berde6e421732013-08-14 15:17:52 -070048import net.floodlightcontroller.core.IUpdate;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080049import net.floodlightcontroller.core.internal.Controller.SwitchUpdate;
50import net.floodlightcontroller.core.internal.Controller.SwitchUpdateType;
51import net.floodlightcontroller.core.internal.OFChannelState.HandshakeState;
52import net.floodlightcontroller.core.module.FloodlightModuleContext;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080053import net.floodlightcontroller.core.test.MockThreadPoolService;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080054import net.floodlightcontroller.restserver.IRestApiService;
55import net.floodlightcontroller.restserver.RestApiServer;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080056import net.floodlightcontroller.test.FloodlightTestCase;
57import net.floodlightcontroller.threadpool.IThreadPoolService;
Jonathan Hart23701d12014-04-03 10:45:48 -070058import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
Jonathan Hart284e70f2014-07-05 12:32:51 -070059import net.onrc.onos.core.linkdiscovery.LinkDiscoveryManager;
Jonathan Hart51f6f5b2014-04-03 10:32:10 -070060import net.onrc.onos.core.main.IOFSwitchPortListener;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070061import net.onrc.onos.core.packet.ARP;
62import net.onrc.onos.core.packet.Ethernet;
63import net.onrc.onos.core.packet.IPacket;
64import net.onrc.onos.core.packet.IPv4;
65import net.onrc.onos.core.registry.IControllerRegistryService;
66import net.onrc.onos.core.registry.StandaloneRegistry;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080067
68import org.easymock.Capture;
69import org.easymock.EasyMock;
70import org.jboss.netty.channel.Channel;
71import org.junit.Test;
72import org.openflow.protocol.OFError;
73import org.openflow.protocol.OFError.OFBadRequestCode;
74import org.openflow.protocol.OFError.OFErrorType;
75import org.openflow.protocol.OFFeaturesReply;
76import org.openflow.protocol.OFPacketIn;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070077import org.openflow.protocol.OFPacketIn.OFPacketInReason;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080078import org.openflow.protocol.OFPhysicalPort;
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -070079import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
80import org.openflow.protocol.OFPhysicalPort.OFPortState;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080081import org.openflow.protocol.OFPortStatus;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070082import org.openflow.protocol.OFPortStatus.OFPortReason;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080083import org.openflow.protocol.OFStatisticsReply;
84import org.openflow.protocol.OFType;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080085import org.openflow.protocol.OFVendor;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080086import org.openflow.protocol.factory.BasicFactory;
87import org.openflow.protocol.statistics.OFFlowStatisticsReply;
88import org.openflow.protocol.statistics.OFStatistics;
89import org.openflow.protocol.statistics.OFStatisticsType;
90import org.openflow.util.HexString;
91import org.openflow.vendor.nicira.OFNiciraVendorData;
92import org.openflow.vendor.nicira.OFRoleReplyVendorData;
93
94/**
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080095 * @author David Erickson (daviderickson@cs.stanford.edu)
96 */
97public class ControllerTest extends FloodlightTestCase {
Ray Milkey269ffb92014-04-03 14:43:30 -070098
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080099 private Controller controller;
100 private MockThreadPoolService tp;
101
102 @Override
103 public void setUp() throws Exception {
104 super.setUp();
105 FloodlightModuleContext fmc = new FloodlightModuleContext();
Ray Milkey269ffb92014-04-03 14:43:30 -0700106
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800107 FloodlightProvider cm = new FloodlightProvider();
Ray Milkey269ffb92014-04-03 14:43:30 -0700108 controller = (Controller) cm.getServiceImpls().get(IFloodlightProviderService.class);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800109 fmc.addService(IFloodlightProviderService.class, controller);
Ray Milkey269ffb92014-04-03 14:43:30 -0700110
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800111 RestApiServer restApi = new RestApiServer();
112 fmc.addService(IRestApiService.class, restApi);
Ray Milkey269ffb92014-04-03 14:43:30 -0700113
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800114 tp = new MockThreadPoolService();
115 fmc.addService(IThreadPoolService.class, tp);
Ray Milkey269ffb92014-04-03 14:43:30 -0700116
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700117 // Following added by ONOS
118 // TODO replace with mock if further testing is needed.
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700119 StandaloneRegistry sr = new StandaloneRegistry();
Ray Milkey269ffb92014-04-03 14:43:30 -0700120 fmc.addService(IControllerRegistryService.class, sr);
Jonathan Hart220b8292013-12-07 19:25:11 -0800121 LinkDiscoveryManager linkDiscovery = new LinkDiscoveryManager();
122 fmc.addService(ILinkDiscoveryService.class, linkDiscovery);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700123
Ray Milkey269ffb92014-04-03 14:43:30 -0700124
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800125 restApi.init(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800126 cm.init(fmc);
127 tp.init(fmc);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700128 sr.init(fmc);
Jonathan Hart220b8292013-12-07 19:25:11 -0800129 linkDiscovery.init(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800130 restApi.startUp(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800131 cm.startUp(fmc);
132 tp.startUp(fmc);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700133 sr.startUp(fmc);
Jonathan Hart220b8292013-12-07 19:25:11 -0800134 linkDiscovery.startUp(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800135 }
136
137 public Controller getController() {
138 return controller;
139 }
140
141 protected OFStatisticsReply getStatisticsReply(int transactionId,
Ray Milkey269ffb92014-04-03 14:43:30 -0700142 int count, boolean moreReplies) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800143 OFStatisticsReply sr = new OFStatisticsReply();
144 sr.setXid(transactionId);
145 sr.setStatisticType(OFStatisticsType.FLOW);
146 List<OFStatistics> statistics = new ArrayList<OFStatistics>();
147 for (int i = 0; i < count; ++i) {
148 statistics.add(new OFFlowStatisticsReply());
149 }
150 sr.setStatistics(statistics);
151 if (moreReplies)
152 sr.setFlags((short) 1);
153 return sr;
154 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700155
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800156 /* Set the mock expectations for sw when sw is passed to addSwitch */
157 protected void setupSwitchForAddSwitch(IOFSwitch sw, long dpid) {
158 String dpidString = HexString.toHexString(dpid);
Ray Milkey269ffb92014-04-03 14:43:30 -0700159
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800160 expect(sw.getId()).andReturn(dpid).anyTimes();
161 expect(sw.getStringId()).andReturn(dpidString).anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700162
Jonathan Hart2fa28062013-11-25 20:16:28 -0800163 //Now we don't write to storage these methods aren't called
164 //expect(sw.getConnectedSince()).andReturn(new Date());
165 //Channel channel = createMock(Channel.class);
166 //expect(sw.getChannel()).andReturn(channel);
167 //expect(channel.getRemoteAddress()).andReturn(null);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800168
169 expect(sw.getCapabilities()).andReturn(0).anyTimes();
170 expect(sw.getBuffers()).andReturn(0).anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700171 expect(sw.getTables()).andReturn((byte) 0).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800172 expect(sw.getActions()).andReturn(0).anyTimes();
173 expect(sw.getPorts()).andReturn(new ArrayList<OFPhysicalPort>()).anyTimes();
174 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700175
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800176 /**
177 * Run the controller's main loop so that updates are processed
178 */
179 protected class ControllerRunThread extends Thread {
180 public void run() {
181 controller.openFlowPort = 0; // Don't listen
182 controller.run();
183 }
184 }
185
186 /**
187 * Verify that a listener that throws an exception halts further
188 * execution, and verify that the Commands STOP and CONTINUE are honored.
Ray Milkey269ffb92014-04-03 14:43:30 -0700189 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800190 * @throws Exception
191 */
192 @Test
193 public void testHandleMessages() throws Exception {
194 Controller controller = getController();
195 controller.removeOFMessageListeners(OFType.PACKET_IN);
196
197 IOFSwitch sw = createMock(IOFSwitch.class);
198 expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
199
200 // Build our test packet
201 IPacket testPacket = new Ethernet()
Ray Milkey269ffb92014-04-03 14:43:30 -0700202 .setSourceMACAddress("00:44:33:22:11:00")
203 .setDestinationMACAddress("00:11:22:33:44:55")
204 .setEtherType(Ethernet.TYPE_ARP)
205 .setPayload(
206 new ARP()
207 .setHardwareType(ARP.HW_TYPE_ETHERNET)
208 .setProtocolType(ARP.PROTO_TYPE_IP)
209 .setHardwareAddressLength((byte) 6)
210 .setProtocolAddressLength((byte) 4)
211 .setOpCode(ARP.OP_REPLY)
212 .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:00"))
213 .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1"))
214 .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55"))
215 .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800216 byte[] testPacketSerialized = testPacket.serialize();
217
218 // Build the PacketIn
219 OFPacketIn pi = ((OFPacketIn) new BasicFactory().getMessage(OFType.PACKET_IN))
220 .setBufferId(-1)
221 .setInPort((short) 1)
222 .setPacketData(testPacketSerialized)
223 .setReason(OFPacketInReason.NO_MATCH)
224 .setTotalLength((short) testPacketSerialized.length);
225
226 IOFMessageListener test1 = createMock(IOFMessageListener.class);
227 expect(test1.getName()).andReturn("test1").anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700228 expect(test1.isCallbackOrderingPrereq((OFType) anyObject(), (String) anyObject())).andReturn(false).anyTimes();
229 expect(test1.isCallbackOrderingPostreq((OFType) anyObject(), (String) anyObject())).andReturn(false).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800230 expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andThrow(new RuntimeException("This is NOT an error! We are testing exception catching."));
231 IOFMessageListener test2 = createMock(IOFMessageListener.class);
232 expect(test2.getName()).andReturn("test2").anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700233 expect(test2.isCallbackOrderingPrereq((OFType) anyObject(), (String) anyObject())).andReturn(false).anyTimes();
234 expect(test2.isCallbackOrderingPostreq((OFType) anyObject(), (String) anyObject())).andReturn(false).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800235 // expect no calls to test2.receive() since test1.receive() threw an exception
236
237 replay(test1, test2, sw);
238 controller.addOFMessageListener(OFType.PACKET_IN, test1);
239 controller.addOFMessageListener(OFType.PACKET_IN, test2);
240 try {
241 controller.handleMessage(sw, pi, null);
242 } catch (RuntimeException e) {
243 assertEquals(e.getMessage().startsWith("This is NOT an error!"), true);
244 }
245 verify(test1, test2, sw);
246
247 // verify STOP works
248 reset(test1, test2, sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700249 expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andReturn(Command.STOP);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800250 //expect(test1.getId()).andReturn(0).anyTimes();
251 expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
252 replay(test1, test2, sw);
253 controller.handleMessage(sw, pi, null);
254 verify(test1, test2, sw);
255 }
256
257 public class FutureFetcher<E> implements Runnable {
258 public E value;
259 public Future<E> future;
260
261 public FutureFetcher(Future<E> future) {
262 this.future = future;
263 }
264
265 @Override
266 public void run() {
267 try {
268 value = future.get();
269 } catch (Exception e) {
270 throw new RuntimeException(e);
271 }
272 }
273
274 /**
275 * @return the value
276 */
277 public E getValue() {
278 return value;
279 }
280
281 /**
282 * @return the future
283 */
284 public Future<E> getFuture() {
285 return future;
286 }
287 }
288
289 /**
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800290 * @throws Exception
291 */
292 @Test
293 public void testOFStatisticsFuture() throws Exception {
294 // Test for a single stats reply
295 IOFSwitch sw = createMock(IOFSwitch.class);
296 sw.cancelStatisticsReply(1);
297 OFStatisticsFuture sf = new OFStatisticsFuture(tp, sw, 1);
298
299 replay(sw);
300 List<OFStatistics> stats;
301 FutureFetcher<List<OFStatistics>> ff = new FutureFetcher<List<OFStatistics>>(sf);
302 Thread t = new Thread(ff);
303 t.start();
304 sf.deliverFuture(sw, getStatisticsReply(1, 10, false));
305
306 t.join();
307 stats = ff.getValue();
308 verify(sw);
309 assertEquals(10, stats.size());
310
311 // Test multiple stats replies
312 reset(sw);
313 sw.cancelStatisticsReply(1);
314
315 sf = new OFStatisticsFuture(tp, sw, 1);
316
317 replay(sw);
318 ff = new FutureFetcher<List<OFStatistics>>(sf);
319 t = new Thread(ff);
320 t.start();
321 sf.deliverFuture(sw, getStatisticsReply(1, 10, true));
322 sf.deliverFuture(sw, getStatisticsReply(1, 5, false));
323 t.join();
324
325 stats = sf.get();
326 verify(sw);
327 assertEquals(15, stats.size());
328
329 // Test cancellation
330 reset(sw);
331 sw.cancelStatisticsReply(1);
332 sf = new OFStatisticsFuture(tp, sw, 1);
333
334 replay(sw);
335 ff = new FutureFetcher<List<OFStatistics>>(sf);
336 t = new Thread(ff);
337 t.start();
338 sf.cancel(true);
339 t.join();
340
341 stats = sf.get();
342 verify(sw);
343 assertEquals(0, stats.size());
344
345 // Test self timeout
346 reset(sw);
347 sw.cancelStatisticsReply(1);
348 sf = new OFStatisticsFuture(tp, sw, 1, 75, TimeUnit.MILLISECONDS);
349
350 replay(sw);
351 ff = new FutureFetcher<List<OFStatistics>>(sf);
352 t = new Thread(ff);
353 t.start();
354 t.join(2000);
355
356 stats = sf.get();
357 verify(sw);
358 assertEquals(0, stats.size());
359 }
360
361 @Test
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800362 public void testAddSwitch() throws Exception {
363 controller.activeSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
364
365 //OFSwitchImpl oldsw = createMock(OFSwitchImpl.class);
366 OFSwitchImpl oldsw = new OFSwitchImpl();
367 OFFeaturesReply featuresReply = new OFFeaturesReply();
368 featuresReply.setDatapathId(0L);
369 featuresReply.setPorts(new ArrayList<OFPhysicalPort>());
370 oldsw.setFeaturesReply(featuresReply);
371 //expect(oldsw.getId()).andReturn(0L).anyTimes();
372 //expect(oldsw.asyncRemoveSwitchLock()).andReturn(rwlock.writeLock()).anyTimes();
373 //oldsw.setConnected(false);
374 //expect(oldsw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
375
376 Channel channel = createNiceMock(Channel.class);
377 //expect(oldsw.getChannel()).andReturn(channel);
378 oldsw.setChannel(channel);
379 expect(channel.close()).andReturn(null);
380
381 IOFSwitch newsw = createMock(IOFSwitch.class);
382 expect(newsw.getId()).andReturn(0L).anyTimes();
383 expect(newsw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
Jonathan Hart2fa28062013-11-25 20:16:28 -0800384 //Now we don't write to storage, these methods aren't called
385 //expect(newsw.getConnectedSince()).andReturn(new Date());
386 //Channel channel2 = createMock(Channel.class);
387 //expect(newsw.getChannel()).andReturn(channel2);
388 //expect(channel2.getRemoteAddress()).andReturn(null);
Jonathan Hart535325c2013-12-12 09:29:32 -0800389 expect(newsw.getPorts()).andReturn(new ArrayList<OFPhysicalPort>());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800390 expect(newsw.getCapabilities()).andReturn(0).anyTimes();
391 expect(newsw.getBuffers()).andReturn(0).anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700392 expect(newsw.getTables()).andReturn((byte) 0).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800393 expect(newsw.getActions()).andReturn(0).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800394 controller.activeSwitches.put(0L, oldsw);
Jonathan Hart2fa28062013-11-25 20:16:28 -0800395 replay(newsw, channel);//, channel2);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800396
397 controller.addSwitch(newsw);
398
Jonathan Hart2fa28062013-11-25 20:16:28 -0800399 verify(newsw, channel);//, channel2);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800400 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700401
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800402 @Test
403 public void testUpdateQueue() throws Exception {
HIGUCHI Yuta36cf0762013-06-14 14:25:38 -0700404 class DummySwitchListener implements IOFSwitchListener, IOFSwitchPortListener {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800405 public int nAdded;
406 public int nRemoved;
407 public int nPortChanged;
Ray Milkey269ffb92014-04-03 14:43:30 -0700408
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800409 public DummySwitchListener() {
410 nAdded = 0;
411 nRemoved = 0;
412 nPortChanged = 0;
413 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700414
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800415 public synchronized void addedSwitch(IOFSwitch sw) {
416 nAdded++;
417 notifyAll();
418 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700419
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800420 public synchronized void removedSwitch(IOFSwitch sw) {
421 nRemoved++;
422 notifyAll();
423 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700424
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800425 public String getName() {
426 return "dummy";
427 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700428
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800429 @Override
430 public void switchPortChanged(Long switchId) {
431 nPortChanged++;
432 notifyAll();
433 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700434
435 @Override
436 public void switchPortAdded(Long switchId, OFPhysicalPort port) {
437 // TODO Auto-generated method stub
438
439 }
440
441 @Override
442 public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
443 // TODO Auto-generated method stub
444
445 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800446 }
447 DummySwitchListener switchListener = new DummySwitchListener();
448 IOFSwitch sw = createMock(IOFSwitch.class);
Jonathan Hart220b8292013-12-07 19:25:11 -0800449 expect(sw.getId()).andReturn(1L).anyTimes();
450 expect(sw.getEnabledPorts()).andReturn(null);
451 expect(sw.getChannel()).andReturn(null).anyTimes();
452 replay(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800453 ControllerRunThread t = new ControllerRunThread();
454 t.start();
Ray Milkey269ffb92014-04-03 14:43:30 -0700455
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800456 controller.addOFSwitchListener(switchListener);
Ray Milkey269ffb92014-04-03 14:43:30 -0700457 synchronized (switchListener) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800458 controller.updates.put(controller.new SwitchUpdate(sw,
Ray Milkey269ffb92014-04-03 14:43:30 -0700459 Controller.SwitchUpdateType.ADDED));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800460 switchListener.wait(500);
Ray Milkey269ffb92014-04-03 14:43:30 -0700461 assertTrue("IOFSwitchListener.addedSwitch() was not called",
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800462 switchListener.nAdded == 1);
Ray Milkey269ffb92014-04-03 14:43:30 -0700463 controller.updates.put(controller.new SwitchUpdate(sw,
464 Controller.SwitchUpdateType.REMOVED));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800465 switchListener.wait(500);
Ray Milkey269ffb92014-04-03 14:43:30 -0700466 assertTrue("IOFSwitchListener.removedSwitch() was not called",
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800467 switchListener.nRemoved == 1);
Ray Milkey269ffb92014-04-03 14:43:30 -0700468 controller.updates.put(controller.new SwitchUpdate(sw,
469 Controller.SwitchUpdateType.PORTCHANGED));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800470 switchListener.wait(500);
Ray Milkey269ffb92014-04-03 14:43:30 -0700471 assertTrue("IOFSwitchListener.switchPortChanged() was not called",
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800472 switchListener.nPortChanged == 1);
473 }
474 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800475
476 /**
477 * Test notifications for controller node IP changes. This requires
Ray Milkey269ffb92014-04-03 14:43:30 -0700478 * synchronization between the main test thread and another thread
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800479 * that runs Controller's main loop and takes / handles updates. We
Ray Milkey269ffb92014-04-03 14:43:30 -0700480 * synchronize with wait(timeout) / notifyAll(). We check for the
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800481 * expected condition after the wait returns. However, if wait returns
482 * due to the timeout (or due to spurious awaking) and the check fails we
483 * might just not have waited long enough. Using a long enough timeout
Ray Milkey269ffb92014-04-03 14:43:30 -0700484 * mitigates this but we cannot get rid of the fundamental "issue".
485 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800486 * @throws Exception
487 */
Jonathan Hart2fa28062013-11-25 20:16:28 -0800488 /*
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800489 @Test
490 public void testControllerNodeIPChanges() throws Exception {
491 class DummyHAListener implements IHAListener {
492 public Map<String, String> curControllerNodeIPs;
493 public Map<String, String> addedControllerNodeIPs;
494 public Map<String, String> removedControllerNodeIPs;
495 public int nCalled;
496
497 public DummyHAListener() {
498 this.nCalled = 0;
499 }
500
501 @Override
502 public void roleChanged(Role oldRole, Role newRole) {
503 // ignore
504 }
505
506 @Override
507 public synchronized void controllerNodeIPsChanged(
508 Map<String, String> curControllerNodeIPs,
509 Map<String, String> addedControllerNodeIPs,
510 Map<String, String> removedControllerNodeIPs) {
511 this.curControllerNodeIPs = curControllerNodeIPs;
512 this.addedControllerNodeIPs = addedControllerNodeIPs;
513 this.removedControllerNodeIPs = removedControllerNodeIPs;
514 this.nCalled++;
515 notifyAll();
516 }
517
518 public void do_assert(int nCalled,
519 Map<String, String> curControllerNodeIPs,
520 Map<String, String> addedControllerNodeIPs,
521 Map<String, String> removedControllerNodeIPs) {
522 assertEquals("nCalled is not as expected", nCalled, this.nCalled);
523 assertEquals("curControllerNodeIPs is not as expected",
524 curControllerNodeIPs, this.curControllerNodeIPs);
525 assertEquals("addedControllerNodeIPs is not as expected",
526 addedControllerNodeIPs, this.addedControllerNodeIPs);
527 assertEquals("removedControllerNodeIPs is not as expected",
528 removedControllerNodeIPs, this.removedControllerNodeIPs);
529
530 }
531 }
532 long waitTimeout = 250; // ms
533 DummyHAListener listener = new DummyHAListener();
534 HashMap<String,String> expectedCurMap = new HashMap<String, String>();
535 HashMap<String,String> expectedAddedMap = new HashMap<String, String>();
536 HashMap<String,String> expectedRemovedMap = new HashMap<String, String>();
537
538 controller.addHAListener(listener);
539 ControllerRunThread t = new ControllerRunThread();
540 t.start();
541
542 synchronized(listener) {
543 // Insert a first entry
544 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
545 getFakeControllerIPRow("row1", "c1", "Ethernet", 0, "1.1.1.1"));
546 expectedCurMap.clear();
547 expectedAddedMap.clear();
548 expectedRemovedMap.clear();
549 expectedCurMap.put("c1", "1.1.1.1");
550 expectedAddedMap.put("c1", "1.1.1.1");
551 listener.wait(waitTimeout);
552 listener.do_assert(1, expectedCurMap, expectedAddedMap, expectedRemovedMap);
553
554 // Add an interface that we want to ignore.
555 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
556 getFakeControllerIPRow("row2", "c1", "Ethernet", 1, "1.1.1.2"));
557 listener.wait(waitTimeout); // TODO: do a different check. This call will have to wait for the timeout
558 assertTrue("controllerNodeIPsChanged() should not have been called here",
559 listener.nCalled == 1);
560
561 // Add another entry
562 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
563 getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.2"));
564 expectedCurMap.clear();
565 expectedAddedMap.clear();
566 expectedRemovedMap.clear();
567 expectedCurMap.put("c1", "1.1.1.1");
568 expectedCurMap.put("c2", "2.2.2.2");
569 expectedAddedMap.put("c2", "2.2.2.2");
570 listener.wait(waitTimeout);
571 listener.do_assert(2, expectedCurMap, expectedAddedMap, expectedRemovedMap);
572
573
574 // Update an entry
575 controller.storageSource.updateRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
576 "row3", getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.3"));
577 expectedCurMap.clear();
578 expectedAddedMap.clear();
579 expectedRemovedMap.clear();
580 expectedCurMap.put("c1", "1.1.1.1");
581 expectedCurMap.put("c2", "2.2.2.3");
582 expectedAddedMap.put("c2", "2.2.2.3");
583 expectedRemovedMap.put("c2", "2.2.2.2");
584 listener.wait(waitTimeout);
585 listener.do_assert(3, expectedCurMap, expectedAddedMap, expectedRemovedMap);
586
587 // Delete an entry
588 controller.storageSource.deleteRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
589 "row3");
590 expectedCurMap.clear();
591 expectedAddedMap.clear();
592 expectedRemovedMap.clear();
593 expectedCurMap.put("c1", "1.1.1.1");
594 expectedRemovedMap.put("c2", "2.2.2.3");
595 listener.wait(waitTimeout);
596 listener.do_assert(4, expectedCurMap, expectedAddedMap, expectedRemovedMap);
597 }
598 }
Jonathan Hart2fa28062013-11-25 20:16:28 -0800599 */
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800600
Jonathan Hart2fa28062013-11-25 20:16:28 -0800601 /*
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800602 @Test
603 public void testGetControllerNodeIPs() {
604 HashMap<String,String> expectedCurMap = new HashMap<String, String>();
605
606 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
607 getFakeControllerIPRow("row1", "c1", "Ethernet", 0, "1.1.1.1"));
608 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
609 getFakeControllerIPRow("row2", "c1", "Ethernet", 1, "1.1.1.2"));
610 controller.storageSource.insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
611 getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.2"));
612 expectedCurMap.put("c1", "1.1.1.1");
613 expectedCurMap.put("c2", "2.2.2.2");
614 assertEquals("expectedControllerNodeIPs is not as expected",
615 expectedCurMap, controller.getControllerNodeIPs());
616 }
Jonathan Hart2fa28062013-11-25 20:16:28 -0800617 */
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800618 @Test
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800619 public void testCheckSwitchReady() {
620 OFChannelState state = new OFChannelState();
621 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
622 chdlr.sw = createMock(OFSwitchImpl.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700623
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800624 // Wrong current state
625 // Should not go to READY
626 state.hsState = OFChannelState.HandshakeState.HELLO;
627 state.hasDescription = true;
628 state.hasGetConfigReply = true;
629 replay(chdlr.sw); // nothing called on sw
630 chdlr.checkSwitchReady();
631 verify(chdlr.sw);
632 assertSame(OFChannelState.HandshakeState.HELLO, state.hsState);
633 reset(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700634
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800635 // Have only config reply
636 state.hsState = OFChannelState.HandshakeState.FEATURES_REPLY;
637 state.hasDescription = false;
638 state.hasGetConfigReply = true;
Ray Milkey269ffb92014-04-03 14:43:30 -0700639 replay(chdlr.sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800640 chdlr.checkSwitchReady();
641 verify(chdlr.sw);
642 assertSame(OFChannelState.HandshakeState.FEATURES_REPLY, state.hsState);
643 assertTrue(controller.connectedSwitches.isEmpty());
644 assertTrue(controller.activeSwitches.isEmpty());
645 reset(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700646
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800647 // Have only desc reply
648 state.hsState = OFChannelState.HandshakeState.FEATURES_REPLY;
649 state.hasDescription = true;
650 state.hasGetConfigReply = false;
Ray Milkey269ffb92014-04-03 14:43:30 -0700651 replay(chdlr.sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800652 chdlr.checkSwitchReady();
653 verify(chdlr.sw);
654 assertSame(OFChannelState.HandshakeState.FEATURES_REPLY, state.hsState);
655 assertTrue(controller.connectedSwitches.isEmpty());
656 assertTrue(controller.activeSwitches.isEmpty());
657 reset(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700658
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800659 //////////////////////////////////////////
660 // Finally, everything is right. Should advance to READY
661 //////////////////////////////////////////
662 controller.roleChanger = createMock(RoleChanger.class);
663 state.hsState = OFChannelState.HandshakeState.FEATURES_REPLY;
664 state.hasDescription = true;
665 state.hasGetConfigReply = true;
666 // Role support disabled. Switch should be promoted to active switch
667 // list.
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700668// FIXME: ONOS modified the behavior to always submit Role Request to trigger OFS error.
669// setupSwitchForAddSwitch(chdlr.sw, 0L);
670// chdlr.sw.clearAllFlowMods();
671// replay(controller.roleChanger, chdlr.sw);
672// chdlr.checkSwitchReady();
673// verify(controller.roleChanger, chdlr.sw);
674// assertSame(OFChannelState.HandshakeState.READY, state.hsState);
675// assertSame(chdlr.sw, controller.activeSwitches.get(0L));
676// assertTrue(controller.connectedSwitches.contains(chdlr.sw));
677// assertTrue(state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800678 reset(chdlr.sw);
679 reset(controller.roleChanger);
680 controller.connectedSwitches.clear();
681 controller.activeSwitches.clear();
Ray Milkey269ffb92014-04-03 14:43:30 -0700682
683
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800684 // Role support enabled.
685 state.hsState = OFChannelState.HandshakeState.FEATURES_REPLY;
686 controller.role = Role.MASTER;
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700687 expect(chdlr.sw.getStringId()).andReturn("SomeID").anyTimes();
688 expect(chdlr.sw.getId()).andReturn(42L).anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700689 Capture<Collection<OFSwitchImpl>> swListCapture =
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700690 new Capture<Collection<OFSwitchImpl>>();
Ray Milkey269ffb92014-04-03 14:43:30 -0700691 controller.roleChanger.submitRequest(capture(swListCapture),
692 same(Role.SLAVE));
693 Capture<Collection<OFSwitchImpl>> swListCapture2 =
694 new Capture<Collection<OFSwitchImpl>>();
695 controller.roleChanger.submitRequest(capture(swListCapture2),
696 same(Role.MASTER));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800697 replay(controller.roleChanger, chdlr.sw);
698 chdlr.checkSwitchReady();
699 verify(controller.roleChanger, chdlr.sw);
700 assertSame(OFChannelState.HandshakeState.READY, state.hsState);
701 assertTrue(controller.activeSwitches.isEmpty());
702 assertTrue(controller.connectedSwitches.contains(chdlr.sw));
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700703// assertTrue(state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800704 Collection<OFSwitchImpl> swList = swListCapture.getValue();
705 assertEquals(1, swList.size());
706 assertTrue("swList must contain this switch", swList.contains(chdlr.sw));
707 }
708
Ray Milkey269ffb92014-04-03 14:43:30 -0700709
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800710 @Test
711 public void testChannelDisconnected() throws Exception {
712 OFChannelState state = new OFChannelState();
713 state.hsState = OFChannelState.HandshakeState.READY;
714 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
715 chdlr.sw = createMock(OFSwitchImpl.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700716
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800717 // Switch is active
718 expect(chdlr.sw.getId()).andReturn(0L).anyTimes();
719 expect(chdlr.sw.getStringId()).andReturn("00:00:00:00:00:00:00:00")
Ray Milkey269ffb92014-04-03 14:43:30 -0700720 .anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800721 chdlr.sw.cancelAllStatisticsReplies();
722 chdlr.sw.setConnected(false);
723 expect(chdlr.sw.isConnected()).andReturn(true);
Ray Milkey269ffb92014-04-03 14:43:30 -0700724
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800725 controller.connectedSwitches.add(chdlr.sw);
726 controller.activeSwitches.put(0L, chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700727
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800728 replay(chdlr.sw);
729 chdlr.channelDisconnected(null, null);
730 verify(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700731
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800732 // Switch is connected but not active
733 reset(chdlr.sw);
734 expect(chdlr.sw.getId()).andReturn(0L).anyTimes();
735 chdlr.sw.setConnected(false);
736 replay(chdlr.sw);
737 chdlr.channelDisconnected(null, null);
738 verify(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700739
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800740 // Not in ready state
741 state.hsState = HandshakeState.START;
742 reset(chdlr.sw);
743 replay(chdlr.sw);
744 chdlr.channelDisconnected(null, null);
745 verify(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700746
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800747 // Switch is null
748 state.hsState = HandshakeState.READY;
749 chdlr.sw = null;
750 chdlr.channelDisconnected(null, null);
751 }
752
753 /*
754 @Test
755 public void testRoleChangeForSerialFailoverSwitch() throws Exception {
756 OFSwitchImpl newsw = createMock(OFSwitchImpl.class);
757 expect(newsw.getId()).andReturn(0L).anyTimes();
758 expect(newsw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
759 Channel channel2 = createMock(Channel.class);
760 expect(newsw.getChannel()).andReturn(channel2);
761
762 // newsw.role is null because the switch does not support
763 // role request messages
764 expect(newsw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
765 .andReturn(false);
766 // switch is connected
767 controller.connectedSwitches.add(newsw);
768
769 // the switch should get disconnected when role is changed to SLAVE
770 expect(channel2.close()).andReturn(null);
771
772 replay(newsw, channel2);
773 controller.setRole(Role.SLAVE);
774 verify(newsw, channel2);
775 }
776 */
777
778 @Test
779 public void testRoleNotSupportedError() throws Exception {
780 int xid = 424242;
781 OFChannelState state = new OFChannelState();
782 state.hsState = HandshakeState.READY;
783 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
784 chdlr.sw = createMock(OFSwitchImpl.class);
785 Channel ch = createMock(Channel.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700786
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800787 // the error returned when role request message is not supported by sw
788 OFError msg = new OFError();
789 msg.setType(OFType.ERROR);
790 msg.setXid(xid);
791 msg.setErrorType(OFErrorType.OFPET_BAD_REQUEST);
792 msg.setErrorCode(OFBadRequestCode.OFPBRC_BAD_VENDOR);
Ray Milkey269ffb92014-04-03 14:43:30 -0700793
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800794 // the switch connection should get disconnected when the controller is
795 // in SLAVE mode and the switch does not support role-request messages
796 state.firstRoleReplyReceived = false;
797 controller.role = Role.SLAVE;
798 expect(chdlr.sw.checkFirstPendingRoleRequestXid(xid)).andReturn(true);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700799 expect(chdlr.sw.deliverRoleRequestNotSupportedEx(xid)).andReturn(Role.SLAVE);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800800 expect(chdlr.sw.getChannel()).andReturn(ch).anyTimes();
801 expect(ch.close()).andReturn(null);
Ray Milkey269ffb92014-04-03 14:43:30 -0700802
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800803 replay(ch, chdlr.sw);
804 chdlr.processOFMessage(msg);
805 verify(ch, chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700806 assertTrue("state.firstRoleReplyReceived must be true",
807 state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800808 assertTrue("activeSwitches must be empty",
Ray Milkey269ffb92014-04-03 14:43:30 -0700809 controller.activeSwitches.isEmpty());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800810 reset(ch, chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700811
812
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800813 // a different error message - should also reject role request
814 msg.setErrorType(OFErrorType.OFPET_BAD_REQUEST);
815 msg.setErrorCode(OFBadRequestCode.OFPBRC_EPERM);
816 state.firstRoleReplyReceived = false;
817 controller.role = Role.SLAVE;
818 expect(chdlr.sw.checkFirstPendingRoleRequestXid(xid)).andReturn(true);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700819 expect(chdlr.sw.deliverRoleRequestNotSupportedEx(xid)).andReturn(Role.SLAVE);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800820 expect(chdlr.sw.getChannel()).andReturn(ch).anyTimes();
821 expect(ch.close()).andReturn(null);
822 replay(ch, chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700823
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800824 chdlr.processOFMessage(msg);
825 verify(ch, chdlr.sw);
826 assertTrue("state.firstRoleReplyReceived must be True even with EPERM",
Ray Milkey269ffb92014-04-03 14:43:30 -0700827 state.firstRoleReplyReceived);
828 assertTrue("activeSwitches must be empty",
829 controller.activeSwitches.isEmpty());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800830 reset(ch, chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700831
832
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800833 // We are MASTER, the switch should be added to the list of active
834 // switches.
835 state.firstRoleReplyReceived = false;
836 controller.role = Role.MASTER;
837 expect(chdlr.sw.checkFirstPendingRoleRequestXid(xid)).andReturn(true);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700838 expect(chdlr.sw.deliverRoleRequestNotSupportedEx(xid)).andReturn(Role.MASTER);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800839 setupSwitchForAddSwitch(chdlr.sw, 0L);
840 chdlr.sw.clearAllFlowMods();
841 replay(ch, chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700842
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800843 chdlr.processOFMessage(msg);
844 verify(ch, chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700845 assertTrue("state.firstRoleReplyReceived must be true",
846 state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800847 assertSame("activeSwitches must contain this switch",
Ray Milkey269ffb92014-04-03 14:43:30 -0700848 chdlr.sw, controller.activeSwitches.get(0L));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800849 reset(ch, chdlr.sw);
850
851 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700852
853
854 @Test
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800855 public void testVendorMessageUnknown() throws Exception {
856 // Check behavior with an unknown vendor id
857 OFChannelState state = new OFChannelState();
858 state.hsState = HandshakeState.READY;
859 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
860 OFVendor msg = new OFVendor();
861 msg.setVendor(0);
862 chdlr.processOFMessage(msg);
863 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700864
865
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800866 // Helper function.
867 protected Controller.OFChannelHandler getChannelHandlerForRoleReplyTest() {
868 OFChannelState state = new OFChannelState();
869 state.hsState = HandshakeState.READY;
870 Controller.OFChannelHandler chdlr = controller.new OFChannelHandler(state);
871 chdlr.sw = createMock(OFSwitchImpl.class);
872 return chdlr;
873 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700874
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800875 // Helper function
876 protected OFVendor getRoleReplyMsgForRoleReplyTest(int xid, int nicira_role) {
877 OFVendor msg = new OFVendor();
878 msg.setXid(xid);
879 msg.setVendor(OFNiciraVendorData.NX_VENDOR_ID);
Ray Milkey269ffb92014-04-03 14:43:30 -0700880 OFRoleReplyVendorData roleReplyVendorData =
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800881 new OFRoleReplyVendorData(OFRoleReplyVendorData.NXT_ROLE_REPLY);
882 msg.setVendorData(roleReplyVendorData);
883 roleReplyVendorData.setRole(nicira_role);
884 return msg;
885 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700886
887 /**
888 * invalid role in role reply
889 */
890 @Test
891 public void testNiciraRoleReplyInvalidRole()
892 throws Exception {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800893 int xid = 424242;
894 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
895 Channel ch = createMock(Channel.class);
896 expect(chdlr.sw.getChannel()).andReturn(ch);
897 expect(ch.close()).andReturn(null);
898 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid, 232323);
899 replay(chdlr.sw, ch);
900 chdlr.processOFMessage(msg);
901 verify(chdlr.sw, ch);
902 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700903
904 /**
905 * First role reply message received: transition from slave to master
906 */
907 @Test
908 public void testNiciraRoleReplySlave2MasterFristTime()
909 throws Exception {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800910 int xid = 424242;
911 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
912 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700913 OFRoleReplyVendorData.NX_ROLE_MASTER);
914
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800915 chdlr.sw.deliverRoleReply(xid, Role.MASTER);
916 expect(chdlr.sw.isActive()).andReturn(true);
917 setupSwitchForAddSwitch(chdlr.sw, 1L);
918 chdlr.sw.clearAllFlowMods();
919 chdlr.state.firstRoleReplyReceived = false;
920 replay(chdlr.sw);
921 chdlr.processOFMessage(msg);
922 verify(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700923 assertTrue("state.firstRoleReplyReceived must be true",
924 chdlr.state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800925 assertSame("activeSwitches must contain this switch",
Ray Milkey269ffb92014-04-03 14:43:30 -0700926 chdlr.sw, controller.activeSwitches.get(1L));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800927 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700928
929
930 /**
931 * Not first role reply message received: transition from slave to master
932 */
933 @Test
934 public void testNiciraRoleReplySlave2MasterNotFristTime()
935 throws Exception {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800936 int xid = 424242;
937 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
938 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700939 OFRoleReplyVendorData.NX_ROLE_MASTER);
940
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800941 chdlr.sw.deliverRoleReply(xid, Role.MASTER);
942 expect(chdlr.sw.isActive()).andReturn(true);
943 setupSwitchForAddSwitch(chdlr.sw, 1L);
944 chdlr.state.firstRoleReplyReceived = true;
945 // Flow table shouldn't be wipe
946 replay(chdlr.sw);
947 chdlr.processOFMessage(msg);
948 verify(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700949 assertTrue("state.firstRoleReplyReceived must be true",
950 chdlr.state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800951 assertSame("activeSwitches must contain this switch",
Ray Milkey269ffb92014-04-03 14:43:30 -0700952 chdlr.sw, controller.activeSwitches.get(1L));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800953 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700954
955 /**
956 * transition from slave to equal
957 */
958 @Test
959 public void testNiciraRoleReplySlave2Equal()
960 throws Exception {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800961 int xid = 424242;
962 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
963 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
Ray Milkey269ffb92014-04-03 14:43:30 -0700964 OFRoleReplyVendorData.NX_ROLE_OTHER);
965
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800966 chdlr.sw.deliverRoleReply(xid, Role.EQUAL);
967 expect(chdlr.sw.isActive()).andReturn(true);
968 setupSwitchForAddSwitch(chdlr.sw, 1L);
969 chdlr.sw.clearAllFlowMods();
970 chdlr.state.firstRoleReplyReceived = false;
971 replay(chdlr.sw);
972 chdlr.processOFMessage(msg);
973 verify(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700974 assertTrue("state.firstRoleReplyReceived must be true",
975 chdlr.state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800976 assertSame("activeSwitches must contain this switch",
Ray Milkey269ffb92014-04-03 14:43:30 -0700977 chdlr.sw, controller.activeSwitches.get(1L));
978 }
979
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800980 @Test
981 /** Slave2Slave transition ==> no change */
Ray Milkey269ffb92014-04-03 14:43:30 -0700982 public void testNiciraRoleReplySlave2Slave() throws Exception {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800983 int xid = 424242;
984 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
Ray Milkey269ffb92014-04-03 14:43:30 -0700985 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
986 OFRoleReplyVendorData.NX_ROLE_SLAVE);
987
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800988 chdlr.sw.deliverRoleReply(xid, Role.SLAVE);
989 expect(chdlr.sw.getId()).andReturn(1L).anyTimes();
990 expect(chdlr.sw.getStringId()).andReturn("00:00:00:00:00:00:00:01")
Ray Milkey269ffb92014-04-03 14:43:30 -0700991 .anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800992 expect(chdlr.sw.isActive()).andReturn(false);
993 // don't add switch to activeSwitches ==> slave2slave
994 chdlr.state.firstRoleReplyReceived = false;
995 replay(chdlr.sw);
996 chdlr.processOFMessage(msg);
997 verify(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -0700998 assertTrue("state.firstRoleReplyReceived must be true",
999 chdlr.state.firstRoleReplyReceived);
1000 assertTrue("activeSwitches must be empty",
1001 controller.activeSwitches.isEmpty());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001002 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001003
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001004 @Test
1005 /** Equal2Master transition ==> no change */
Ray Milkey269ffb92014-04-03 14:43:30 -07001006 public void testNiciraRoleReplyEqual2Master() throws Exception {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001007 int xid = 424242;
1008 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
Ray Milkey269ffb92014-04-03 14:43:30 -07001009 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
1010 OFRoleReplyVendorData.NX_ROLE_MASTER);
1011
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001012 chdlr.sw.deliverRoleReply(xid, Role.MASTER);
1013 expect(chdlr.sw.getId()).andReturn(1L).anyTimes();
1014 expect(chdlr.sw.getStringId()).andReturn("00:00:00:00:00:00:00:01")
Ray Milkey269ffb92014-04-03 14:43:30 -07001015 .anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001016 expect(chdlr.sw.isActive()).andReturn(true);
1017 controller.activeSwitches.put(1L, chdlr.sw);
1018 chdlr.state.firstRoleReplyReceived = false;
1019 replay(chdlr.sw);
1020 chdlr.processOFMessage(msg);
1021 verify(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -07001022 assertTrue("state.firstRoleReplyReceived must be true",
1023 chdlr.state.firstRoleReplyReceived);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001024 assertSame("activeSwitches must contain this switch",
Ray Milkey269ffb92014-04-03 14:43:30 -07001025 chdlr.sw, controller.activeSwitches.get(1L));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001026 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001027
1028 @Test
1029 public void testNiciraRoleReplyMaster2Slave()
1030 throws Exception {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001031 int xid = 424242;
1032 Controller.OFChannelHandler chdlr = getChannelHandlerForRoleReplyTest();
Ray Milkey269ffb92014-04-03 14:43:30 -07001033 OFVendor msg = getRoleReplyMsgForRoleReplyTest(xid,
1034 OFRoleReplyVendorData.NX_ROLE_SLAVE);
1035
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001036 chdlr.sw.deliverRoleReply(xid, Role.SLAVE);
1037 expect(chdlr.sw.getId()).andReturn(1L).anyTimes();
1038 expect(chdlr.sw.getStringId()).andReturn("00:00:00:00:00:00:00:01")
Ray Milkey269ffb92014-04-03 14:43:30 -07001039 .anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001040 controller.activeSwitches.put(1L, chdlr.sw);
1041 expect(chdlr.sw.isActive()).andReturn(false);
1042 expect(chdlr.sw.isConnected()).andReturn(true);
1043 chdlr.sw.cancelAllStatisticsReplies();
1044 chdlr.state.firstRoleReplyReceived = false;
1045 replay(chdlr.sw);
1046 chdlr.processOFMessage(msg);
1047 verify(chdlr.sw);
Ray Milkey269ffb92014-04-03 14:43:30 -07001048 assertTrue("state.firstRoleReplyReceived must be true",
1049 chdlr.state.firstRoleReplyReceived);
1050 assertTrue("activeSwitches must be empty",
1051 controller.activeSwitches.isEmpty());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001052 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001053
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001054 /**
1055 * Tests that you can't remove a switch from the active
1056 * switch list.
Ray Milkey269ffb92014-04-03 14:43:30 -07001057 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001058 * @throws Exception
1059 */
1060 @Test
1061 public void testRemoveActiveSwitch() {
1062 IOFSwitch sw = EasyMock.createNiceMock(IOFSwitch.class);
1063 boolean exceptionThrown = false;
1064 expect(sw.getId()).andReturn(1L).anyTimes();
1065 replay(sw);
1066 getController().activeSwitches.put(sw.getId(), sw);
1067 try {
1068 getController().getSwitches().remove(1L);
1069 } catch (UnsupportedOperationException e) {
1070 exceptionThrown = true;
1071 }
1072 assertTrue(exceptionThrown);
1073 verify(sw);
1074 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001075
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001076 public void verifyPortChangedUpdateInQueue(IOFSwitch sw) throws Exception {
1077 assertEquals(1, controller.updates.size());
1078 IUpdate update = controller.updates.take();
1079 assertEquals(true, update instanceof SwitchUpdate);
Ray Milkey269ffb92014-04-03 14:43:30 -07001080 SwitchUpdate swUpdate = (SwitchUpdate) update;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001081 assertEquals(sw, swUpdate.sw);
1082 assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.switchUpdateType);
1083 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001084
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001085 public void verifyPortAddedUpdateInQueue(IOFSwitch sw) throws Exception {
1086 assertEquals(2, controller.updates.size());
1087 IUpdate update = controller.updates.take();
1088 assertEquals(true, update instanceof SwitchUpdate);
Ray Milkey269ffb92014-04-03 14:43:30 -07001089 SwitchUpdate swUpdate = (SwitchUpdate) update;
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001090 assertEquals(sw, swUpdate.sw);
1091 assertEquals(SwitchUpdateType.PORTADDED, swUpdate.switchUpdateType);
1092 verifyPortChangedUpdateInQueue(sw);
1093 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001094
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001095 public void verifyPortRemovedUpdateInQueue(IOFSwitch sw) throws Exception {
1096 assertEquals(2, controller.updates.size());
1097 IUpdate update = controller.updates.take();
1098 assertEquals(true, update instanceof SwitchUpdate);
Ray Milkey269ffb92014-04-03 14:43:30 -07001099 SwitchUpdate swUpdate = (SwitchUpdate) update;
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001100 assertEquals(sw, swUpdate.sw);
1101 assertEquals(SwitchUpdateType.PORTREMOVED, swUpdate.switchUpdateType);
1102 verifyPortChangedUpdateInQueue(sw);
1103 }
Ray Milkey269ffb92014-04-03 14:43:30 -07001104
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001105 /*
1106 * Test handlePortStatus()
1107 * TODO: test correct updateStorage behavior!
1108 */
Ray Milkey269ffb92014-04-03 14:43:30 -07001109 @Test
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001110 public void testHandlePortStatus() throws Exception {
1111 IOFSwitch sw = createMock(IOFSwitch.class);
Jonathan Hart220b8292013-12-07 19:25:11 -08001112 expect(sw.getId()).andReturn(1L).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001113 OFPhysicalPort port = new OFPhysicalPort();
1114 port.setName("myPortName1");
Ray Milkey269ffb92014-04-03 14:43:30 -07001115 port.setPortNumber((short) 42);
1116
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001117 OFPortStatus ofps = new OFPortStatus();
1118 ofps.setDesc(port);
Ray Milkey269ffb92014-04-03 14:43:30 -07001119
1120 ofps.setReason((byte) OFPortReason.OFPPR_ADD.ordinal());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001121 sw.setPort(port);
1122 expectLastCall().once();
1123 replay(sw);
1124 controller.handlePortStatusMessage(sw, ofps, false);
1125 verify(sw);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001126 verifyPortAddedUpdateInQueue(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001127 reset(sw);
Ray Milkey269ffb92014-04-03 14:43:30 -07001128
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001129 // ONOS:Port is considered added if Link state is not down and not configured to be down
Ray Milkey269ffb92014-04-03 14:43:30 -07001130 ofps.setReason((byte) OFPortReason.OFPPR_MODIFY.ordinal());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001131 sw.setPort(port);
1132 expectLastCall().once();
1133 replay(sw);
1134 controller.handlePortStatusMessage(sw, ofps, false);
1135 verify(sw);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001136 verifyPortAddedUpdateInQueue(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001137 reset(sw);
Ray Milkey269ffb92014-04-03 14:43:30 -07001138
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001139 // ONOS:Port is considered removed if Link state is down
Ray Milkey269ffb92014-04-03 14:43:30 -07001140 ofps.setReason((byte) OFPortReason.OFPPR_MODIFY.ordinal());
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001141 port.setState(OFPortState.OFPPS_LINK_DOWN.getValue());
1142 sw.setPort(port);
1143 expectLastCall().once();
1144 replay(sw);
1145 controller.handlePortStatusMessage(sw, ofps, false);
1146 verify(sw);
1147 verifyPortRemovedUpdateInQueue(sw);
1148 reset(sw);
1149 port.setState(0);// reset
Ray Milkey269ffb92014-04-03 14:43:30 -07001150
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001151 // ONOS: .. or is configured to be down
Ray Milkey269ffb92014-04-03 14:43:30 -07001152 ofps.setReason((byte) OFPortReason.OFPPR_MODIFY.ordinal());
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001153 port.setConfig(OFPortConfig.OFPPC_PORT_DOWN.getValue());
1154 sw.setPort(port);
1155 expectLastCall().once();
1156 replay(sw);
1157 controller.handlePortStatusMessage(sw, ofps, false);
1158 verify(sw);
1159 verifyPortRemovedUpdateInQueue(sw);
1160 reset(sw);
1161 port.setConfig(0);// reset
Ray Milkey269ffb92014-04-03 14:43:30 -07001162
1163
1164 ofps.setReason((byte) OFPortReason.OFPPR_DELETE.ordinal());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001165 sw.deletePort(port.getPortNumber());
1166 expectLastCall().once();
1167 replay(sw);
1168 controller.handlePortStatusMessage(sw, ofps, false);
1169 verify(sw);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001170 verifyPortRemovedUpdateInQueue(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001171 reset(sw);
1172 }
1173}