blob: 339c300113d5943905747a3a14a6ecb693cc90a7 [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;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070021import static org.easymock.EasyMock.createMock;
22import static org.easymock.EasyMock.createNiceMock;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070023import static org.easymock.EasyMock.createStrictMock;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070024import 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;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070032import static org.junit.Assert.assertArrayEquals;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080033
34import java.util.ArrayList;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070035import java.util.HashSet;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080036import java.util.List;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070037import java.util.Set;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080038import java.util.concurrent.Future;
39import java.util.concurrent.TimeUnit;
40
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080041import net.floodlightcontroller.core.FloodlightContext;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070042import net.floodlightcontroller.core.FloodlightProvider;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080043import net.floodlightcontroller.core.IFloodlightProviderService;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080044import net.floodlightcontroller.core.IFloodlightProviderService.Role;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070045import net.floodlightcontroller.core.IListener;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080046import net.floodlightcontroller.core.IListener.Command;
HIGUCHI Yuta5968f722013-06-12 10:58:50 -070047import net.floodlightcontroller.core.IOFMessageListener;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080048import net.floodlightcontroller.core.IOFSwitch;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070049import net.floodlightcontroller.core.IOFSwitch.PortChangeType;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080050import net.floodlightcontroller.core.IOFSwitchListener;
Pankaj Berde6e421732013-08-14 15:17:52 -070051import net.floodlightcontroller.core.IUpdate;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080052import net.floodlightcontroller.core.internal.Controller.SwitchUpdate;
53import net.floodlightcontroller.core.internal.Controller.SwitchUpdateType;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080054import net.floodlightcontroller.core.module.FloodlightModuleContext;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080055import net.floodlightcontroller.core.test.MockThreadPoolService;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070056import net.floodlightcontroller.debugcounter.DebugCounter;
57import net.floodlightcontroller.debugcounter.IDebugCounterService;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080058import net.floodlightcontroller.restserver.IRestApiService;
59import net.floodlightcontroller.restserver.RestApiServer;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080060import net.floodlightcontroller.test.FloodlightTestCase;
61import net.floodlightcontroller.threadpool.IThreadPoolService;
Jonathan Hart23701d12014-04-03 10:45:48 -070062import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
Jonathan Hart284e70f2014-07-05 12:32:51 -070063import net.onrc.onos.core.linkdiscovery.LinkDiscoveryManager;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070064import net.onrc.onos.core.packet.ARP;
65import net.onrc.onos.core.packet.Ethernet;
66import net.onrc.onos.core.packet.IPacket;
67import net.onrc.onos.core.packet.IPv4;
68import net.onrc.onos.core.registry.IControllerRegistryService;
69import net.onrc.onos.core.registry.StandaloneRegistry;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080070
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070071import org.junit.Before;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080072import org.junit.Test;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070073import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
74import org.projectfloodlight.openflow.protocol.OFFactories;
75import org.projectfloodlight.openflow.protocol.OFFactory;
76import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
77import org.projectfloodlight.openflow.protocol.OFFlowMod;
78import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
79import org.projectfloodlight.openflow.protocol.OFPacketIn;
80import org.projectfloodlight.openflow.protocol.OFPacketInReason;
81import org.projectfloodlight.openflow.protocol.OFPortDesc;
82import org.projectfloodlight.openflow.protocol.OFPortState;
83import org.projectfloodlight.openflow.protocol.OFStatsReply;
84import org.projectfloodlight.openflow.protocol.OFType;
85import org.projectfloodlight.openflow.protocol.OFVersion;
86import org.projectfloodlight.openflow.protocol.ver10.OFStatsReplyFlagsSerializerVer10;
87import org.projectfloodlight.openflow.types.DatapathId;
88import org.projectfloodlight.openflow.types.OFBufferId;
89import org.projectfloodlight.openflow.types.OFPort;
90import org.projectfloodlight.openflow.util.HexString;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080091
92/**
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080093 * @author David Erickson (daviderickson@cs.stanford.edu)
94 */
95public class ControllerTest extends FloodlightTestCase {
Ray Milkey269ffb92014-04-03 14:43:30 -070096
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080097 private Controller controller;
98 private MockThreadPoolService tp;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070099 protected OFFactory factory10 = OFFactories.getFactory(OFVersion.OF_10);
100 private IPacket testPacket;
101 private OFPacketIn pi;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800102
103 @Override
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700104 @Before
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800105 public void setUp() throws Exception {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700106 doSetUp(Role.MASTER);
107 }
108
109 public void doSetUp(Role role) throws Exception {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800110 super.setUp();
111 FloodlightModuleContext fmc = new FloodlightModuleContext();
Ray Milkey269ffb92014-04-03 14:43:30 -0700112
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800113 FloodlightProvider cm = new FloodlightProvider();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700114
115 controller = (Controller) cm.getServiceImpls().get(
116 IFloodlightProviderService.class);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800117 fmc.addService(IFloodlightProviderService.class, controller);
Ray Milkey269ffb92014-04-03 14:43:30 -0700118
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800119 RestApiServer restApi = new RestApiServer();
120 fmc.addService(IRestApiService.class, restApi);
Ray Milkey269ffb92014-04-03 14:43:30 -0700121
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700122 // TODO replace with mock if further testing is needed.
123 DebugCounter counterService = new DebugCounter();
124 fmc.addService(IDebugCounterService.class, counterService);
125
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800126 tp = new MockThreadPoolService();
127 fmc.addService(IThreadPoolService.class, tp);
Ray Milkey269ffb92014-04-03 14:43:30 -0700128
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700129 // Following added by ONOS
130 // TODO replace with mock if further testing is needed.
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700131 StandaloneRegistry sr = new StandaloneRegistry();
Ray Milkey269ffb92014-04-03 14:43:30 -0700132 fmc.addService(IControllerRegistryService.class, sr);
Jonathan Hart220b8292013-12-07 19:25:11 -0800133 LinkDiscoveryManager linkDiscovery = new LinkDiscoveryManager();
134 fmc.addService(ILinkDiscoveryService.class, linkDiscovery);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700135
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800136 restApi.init(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800137 cm.init(fmc);
138 tp.init(fmc);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700139 sr.init(fmc);
Jonathan Hart220b8292013-12-07 19:25:11 -0800140 linkDiscovery.init(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800141 restApi.startUp(fmc);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800142 cm.startUp(fmc);
143 tp.startUp(fmc);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700144 sr.startUp(fmc);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700145 // linkDiscovery.startUp(fmc);
146
147 testPacket = new Ethernet()
148 .setSourceMACAddress("00:44:33:22:11:00")
149 .setDestinationMACAddress("00:11:22:33:44:55")
150 .setEtherType(Ethernet.TYPE_ARP)
151 .setPayload(
152 new ARP()
153 .setHardwareType(ARP.HW_TYPE_ETHERNET)
154 .setProtocolType(ARP.PROTO_TYPE_IP)
155 .setHardwareAddressLength((byte) 6)
156 .setProtocolAddressLength((byte) 4)
157 .setOpCode(ARP.OP_REPLY)
158 .setSenderHardwareAddress(
159 Ethernet.toMACAddress("00:44:33:22:11:00"))
160 .setSenderProtocolAddress(
161 IPv4.toIPv4AddressBytes("192.168.1.1"))
162 .setTargetHardwareAddress(
163 Ethernet.toMACAddress("00:11:22:33:44:55"))
164 .setTargetProtocolAddress(
165 IPv4.toIPv4AddressBytes("192.168.1.2")));
166 byte[] testPacketSerialized = testPacket.serialize();
167
168 pi = factory10.buildPacketIn()
169 .setBufferId(OFBufferId.NO_BUFFER)
170 .setInPort(OFPort.of(1))
171 .setData(testPacketSerialized)
172 .setReason(OFPacketInReason.NO_MATCH)
173 .setTotalLen((short) testPacketSerialized.length).build();
174
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800175 }
176
177 public Controller getController() {
178 return controller;
179 }
180
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700181 protected OFStatsReply getStatisticsReply(int transactionId,
182 int count, boolean moreReplies) {
183 List<OFFlowStatsEntry> statistics = new ArrayList<OFFlowStatsEntry>();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800184 for (int i = 0; i < count; ++i) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700185 statistics.add(factory10.buildFlowStatsEntry().build());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800186 }
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700187 assertEquals(statistics.size(), count);
188 OFStatsReply sr;
189 if (moreReplies) {
190 sr = (factory10.buildFlowStatsReply()
191 .setXid(transactionId)
192 .setEntries(statistics)
193 .setFlags(OFStatsReplyFlagsSerializerVer10.ofWireValue((short) 1))
194 .build());
195 }
196 else {
197 sr = (factory10.buildFlowStatsReply()
198 .setXid(transactionId)
199 .setEntries(statistics).build());
200 }
201
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800202 return sr;
203 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700204
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700205 private OFDescStatsReply createOFDescStatsReply() {
206 OFDescStatsReply desc = factory10.buildDescStatsReply()
207 .setHwDesc("")
208 .setMfrDesc("")
209 .setDpDesc("")
210 .setMfrDesc("")
211 .setSwDesc("")
212 .setSerialNum("").build();
213 return desc;
214 }
215
216 private OFFeaturesReply createOFFeaturesReply() {
217 OFFeaturesReply fr = factory10.buildFeaturesReply()
218 .setPorts(new ArrayList<OFPortDesc>())
219 .build();
220 return fr;
221
222 }
223
224 /**
225 * Set the mock expectations for sw when sw is passed to addSwitch The same
226 * expectations can be used when a new SwitchSyncRepresentation is created
227 * from the given mocked switch
228 */
229 protected void setupSwitchForAddSwitch(IOFSwitch sw, long dpid,
230 OFDescStatsReply desc, OFFeaturesReply featuresReply) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800231 String dpidString = HexString.toHexString(dpid);
Ray Milkey269ffb92014-04-03 14:43:30 -0700232
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700233 if (desc == null) {
234 desc = createOFDescStatsReply();
235 }
236 if (featuresReply == null) {
237 featuresReply = createOFFeaturesReply();
238 featuresReply.createBuilder().setDatapathId(DatapathId.of(dpid));
239
240 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800241 expect(sw.getId()).andReturn(dpid).anyTimes();
242 expect(sw.getStringId()).andReturn(dpidString).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800243 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700244
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800245 /**
246 * Run the controller's main loop so that updates are processed
247 */
248 protected class ControllerRunThread extends Thread {
Yuta HIGUCHI0b7c19e2014-07-21 23:33:20 -0700249 @Override
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800250 public void run() {
251 controller.openFlowPort = 0; // Don't listen
252 controller.run();
253 }
254 }
255
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700256 @SuppressWarnings("unchecked")
257 private <T> void setupListenerOrdering(IListener<T> listener) {
258 listener.isCallbackOrderingPostreq((T) anyObject(),
259 anyObject(String.class));
260 expectLastCall().andReturn(false).anyTimes();
261
262 listener.isCallbackOrderingPrereq((T) anyObject(),
263 anyObject(String.class));
264 expectLastCall().andReturn(false).anyTimes();
265 }
266
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800267 /**
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700268 * Verify that a listener that throws an exception halts further execution,
269 * and verify that the Commands STOP and CONTINUE are honored.
270 *
271 * @throws Exception
272 */
273
274 @Test
275 public void testHandleMessagesNoListeners() throws Exception {
276 IOFSwitch sw = createMock(IOFSwitch.class);
277 expect(sw.getId()).andReturn(0L).anyTimes();
278 expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
279 expect(sw.getOFVersion()).andReturn(OFVersion.OF_10).anyTimes();
280 replay(sw);
281 controller.handleMessage(sw, pi, null);
282 verify(sw);
283 }
284
285 /**
286 * Test message dispatching to OFMessageListeners. Test ordering of
287 * listeners for different types (we do this implicitly by using STOP and
288 * CONTINUE and making sure the processing stops at the right place) Verify
289 * that a listener that throws an exception halts further execution, and
290 * verify that the Commands STOP and CONTINUE are honored.
Ray Milkey269ffb92014-04-03 14:43:30 -0700291 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800292 * @throws Exception
293 */
294 @Test
295 public void testHandleMessages() throws Exception {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800296 controller.removeOFMessageListeners(OFType.PACKET_IN);
297
298 IOFSwitch sw = createMock(IOFSwitch.class);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700299 expect(sw.getId()).andReturn(0L).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800300 expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700301 expect(sw.getOFVersion()).andReturn(OFVersion.OF_10).anyTimes();
302 // Setup listener orderings
303 IOFMessageListener test1 = createMock(IOFMessageListener.class);
304 expect(test1.getName()).andReturn("test1").anyTimes();
305 setupListenerOrdering(test1);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800306
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700307 IOFMessageListener test2 = createMock(IOFMessageListener.class);
308 expect(test2.getName()).andReturn("test2").anyTimes();
309 // using a postreq and a prereq ordering here
310 expect(test2.isCallbackOrderingPrereq(OFType.PACKET_IN, "test1"))
311 .andReturn(true).atLeastOnce();
312 expect(test2.isCallbackOrderingPostreq(OFType.FLOW_MOD, "test1"))
313 .andReturn(true).atLeastOnce();
314 setupListenerOrdering(test2);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800315
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700316 IOFMessageListener test3 = createMock(IOFMessageListener.class);
317 expect(test3.getName()).andReturn("test3").anyTimes();
318 expect(test3.isCallbackOrderingPrereq((OFType) anyObject(), eq("test1")))
319 .andReturn(true).atLeastOnce();
320 expect(test3.isCallbackOrderingPrereq((OFType) anyObject(), eq("test2")))
321 .andReturn(true).atLeastOnce();
322 setupListenerOrdering(test3);
323
324 // Ordering: PacketIn: test1 -> test2 -> test3
325 // FlowMod: test2 -> test1
326 replay(test1, test2, test3);
327 controller.addOFMessageListener(OFType.PACKET_IN, test1);
328 controller.addOFMessageListener(OFType.PACKET_IN, test3);
329 controller.addOFMessageListener(OFType.PACKET_IN, test2);
330 controller.addOFMessageListener(OFType.FLOW_MOD, test1);
331 controller.addOFMessageListener(OFType.FLOW_MOD, test2);
332 verify(test1);
333 verify(test2);
334 verify(test3);
335
336 replay(sw);
337
338 // ------------------
339 // Test PacketIn handling: all listeners return CONTINUE
340 reset(test1, test2, test3);
341 expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class)))
342 .andReturn(Command.CONTINUE);
343 expect(test2.receive(eq(sw), eq(pi), isA(FloodlightContext.class)))
344 .andReturn(Command.CONTINUE);
345 expect(test3.receive(eq(sw), eq(pi), isA(FloodlightContext.class)))
346 .andReturn(Command.CONTINUE);
347 replay(test1, test2, test3);
348 controller.handleMessage(sw, pi, null);
349 verify(test1);
350 verify(test2);
351 verify(test3);
352
353 // ------------------
354 // Test PacketIn handling: with a thrown exception.
355 reset(test1, test2, test3);
356 expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class)))
357 .andReturn(Command.CONTINUE);
358 expect(test2.receive(eq(sw), eq(pi), isA(FloodlightContext.class)))
359 .andThrow(new RuntimeException("This is NOT an error! We " +
360 "are testing exception catching."));
361 // expect no calls to test3.receive() since test2.receive throws
362 // an exception
363 replay(test1, test2, test3);
364 try {
365 controller.handleMessage(sw, pi, null);
366 fail("Expected exception was not thrown!");
367 } catch (RuntimeException e) {
368 assertTrue("The caught exception was not the expected one",
369 e.getMessage().startsWith("This is NOT an error!"));
370 }
371 verify(test1);
372 verify(test2);
373 verify(test3);
374
375 // ------------------
376 // Test PacketIn handling: test1 return Command.STOP
377 reset(test1, test2, test3);
378 expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class)))
379 .andReturn(Command.STOP);
380 // expect no calls to test3.receive() and test2.receive since
381 // test1.receive returns STOP
382 replay(test1, test2, test3);
383 controller.handleMessage(sw, pi, null);
384 verify(test1);
385 verify(test2);
386 verify(test3);
387
388 OFFlowMod fm = factory10.buildFlowAdd().build();
389
390 // ------------------
391 // Test FlowMod handling: all listeners return CONTINUE
392 reset(test1, test2, test3);
393 expect(test1.receive(eq(sw), eq(fm), isA(FloodlightContext.class)))
394 .andReturn(Command.CONTINUE);
395 expect(test2.receive(eq(sw), eq(fm), isA(FloodlightContext.class)))
396 .andReturn(Command.CONTINUE);
397 // test3 is not a listener for FlowMod
398 replay(test1, test2, test3);
399 controller.handleMessage(sw, fm, null);
400 verify(test1);
401 verify(test2);
402 verify(test3);
403
404 // ------------------
405 // Test FlowMod handling: test2 (first listener) return STOP
406 reset(test1, test2, test3);
407 expect(test2.receive(eq(sw), eq(fm), isA(FloodlightContext.class)))
408 .andReturn(Command.STOP);
409 // test2 will not be called
410 // test3 is not a listener for FlowMod
411 replay(test1, test2, test3);
412 controller.handleMessage(sw, fm, null);
413 verify(test1);
414 verify(test2);
415 verify(test3);
416
417 verify(sw);
418 }
419
420 @Test
421 public void testHandleMessageWithContext() throws Exception {
422 IOFSwitch sw = createMock(IOFSwitch.class);
423 expect(sw.getId()).andReturn(0L).anyTimes();
424 expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes();
425 expect(sw.getOFVersion()).andReturn(OFVersion.OF_10).anyTimes();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800426
427 IOFMessageListener test1 = createMock(IOFMessageListener.class);
428 expect(test1.getName()).andReturn("test1").anyTimes();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700429 expect(test1.isCallbackOrderingPrereq((OFType) anyObject(),
430 (String) anyObject()))
431 .andReturn(false).anyTimes();
432 expect(test1.isCallbackOrderingPostreq((OFType) anyObject(),
433 (String) anyObject()))
434 .andReturn(false).anyTimes();
435 FloodlightContext cntx = new FloodlightContext();
436 expect(test1.receive(same(sw), same(pi), same(cntx)))
437 .andReturn(Command.CONTINUE);
438
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800439 IOFMessageListener test2 = createMock(IOFMessageListener.class);
440 expect(test2.getName()).andReturn("test2").anyTimes();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700441 expect(test2.isCallbackOrderingPrereq((OFType) anyObject(),
442 (String) anyObject()))
443 .andReturn(false).anyTimes();
444 expect(test2.isCallbackOrderingPostreq((OFType) anyObject(),
445 (String) anyObject()))
446 .andReturn(false).anyTimes();
447 // test2 will not receive any message!
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800448
449 replay(test1, test2, sw);
450 controller.addOFMessageListener(OFType.PACKET_IN, test1);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700451 controller.addOFMessageListener(OFType.ERROR, test2);
452 controller.handleMessage(sw, pi, cntx);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800453 verify(test1, test2, sw);
454
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700455 Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
456 IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
457 assertArrayEquals(testPacket.serialize(), eth.serialize());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800458 }
459
460 public class FutureFetcher<E> implements Runnable {
461 public E value;
462 public Future<E> future;
463
464 public FutureFetcher(Future<E> future) {
465 this.future = future;
466 }
467
468 @Override
469 public void run() {
470 try {
471 value = future.get();
472 } catch (Exception e) {
473 throw new RuntimeException(e);
474 }
475 }
476
477 /**
478 * @return the value
479 */
480 public E getValue() {
481 return value;
482 }
483
484 /**
485 * @return the future
486 */
487 public Future<E> getFuture() {
488 return future;
489 }
490 }
491
492 /**
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800493 * @throws Exception
494 */
495 @Test
496 public void testOFStatisticsFuture() throws Exception {
497 // Test for a single stats reply
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700498 OFSwitchImplBase sw = createMock(OFSwitchImplBase.class);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800499 sw.cancelStatisticsReply(1);
500 OFStatisticsFuture sf = new OFStatisticsFuture(tp, sw, 1);
501
502 replay(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700503 List<OFStatsReply> stats;
504 FutureFetcher<List<OFStatsReply>> ff = new FutureFetcher<List<OFStatsReply>>(sf);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800505 Thread t = new Thread(ff);
506 t.start();
507 sf.deliverFuture(sw, getStatisticsReply(1, 10, false));
508
509 t.join();
510 stats = ff.getValue();
511 verify(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700512 // TODO: temporary fix: size = 1 ?
513 assertEquals(1, stats.size());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800514
515 // Test multiple stats replies
516 reset(sw);
517 sw.cancelStatisticsReply(1);
518
519 sf = new OFStatisticsFuture(tp, sw, 1);
520
521 replay(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700522 ff = new FutureFetcher<List<OFStatsReply>>(sf);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800523 t = new Thread(ff);
524 t.start();
525 sf.deliverFuture(sw, getStatisticsReply(1, 10, true));
526 sf.deliverFuture(sw, getStatisticsReply(1, 5, false));
527 t.join();
528
529 stats = sf.get();
530 verify(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700531 // TODO: temporary fix: size = 2 ?
532 assertEquals(2, stats.size());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800533
534 // Test cancellation
535 reset(sw);
536 sw.cancelStatisticsReply(1);
537 sf = new OFStatisticsFuture(tp, sw, 1);
538
539 replay(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700540 ff = new FutureFetcher<List<OFStatsReply>>(sf);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800541 t = new Thread(ff);
542 t.start();
543 sf.cancel(true);
544 t.join();
545
546 stats = sf.get();
547 verify(sw);
548 assertEquals(0, stats.size());
549
550 // Test self timeout
551 reset(sw);
552 sw.cancelStatisticsReply(1);
553 sf = new OFStatisticsFuture(tp, sw, 1, 75, TimeUnit.MILLISECONDS);
554
555 replay(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700556 ff = new FutureFetcher<List<OFStatsReply>>(sf);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800557 t = new Thread(ff);
558 t.start();
559 t.join(2000);
560
561 stats = sf.get();
562 verify(sw);
563 assertEquals(0, stats.size());
564 }
565
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700566 /**
567 * Test switchActivated for a new switch, i.e., a switch that was not
568 * previously known to the controller cluser. We expect that all flow mods
569 * are cleared and we expect a switchAdded
570 */
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800571 @Test
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700572 public void testNewSwitchActivated() throws Exception {
573 controller.setAlwaysClearFlowsOnSwActivate(false);
574 controller.setAlwaysClearFlowsOnSwAdd(false);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800575
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700576 IOFSwitch sw = createMock(IOFSwitch.class);
577 expect(sw.getPorts()).andReturn(new HashSet<OFPortDesc>()).anyTimes();
578 setupSwitchForAddSwitch(sw, 0L, null, null);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800579
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700580 // strict mock. Order of events matters!
581 IOFSwitchListener listener = createStrictMock(IOFSwitchListener.class);
582 listener.switchActivatedMaster(0L);
583 expectLastCall().once();
584 replay(listener);
585 controller.addOFSwitchListener(listener);
586
587 replay(sw);
588 controller.addConnectedSwitch(0L, new OFChannelHandler(controller));
589 controller.addActivatedMasterSwitch(0L, sw);
590 verify(sw);
591 assertEquals(sw, controller.getMasterSwitch(0L));
592 controller.processUpdateQueueForTesting();
593 verify(listener);
594 }
595
596 /**
597 * Test switchActivated for a new switch while in equal: a no-op
598 */
599 @Test
600 public void testNewSwitchActivatedWhileSlave() throws Exception {
601 doSetUp(Role.EQUAL);
602 IOFSwitch sw = createMock(IOFSwitch.class);
603
604 IOFSwitchListener listener = createMock(IOFSwitchListener.class);
605 controller.addOFSwitchListener(listener);
606
607 replay(sw, listener); // nothing recorded
608 controller.addConnectedSwitch(0L, new OFChannelHandler(controller));
609 controller.addActivatedEqualSwitch(0L, sw);
610 verify(sw);
611 verify(listener);
612 }
613
614 /**
615 * Disconnect a switch. normal program flow
616 */
617 @Test
618 private void doTestSwitchConnectReconnect(boolean reconnect)
619 throws Exception {
620 IOFSwitch sw = doActivateNewSwitch(1L, null, null);
621 expect(sw.getId()).andReturn(1L).anyTimes();
622 expect(sw.getStringId()).andReturn(HexString.toHexString(1L)).anyTimes();
623 sw.setConnected(false);
624 expectLastCall().once();
625 sw.cancelAllStatisticsReplies();
626 expectLastCall().once();
627 IOFSwitchListener listener = createMock(IOFSwitchListener.class);
628 listener.switchDisconnected(1L);
629 expectLastCall().once();
630 controller.addOFSwitchListener(listener);
631 replay(sw, listener);
632 controller.removeConnectedSwitch(1L);
633 controller.processUpdateQueueForTesting();
634 verify(sw, listener);
635
636 assertNull(controller.getSwitch(1L));
637 if (reconnect) {
638 controller.removeOFSwitchListener(listener);
639 sw = doActivateOldSwitch(1L, null, null);
640 }
641 }
642
643 @Test
644 public void testSwitchDisconnected() throws Exception {
645 doTestSwitchConnectReconnect(false);
646 }
647
648 /**
649 * Disconnect a switch and reconnect, verify no clearAllFlowmods()
650 */
651 @Test
652 public void testSwitchReconnect() throws Exception {
653 doTestSwitchConnectReconnect(true);
654 }
655
656 /* /**
657 * Remove a nonexisting switch. should be ignored
658 */
659 @Test
660 public void testNonexistingSwitchDisconnected() throws Exception {
661 IOFSwitch sw = createMock(IOFSwitch.class);
662 expect(sw.getId()).andReturn(1L).anyTimes();
663 expect(sw.getStringId()).andReturn(HexString.toHexString(1L)).anyTimes();
664 IOFSwitchListener listener = createMock(IOFSwitchListener.class);
665 controller.addOFSwitchListener(listener);
666 replay(sw, listener);
667 controller.removeConnectedSwitch(sw.getId());
668 // controller.processUpdateQueueForTesting();
669 verify(sw, listener);
670
671 assertNull(controller.getSwitch(1L));
672 }
673
674 /**
675 * Try to activate a switch that's already active (which can happen if two
676 * different switches have the same DPIP or if a switch reconnects while the
677 * old TCP connection is still alive
678 */
679 // TODO: I do not if it represents the expected behaviour
680 @Test
681 public void testSwitchActivatedWithAlreadyActiveSwitch() throws Exception {
682 OFDescStatsReply oldDesc = createOFDescStatsReply();
683 oldDesc.createBuilder().setDpDesc("Ye Olde Switch");
684 OFDescStatsReply newDesc = createOFDescStatsReply();
685 oldDesc.createBuilder().setDpDesc("The new Switch");
686 OFFeaturesReply featuresReply = createOFFeaturesReply();
687
688 // Setup: add a switch to the controller
689 IOFSwitch oldsw = createMock(IOFSwitch.class);
690 setupSwitchForAddSwitch(oldsw, 0L, oldDesc, featuresReply);
691 expect(oldsw.getPorts()).andReturn(new HashSet<OFPortDesc>()).anyTimes();
692 // oldsw.clearAllFlowMods();
693 // expectLastCall().once();
694 replay(oldsw);
695 controller.addConnectedSwitch(oldsw.getId(), new OFChannelHandler(controller));
696 controller.addActivatedMasterSwitch(oldsw.getId(), oldsw);
697 verify(oldsw);
698 // drain the queue, we don't care what's in it
699 controller.processUpdateQueueForTesting();
700 assertEquals(oldsw, controller.getSwitch(0L));
701
702 // Now the actual test: add a new switch with the same dpid to
703 // the controller
704 reset(oldsw);
705 expect(oldsw.getId()).andReturn(0L).anyTimes();
706 // oldsw.cancelAllStatisticsReplies();
707 // expectLastCall().once();
708 // oldsw.disconnectOutputStream();
709 // expectLastCall().once();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800710
711 IOFSwitch newsw = createMock(IOFSwitch.class);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700712 setupSwitchForAddSwitch(newsw, 0L, newDesc, featuresReply);
713 // newsw.clearAllFlowMods();
714 // expectLastCall().once();
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800715
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700716 // Strict mock. We need to get the removed notification before the
717 // add notification
718 IOFSwitchListener listener = createStrictMock(IOFSwitchListener.class);
719 // listener.switchDisconnected(0L);
720 // listener.switchActivatedMaster(0L);
721 replay(listener);
722 controller.addOFSwitchListener(listener);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800723
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700724 replay(newsw, oldsw);
725 controller.addActivatedMasterSwitch(0L, newsw);
726 verify(newsw, oldsw);
727
728 assertEquals(oldsw, controller.getSwitch(0L));
729 controller.processUpdateQueueForTesting();
730 verify(listener);
731 }
732
733 /**
734 * Tests that you can't remove a switch from the map returned by
735 * getSwitches() (because getSwitches should return an unmodifiable map)
736 */
737 @Test
738 public void testRemoveActiveSwitch() {
739 IOFSwitch sw = createNiceMock(IOFSwitch.class);
740 expect(sw.getPorts()).andReturn(new ArrayList<OFPortDesc>()).anyTimes();
741 setupSwitchForAddSwitch(sw, 1L, null, null);
742 replay(sw);
743 controller.addConnectedSwitch(1L, new OFChannelHandler(controller));
744 controller.addActivatedMasterSwitch(1L, sw);
745 assertEquals(sw, getController().getSwitch(1L));
746 controller.getAllSwitchDpids().remove(1L);
747 assertEquals(sw, getController().getSwitch(1L));
748 verify(sw);
749 // we don't care for updates. drain queue.
750 controller.processUpdateQueueForTesting();
751 }
752
753 /**
754 * Create and activate a switch, either completely new or reconnected The
755 * mocked switch instance will be returned. It wil be reset.
756 */
757 private IOFSwitch doActivateSwitchInt(long dpid,
758 OFDescStatsReply desc,
759 OFFeaturesReply featuresReply,
760 boolean clearFlows)
761 throws Exception {
762 controller.setAlwaysClearFlowsOnSwActivate(false);
763
764 IOFSwitch sw = createMock(IOFSwitch.class);
765 if (featuresReply == null) {
766 featuresReply = createOFFeaturesReply();
767 featuresReply.createBuilder().setDatapathId(DatapathId.of(dpid));
768 }
769 if (desc == null) {
770 desc = createOFDescStatsReply();
771 }
772 setupSwitchForAddSwitch(sw, dpid, desc, featuresReply);
773 if (clearFlows) {
774 sw.clearAllFlowMods();
775 expectLastCall().once();
776 }
777 expect(sw.getPorts()).andReturn(new HashSet<OFPortDesc>()).anyTimes();
778
779 replay(sw);
780 controller.addConnectedSwitch(dpid, new OFChannelHandler(controller));
781 controller.addActivatedMasterSwitch(dpid, sw);
782 verify(sw);
783 assertEquals(sw, controller.getSwitch(dpid));
784 // drain updates and ignore
785 controller.processUpdateQueueForTesting();
786
787 // SwitchSyncRepresentation storedSwitch = storeClient.getValue(dpid);
788 // assertEquals(featuresReply, storedSwitch.getFeaturesReply());
789 // assertEquals(desc, storedSwitch.getDescription());
790 reset(sw);
791 return sw;
792 }
793
794 /**
795 * Create and activate a new switch with the given dpid, features reply and
796 * description. If description and/or features reply are null we'll allocate
797 * the default one The mocked switch instance will be returned. It wil be
798 * reset.
799 */
800 private IOFSwitch doActivateNewSwitch(long dpid,
801 OFDescStatsReply desc,
802 OFFeaturesReply featuresReply)
803 throws Exception {
804 return doActivateSwitchInt(dpid, desc, featuresReply, false);
805 }
806
807 /**
808 * Create and activate a switch that's just been disconnected. The mocked
809 * switch instance will be returned. It wil be reset.
810 */
811 private IOFSwitch doActivateOldSwitch(long dpid,
812 OFDescStatsReply desc,
813 OFFeaturesReply featuresReply)
814 throws Exception {
815 return doActivateSwitchInt(dpid, desc, featuresReply, false);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800816 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700817
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800818 @Test
819 public void testUpdateQueue() throws Exception {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700820 class DummySwitchListener implements IOFSwitchListener {
821 public int nAddedMaster;
822 public int nAddedEqual;
823 public int nDisconnected;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800824 public int nPortChanged;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700825 public int nPortAdded;
826 public int nPortDeleted;
Ray Milkey269ffb92014-04-03 14:43:30 -0700827
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800828 public DummySwitchListener() {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700829 nAddedMaster = 0;
830 nAddedEqual = 0;
831 nDisconnected = 0;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800832 nPortChanged = 0;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700833 nPortAdded = 0;
834 nPortDeleted = 0;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800835 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700836
Yuta HIGUCHI0b7c19e2014-07-21 23:33:20 -0700837 @Override
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800838 public String getName() {
839 return "dummy";
840 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700841
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800842 @Override
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700843 public void switchActivatedMaster(long swId) {
844 nAddedMaster++;
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800845 notifyAll();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700846
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800847 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700848
849 @Override
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700850 public void switchActivatedEqual(long swId) {
851 nAddedEqual++;
852 notifyAll();
853
854 }
855
856 @Override
857 public void switchMasterToEqual(long swId) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700858 // TODO Auto-generated method stub
859
860 }
861
862 @Override
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700863 public void switchEqualToMaster(long swId) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700864 // TODO Auto-generated method stub
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700865 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700866
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700867 @Override
868 public void switchDisconnected(long swId) {
869 nDisconnected++;
870 notifyAll();
871
872 }
873
874 @Override
875 public void switchPortChanged(long swId, OFPortDesc port,
876 PortChangeType changeType) {
877 switch (changeType) {
878 case ADD:
879 nPortAdded++;
880 notifyAll();
881 break;
882 case DELETE:
883 nPortDeleted++;
884 notifyAll();
885 break;
886
887 case OTHER_UPDATE:
888 nPortChanged++;
889 notifyAll();
890 break;
891
892 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700893 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800894 }
895 DummySwitchListener switchListener = new DummySwitchListener();
896 IOFSwitch sw = createMock(IOFSwitch.class);
Jonathan Hart220b8292013-12-07 19:25:11 -0800897 expect(sw.getId()).andReturn(1L).anyTimes();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700898 expect(sw.getPort(1)).andReturn(factory10.buildPortDesc().build()).anyTimes();
Jonathan Hart220b8292013-12-07 19:25:11 -0800899 replay(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800900 ControllerRunThread t = new ControllerRunThread();
901 t.start();
Ray Milkey269ffb92014-04-03 14:43:30 -0700902
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800903 controller.addOFSwitchListener(switchListener);
Ray Milkey269ffb92014-04-03 14:43:30 -0700904 synchronized (switchListener) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700905 controller.updates.put(controller.new SwitchUpdate(sw.getId(),
906 Controller.SwitchUpdateType.ACTIVATED_MASTER));
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800907 switchListener.wait(500);
Ray Milkey269ffb92014-04-03 14:43:30 -0700908 assertTrue("IOFSwitchListener.addedSwitch() was not called",
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700909 switchListener.nAddedMaster == 1);
910 controller.addOFSwitchListener(switchListener);
911 synchronized (switchListener) {
912 controller.updates.put(controller.new SwitchUpdate(sw.getId(),
913 Controller.SwitchUpdateType.ACTIVATED_EQUAL));
914 switchListener.wait(500);
915 assertTrue("IOFSwitchListener.addedSwitch() was not called",
916 switchListener.nAddedEqual == 1);
917 controller.updates.put(controller.new SwitchUpdate(sw.getId(),
918 Controller.SwitchUpdateType.DISCONNECTED));
919 switchListener.wait(500);
920 assertTrue("IOFSwitchListener.removedSwitch() was not called",
921 switchListener.nDisconnected == 1);
922 controller.updates.put(controller.new SwitchUpdate(sw.getId(),
923 Controller.SwitchUpdateType.PORTCHANGED, sw.getPort(1),
924 PortChangeType.ADD));
925 switchListener.wait(500);
926 assertTrue(
927 "IOFSwitchListener.switchPortChanged() with PortChangeType.ADD was not called",
928 switchListener.nPortAdded == 1);
929 controller.updates.put(controller.new SwitchUpdate(sw.getId(),
930 Controller.SwitchUpdateType.PORTCHANGED, sw.getPort(1),
931 PortChangeType.DELETE));
932 switchListener.wait(500);
933 assertTrue(
934 "IOFSwitchListener.switchPortChanged() with PortChangeType.DELETE was not called",
935 switchListener.nPortDeleted == 1);
936 controller.updates.put(controller.new SwitchUpdate(sw.getId(),
937 Controller.SwitchUpdateType.PORTCHANGED, sw.getPort(1),
938 PortChangeType.OTHER_UPDATE));
939 switchListener.wait(500);
940 assertTrue(
941 "IOFSwitchListener.switchPortChanged() with PortChangeType.OTHER_UPDATE was not called",
942 switchListener.nPortChanged == 1);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800943 }
944 }
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800945 }
946
Ray Milkey269ffb92014-04-03 14:43:30 -0700947
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800948 public void verifyPortChangedUpdateInQueue(IOFSwitch sw) throws Exception {
949 assertEquals(1, controller.updates.size());
950 IUpdate update = controller.updates.take();
951 assertEquals(true, update instanceof SwitchUpdate);
Ray Milkey269ffb92014-04-03 14:43:30 -0700952 SwitchUpdate swUpdate = (SwitchUpdate) update;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700953 assertEquals(sw.getId(), swUpdate.getSwId());
954 assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.getSwitchUpdateType());
955 assertEquals(PortChangeType.OTHER_UPDATE, swUpdate.getPortChangeType());
956 }
957
958 public void verifyPortDownUpdateInQueue(IOFSwitch sw) throws Exception {
959 assertEquals(1, controller.updates.size());
960 IUpdate update = controller.updates.take();
961 assertEquals(true, update instanceof SwitchUpdate);
962 SwitchUpdate swUpdate = (SwitchUpdate) update;
963 assertEquals(sw.getId(), swUpdate.getSwId());
964 assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.getSwitchUpdateType());
965 assertEquals(PortChangeType.DOWN, swUpdate.getPortChangeType());
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800966 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700967
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700968 public void verifyPortAddedUpdateInQueue(IOFSwitch sw) throws Exception {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700969 assertEquals(1, controller.updates.size());
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700970 IUpdate update = controller.updates.take();
971 assertEquals(true, update instanceof SwitchUpdate);
Ray Milkey269ffb92014-04-03 14:43:30 -0700972 SwitchUpdate swUpdate = (SwitchUpdate) update;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700973 assertEquals(sw.getId(), swUpdate.getSwId());
974 assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.getSwitchUpdateType());
975 assertEquals(PortChangeType.ADD, swUpdate.getPortChangeType());
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700976 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700977
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700978 public void verifyPortRemovedUpdateInQueue(IOFSwitch sw) throws Exception {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700979 assertEquals(1, controller.updates.size());
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700980 IUpdate update = controller.updates.take();
981 assertEquals(true, update instanceof SwitchUpdate);
Ray Milkey269ffb92014-04-03 14:43:30 -0700982 SwitchUpdate swUpdate = (SwitchUpdate) update;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700983 assertEquals(sw.getId(), swUpdate.getSwId());
984 assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.getSwitchUpdateType());
985 assertEquals(PortChangeType.DELETE, swUpdate.getPortChangeType());
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -0700986 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700987
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700988 // * Test handlePortStatus()
989 // *
Ray Milkey269ffb92014-04-03 14:43:30 -0700990 @Test
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800991 public void testHandlePortStatus() throws Exception {
992 IOFSwitch sw = createMock(IOFSwitch.class);
Jonathan Hart220b8292013-12-07 19:25:11 -0800993 expect(sw.getId()).andReturn(1L).anyTimes();
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700994 //expect(sw.getPorts()).andReturn(new HashSet<OFPortDesc>()).anyTimes();
995 OFPortDesc port = factory10.buildPortDesc()
996 .setName("myPortName1")
997 .setPortNo(OFPort.of(42))
998 .build();
Ray Milkey269ffb92014-04-03 14:43:30 -0700999
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001000 controller.connectedSwitches.put(1L, new OFChannelHandler(controller));
1001 controller.activeMasterSwitches.put(1L, sw);
Ray Milkey269ffb92014-04-03 14:43:30 -07001002
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001003 replay(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001004 controller.notifyPortChanged(sw.getId(), port, PortChangeType.ADD);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001005 verify(sw);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001006 verifyPortAddedUpdateInQueue(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001007 reset(sw);
Ray Milkey269ffb92014-04-03 14:43:30 -07001008
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001009 expect(sw.getId()).andReturn(1L).anyTimes();
1010
1011 Set<OFPortState> ofPortStates = new HashSet<OFPortState>();
1012 ofPortStates.add(OFPortState.LINK_DOWN);
1013 port.createBuilder().setState(ofPortStates);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001014 replay(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001015 controller.notifyPortChanged(sw.getId(), port, PortChangeType.OTHER_UPDATE);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001016 verify(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001017 verifyPortChangedUpdateInQueue(sw);
1018 reset(sw);
1019 ofPortStates = new HashSet<OFPortState>();
1020 port.createBuilder().setState(ofPortStates);
1021
1022 expect(sw.getId()).andReturn(1L).anyTimes();
1023
1024 port.createBuilder().setState(ofPortStates);
1025 replay(sw);
1026 controller.notifyPortChanged(sw.getId(), port, PortChangeType.DOWN);
1027 verify(sw);
1028 verifyPortDownUpdateInQueue(sw);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001029 reset(sw);
Ray Milkey269ffb92014-04-03 14:43:30 -07001030
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001031 expect(sw.getId()).andReturn(1L).anyTimes();
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001032 replay(sw);
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001033 controller.notifyPortChanged(sw.getId(), port, PortChangeType.DELETE);
HIGUCHI Yuta21fd07f2013-06-28 11:24:14 -07001034 verify(sw);
1035 verifyPortRemovedUpdateInQueue(sw);
1036 reset(sw);
Ray Milkey269ffb92014-04-03 14:43:30 -07001037
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001038 }
1039}