blob: f267923770f609ba7e4c547c09d8f47c46b6a30d [file] [log] [blame]
tom9ccd7812014-08-25 22:43:19 -07001package org.onlab.onos.of.controller.impl.internal;
alshabib3b554cf2014-08-18 11:19:50 -05002
3import static org.easymock.EasyMock.capture;
4import static org.easymock.EasyMock.createMock;
5import static org.easymock.EasyMock.expect;
6import static org.easymock.EasyMock.expectLastCall;
7import static org.easymock.EasyMock.replay;
8import static org.easymock.EasyMock.reset;
9import static org.easymock.EasyMock.verify;
10import static org.junit.Assert.assertEquals;
11import static org.junit.Assert.assertFalse;
12import static org.junit.Assert.assertTrue;
13
14import java.io.IOException;
15import java.util.ArrayList;
16import java.util.Collections;
17import java.util.HashSet;
18import java.util.List;
19import java.util.Set;
20
tom9ccd7812014-08-25 22:43:19 -070021import org.onlab.onos.of.controller.impl.IOFSwitch;
22import org.onlab.onos.of.controller.impl.Role;
23import org.onlab.onos.of.controller.impl.debugcounter.DebugCounter;
24import org.onlab.onos.of.controller.impl.debugcounter.IDebugCounterService;
25import org.onlab.onos.of.controller.impl.internal.OFChannelHandler.RoleRecvStatus;
alshabib3b554cf2014-08-18 11:19:50 -050026
27import org.easymock.Capture;
28import org.easymock.CaptureType;
29import org.jboss.netty.channel.Channel;
30import org.jboss.netty.channel.ChannelHandlerContext;
31import org.jboss.netty.channel.ChannelPipeline;
32import org.jboss.netty.channel.ChannelStateEvent;
33import org.jboss.netty.channel.ExceptionEvent;
34import org.jboss.netty.channel.MessageEvent;
35import org.junit.After;
36import org.junit.Before;
37import org.junit.Test;
38import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
39import org.projectfloodlight.openflow.protocol.OFExperimenter;
40import org.projectfloodlight.openflow.protocol.OFFactories;
41import org.projectfloodlight.openflow.protocol.OFFactory;
42import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
43import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
44import org.projectfloodlight.openflow.protocol.OFHelloElem;
45import org.projectfloodlight.openflow.protocol.OFMessage;
46import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
47import org.projectfloodlight.openflow.protocol.OFPacketIn;
48import org.projectfloodlight.openflow.protocol.OFPacketInReason;
49import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
50import org.projectfloodlight.openflow.protocol.OFSetConfig;
51import org.projectfloodlight.openflow.protocol.OFStatsReply;
52import org.projectfloodlight.openflow.protocol.OFStatsRequest;
53import org.projectfloodlight.openflow.protocol.OFStatsType;
54import org.projectfloodlight.openflow.protocol.OFType;
55import org.projectfloodlight.openflow.protocol.OFVersion;
56import org.projectfloodlight.openflow.types.DatapathId;
57import org.projectfloodlight.openflow.types.U32;
58
59/**
60 * Channel handler deals with the switch connection and dispatches
61 * switch messages to the appropriate locations. These Unit Testing cases
62 * test the channeler state machine and role changer. In the first release,
63 * we will focus on OF version 1.0. we will add the testing case for
64 * version 1.3 later.
65 */
66public class OFChannelHandlerTest {
67 private Controller controller;
68 private IDebugCounterService debugCounterService;
69 private OFChannelHandler handler;
70 private Channel channel;
71 private ChannelHandlerContext ctx;
72 private MessageEvent messageEvent;
73 private ChannelStateEvent channelStateEvent;
74 private ChannelPipeline pipeline;
75 private Capture<ExceptionEvent> exceptionEventCapture;
76 private Capture<List<OFMessage>> writeCapture;
77 private OFFeaturesReply featuresReply;
78 private Set<Integer> seenXids = null;
79 private IOFSwitch swImplBase;
80 private OFVersion ofVersion = OFVersion.OF_10;
81 private OFFactory factory13;
82 private OFFactory factory10;
83 private OFFactory factory;
84
85 @Before
86 public void setUp() throws Exception {
87 controller = createMock(Controller.class);
88 ctx = createMock(ChannelHandlerContext.class);
89 channelStateEvent = createMock(ChannelStateEvent.class);
90 channel = createMock(Channel.class);
91 messageEvent = createMock(MessageEvent.class);
92 exceptionEventCapture = new Capture<ExceptionEvent>(CaptureType.ALL);
93 pipeline = createMock(ChannelPipeline.class);
94 writeCapture = new Capture<List<OFMessage>>(CaptureType.ALL);
95 swImplBase = createMock(IOFSwitch.class);
96 seenXids = null;
97 factory13 = OFFactories.getFactory(OFVersion.OF_13);
98 factory10 = OFFactories.getFactory(OFVersion.OF_10);
99 factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
100
101 // TODO: should mock IDebugCounterService and make sure
102 // the expected counters are updated.
103 debugCounterService = new DebugCounter();
104 Controller.Counters counters =
105 new Controller.Counters();
106 counters.createCounters(debugCounterService);
107 expect(controller.getCounters()).andReturn(counters).anyTimes();
108 expect(controller.getOFMessageFactory10()).andReturn(factory10)
109 .anyTimes();
110 expect(controller.getOFMessageFactory13()).andReturn(factory13)
111 .anyTimes();
112 expect(controller.addConnectedSwitch(2000, handler)).andReturn(true)
113 .anyTimes();
114 replay(controller);
115 handler = new OFChannelHandler(controller);
116 verify(controller);
117 reset(controller);
118
119 resetChannel();
120
121 // replay controller. Reset it if you need more specific behavior
122 replay(controller);
123
124 // replay switch. Reset it if you need more specific behavior
125 replay(swImplBase);
126
127 // Mock ctx and channelStateEvent
128 expect(ctx.getChannel()).andReturn(channel).anyTimes();
129 expect(channelStateEvent.getChannel()).andReturn(channel).anyTimes();
130 replay(ctx, channelStateEvent);
131
132 /* Setup an exception event capture on the channel. Right now
133 * we only expect exception events to be send up the channel.
134 * However, it's easy to extend to other events if we need it
135 */
136 pipeline.sendUpstream(capture(exceptionEventCapture));
137 expectLastCall().anyTimes();
138 replay(pipeline);
139 featuresReply = (OFFeaturesReply) buildOFMessage(OFType.FEATURES_REPLY);
140 }
141
142 @After
143 public void tearDown() {
144 /* ensure no exception was thrown */
145 if (exceptionEventCapture.hasCaptured()) {
146 Throwable ex = exceptionEventCapture.getValue().getCause();
147 throw new AssertionError("Unexpected exception: " +
148 ex.getClass().getName() + "(" + ex + ")");
149 }
150 assertFalse("Unexpected messages have been captured",
151 writeCapture.hasCaptured());
152 // verify all mocks.
153 verify(channel);
154 verify(messageEvent);
155 verify(controller);
156 verify(ctx);
157 verify(channelStateEvent);
158 verify(pipeline);
159 verify(swImplBase);
160
161 }
162
163 /**
164 * Reset the channel mock and set basic method call expectations.
165 *
166 **/
167 void resetChannel() {
168 reset(channel);
169 expect(channel.getPipeline()).andReturn(pipeline).anyTimes();
170 expect(channel.getRemoteAddress()).andReturn(null).anyTimes();
171 }
172
173 /**
174 * reset, setup, and replay the messageEvent mock for the given
175 * messages.
176 */
177 void setupMessageEvent(List<OFMessage> messages) {
178 reset(messageEvent);
179 expect(messageEvent.getMessage()).andReturn(messages).atLeastOnce();
180 replay(messageEvent);
181 }
182
183 /**
184 * reset, setup, and replay the messageEvent mock for the given
185 * messages, mock controller send message to channel handler.
186 *
187 * This method will reset, start replay on controller, and then verify
188 */
189 void sendMessageToHandlerWithControllerReset(List<OFMessage> messages)
190 throws Exception {
191 verify(controller);
192 reset(controller);
193
194 sendMessageToHandlerNoControllerReset(messages);
195 }
196
197 /**
198 * reset, setup, and replay the messageEvent mock for the given
199 * messages, mock controller send message to channel handler.
200 *
201 * This method will start replay on controller, and then verify
202 */
203 void sendMessageToHandlerNoControllerReset(List<OFMessage> messages)
204 throws Exception {
205 setupMessageEvent(messages);
206
207 expect(controller.addConnectedSwitch(1000, handler))
208 .andReturn(true).anyTimes();
209 replay(controller);
210
211 handler.messageReceived(ctx, messageEvent);
212 verify(controller);
213 }
214
215 /**
216 * Extract the list of OFMessages that was captured by the Channel.write()
217 * capture. Will check that something was actually captured first. We'll
218 * collapse the messages from multiple writes into a single list of
219 * OFMessages.
220 * Resets the channelWriteCapture.
221 */
222 List<OFMessage> getMessagesFromCapture() {
223 List<OFMessage> msgs = new ArrayList<OFMessage>();
224
225 assertTrue("No write on channel was captured",
226 writeCapture.hasCaptured());
227 List<List<OFMessage>> capturedVals = writeCapture.getValues();
228
229 for (List<OFMessage> oneWriteList: capturedVals) {
230 msgs.addAll(oneWriteList);
231 }
232 writeCapture.reset();
233 return msgs;
234 }
235
236
237 /**
238 * Verify that the given exception event capture (as returned by
239 * getAndInitExceptionCapture) has thrown an exception of the given
240 * expectedExceptionClass.
241 * Resets the capture
242 */
243 void verifyExceptionCaptured(
244 Class<? extends Throwable> expectedExceptionClass) {
245 assertTrue("Excpected exception not thrown",
246 exceptionEventCapture.hasCaptured());
247 Throwable caughtEx = exceptionEventCapture.getValue().getCause();
248 assertEquals(expectedExceptionClass, caughtEx.getClass());
249 exceptionEventCapture.reset();
250 }
251
252 /**
253 * Make sure that the transaction ids in the given messages are
254 * not 0 and differ between each other.
255 * While it's not a defect per se if the xids are we want to ensure
256 * we use different ones for each message we send.
257 */
258 void verifyUniqueXids(List<OFMessage> msgs) {
259 if (seenXids == null) {
260 seenXids = new HashSet<Integer>();
261 }
262 for (OFMessage m: msgs) {
263 int xid = (int) m.getXid();
264 assertTrue("Xid in messags is 0", xid != 0);
265 assertFalse("Xid " + xid + " has already been used",
266 seenXids.contains(xid));
267 seenXids.add(xid);
268 }
269 }
270
271
272
273 public void testInitState() throws Exception {
274 OFMessage m = buildOFMessage(OFType.HELLO);
275
276 expect(messageEvent.getMessage()).andReturn(null);
277 replay(channel, messageEvent);
278
279 // We don't expect to receive /any/ messages in init state since
280 // channelConnected moves us to a different state
281 sendMessageToHandlerWithControllerReset(Collections.singletonList(m));
282
283 verifyExceptionCaptured(SwitchStateException.class);
284 assertEquals(OFChannelHandler.ChannelState.INIT,
285 handler.getStateForTesting());
286 }
287
288 /**
289 * move the channel from scratch to WAIT_HELLO state.
290 *
291 */
292 @Test
293 public void moveToWaitHello() throws Exception {
294 resetChannel();
295 channel.write(capture(writeCapture));
296 expectLastCall().andReturn(null).once();
297 replay(channel);
298 // replay unused mocks
299 replay(messageEvent);
300
301 handler.channelConnected(ctx, channelStateEvent);
302
303 List<OFMessage> msgs = getMessagesFromCapture();
304 assertEquals(1, msgs.size());
305 assertEquals(OFType.HELLO, msgs.get(0).getType());
306 assertEquals(OFChannelHandler.ChannelState.WAIT_HELLO,
307 handler.getStateForTesting());
308 //Should verify that the Hello received from the controller
309 //is ALWAYS OF1.3 hello regardless of the switch version
310 assertEquals(OFVersion.OF_13, msgs.get(0).getVersion());
311 verifyUniqueXids(msgs);
312 }
313
314
315 /**
316 * Move the channel from scratch to WAIT_FEATURES_REPLY state.
317 * Builds on moveToWaitHello().
318 * adds testing for WAIT_HELLO state.
319 */
320 @Test
321 public void moveToWaitFeaturesReply() throws Exception {
322 moveToWaitHello();
323 resetChannel();
324 channel.write(capture(writeCapture));
325 expectLastCall().andReturn(null).atLeastOnce();
326 replay(channel);
327
328 OFMessage hello = buildOFMessage(OFType.HELLO);
329 sendMessageToHandlerWithControllerReset(Collections.singletonList(hello));
330
331 List<OFMessage> msgs = getMessagesFromCapture();
332 assertEquals(1, msgs.size());
333 assertEquals(OFType.FEATURES_REQUEST, msgs.get(0).getType());
334 if (ofVersion == OFVersion.OF_10) {
335 assertEquals(OFVersion.OF_10, msgs.get(0).getVersion());
336 }
337 verifyUniqueXids(msgs);
338
339 assertEquals(OFChannelHandler.ChannelState.WAIT_FEATURES_REPLY,
340 handler.getStateForTesting());
341 }
342
343 /**
344 * Move the channel from scratch to WAIT_CONFIG_REPLY state.
345 * Builds on moveToWaitFeaturesReply.
346 * adds testing for WAIT_FEATURES_REPLY state.
347 */
348 @Test
349 public void moveToWaitConfigReply() throws Exception {
350 moveToWaitFeaturesReply();
351
352 resetChannel();
353 channel.write(capture(writeCapture));
354 expectLastCall().andReturn(null).atLeastOnce();
355 replay(channel);
356
357 sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(featuresReply));
358 List<OFMessage> msgs = getMessagesFromCapture();
359 assertEquals(3, msgs.size());
360 assertEquals(OFType.SET_CONFIG, msgs.get(0).getType());
361 OFSetConfig sc = (OFSetConfig) msgs.get(0);
362 assertEquals((short) 0xffff, sc.getMissSendLen());
363 assertEquals(OFType.BARRIER_REQUEST, msgs.get(1).getType());
364 assertEquals(OFType.GET_CONFIG_REQUEST, msgs.get(2).getType());
365 verifyUniqueXids(msgs);
366 assertEquals(OFChannelHandler.ChannelState.WAIT_CONFIG_REPLY,
367 handler.getStateForTesting());
368 }
369
370 /**
371 * Move the channel from scratch to WAIT_DESCRIPTION_STAT_REPLY state.
372 * Builds on moveToWaitConfigReply().
373 * adds testing for WAIT_CONFIG_REPLY state.
374 */
375 @Test
376 public void moveToWaitDescriptionStatReply() throws Exception {
377 moveToWaitConfigReply();
378 resetChannel();
379 channel.write(capture(writeCapture));
380 expectLastCall().andReturn(null).atLeastOnce();
381 replay(channel);
382
383 OFGetConfigReply cr = (OFGetConfigReply) buildOFMessage(OFType.GET_CONFIG_REPLY);
384
385 sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(cr));
386
387 List<OFMessage> msgs = getMessagesFromCapture();
388 assertEquals(1, msgs.size());
389 assertEquals(OFType.STATS_REQUEST, msgs.get(0).getType());
390 OFStatsRequest<?> sr = (OFStatsRequest<?>) msgs.get(0);
391 assertEquals(OFStatsType.DESC, sr.getStatsType());
392 verifyUniqueXids(msgs);
393 assertEquals(OFChannelHandler.ChannelState.WAIT_DESCRIPTION_STAT_REPLY,
394 handler.getStateForTesting());
395 }
396
397
398 private OFStatsReply createDescriptionStatsReply() throws IOException {
399 OFStatsReply sr = (OFStatsReply) buildOFMessage(OFType.STATS_REPLY);
400 return sr;
401 }
402
403 /**
404 * Move the channel from scratch to WAIT_INITIAL_ROLE state.
405 * for a switch that does not have a sub-handshake.
406 * Builds on moveToWaitDescriptionStatReply().
407 * adds testing for WAIT_DESCRIPTION_STAT_REPLY state.
408 *
409 */
410 @Test
411 public void moveToWaitInitialRole()
412 throws Exception {
413 moveToWaitDescriptionStatReply();
414
415 long xid = 2000;
416
417 // build the stats reply
418 OFStatsReply sr = createDescriptionStatsReply();
419
420 resetChannel();
421 replay(channel);
422
423 setupMessageEvent(Collections.<OFMessage>singletonList(sr));
424
425 // mock controller
426 reset(controller);
427 reset(swImplBase);
428
429 expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
430 .andReturn(swImplBase).anyTimes();
431 expect(controller.getDebugCounter())
432 .andReturn(debugCounterService).anyTimes();
433 controller.submitRegistryRequest(1000);
434 expectLastCall().once();
435 replay(controller);
436
437 //TODO: With the description stats message you are sending in the test,
438 //you will end up with an OFSwitchImplBase object
439 //which by default does NOT support the nicira role messages.
440 //If you wish to test the case where Nicira role messages are supported,
441 //then make a comment here that states that this is different
442 //from the default behavior of switchImplbase /or/
443 //send the right desc-stats (for example send what is expected from OVS 1.0)
444
445 if (ofVersion == OFVersion.OF_10) {
446 expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
447 .andReturn(true).once();
448
449 swImplBase.write(capture(writeCapture));
450 expectLastCall().anyTimes();
451 }
452
453 swImplBase.setOFVersion(ofVersion);
454 expectLastCall().once();
455 swImplBase.setConnected(true);
456 expectLastCall().once();
457 swImplBase.setChannel(channel);
458 expectLastCall().once();
459 swImplBase.setDebugCounterService(controller.getDebugCounter());
460 expectLastCall().once();
461 expect(swImplBase.getStringId())
462 .andReturn(null).anyTimes();
463 swImplBase.setRole(Role.EQUAL);
464 expectLastCall().once();
465
466 expect(swImplBase.getNextTransactionId())
467 .andReturn((int) xid).anyTimes();
468 expect(swImplBase.getId())
469 .andReturn(1000L).once();
470
471 swImplBase.setFeaturesReply(featuresReply);
472 expectLastCall().once();
473 swImplBase.setPortDescReply((OFPortDescStatsReply) null);
474 replay(swImplBase);
475
476 // send the description stats reply
477 handler.messageReceived(ctx, messageEvent);
478
479 List<OFMessage> msgs = getMessagesFromCapture();
480 assertEquals(1, msgs.size());
481 assertEquals(OFType.EXPERIMENTER, msgs.get(0).getType());
482 verifyNiciraMessage((OFExperimenter) msgs.get(0));
483
484 verify(controller);
485 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
486 handler.getStateForTesting());
487 }
488
489 /**
490 * Move the channel from scratch to.
491 * WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
492 * Builds on moveToWaitInitialRole().
493 */
494 @Test
495 public void moveToWaitSubHandshake()
496 throws Exception {
497 moveToWaitInitialRole();
498
499 int xid = 2000;
500 resetChannel();
501 replay(channel);
502
503 reset(swImplBase);
504 // Set the role
505 setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
506 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
507 handler.getStateForTesting());
508
509 // build the stats reply
510 OFStatsReply sr = createDescriptionStatsReply();
511 OFMessage rr = getRoleReply(xid, Role.SLAVE);
512 setupMessageEvent(Collections.<OFMessage>singletonList(rr));
513
514 // mock controller
515 reset(controller);
516 reset(swImplBase);
517
518 expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
519 .andReturn(swImplBase).anyTimes();
520 expect(controller.getDebugCounter())
521 .andReturn(debugCounterService).anyTimes();
522
523 replay(controller);
524
525 expect(swImplBase.getStringId())
526 .andReturn(null).anyTimes();
527 swImplBase.setRole(Role.SLAVE);
528 expectLastCall().once();
529 expect(swImplBase.getNextTransactionId())
530 .andReturn(xid).anyTimes();
531 swImplBase.startDriverHandshake();
532 expectLastCall().once();
533
534 //when this flag is false, state machine will move to
535 //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
536 expect(swImplBase.isDriverHandshakeComplete())
537 .andReturn(false).once();
538
539 replay(swImplBase);
540
541 // send the description stats reply
542 handler.messageReceived(ctx, messageEvent);
543
544 assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
545 handler.getStateForTesting());
546 }
547
548 /**
549 * Move the channel from scratch to WAIT_INITIAL_ROLE state,
550 * then move the channel to EQUAL state based on the switch Role.
551 * This test basically test the switch with role support.
552 * Builds on moveToWaitInitialRole().
553 *
554 * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
555 * and PORT_STATUS), state machine will transit to MASTER or
556 * EQUAL state based on the switch role.
557 */
558 @Test
559 public void moveToSlaveWithHandshakeComplete()
560 throws Exception {
561
562 moveToWaitInitialRole();
563
564 int xid = 2000;
565 resetChannel();
566 replay(channel);
567
568 reset(swImplBase);
569 // Set the role
570 setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
571 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
572 handler.getStateForTesting());
573
574 // build the stats reply
575 OFStatsReply sr = createDescriptionStatsReply();
576 OFMessage rr = getRoleReply(xid, Role.SLAVE);
577 setupMessageEvent(Collections.<OFMessage>singletonList(rr));
578
579 // mock controller
580 reset(controller);
581 reset(swImplBase);
582
583 expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
584 .andReturn(swImplBase).anyTimes();
585
586 expect(controller.getDebugCounter())
587 .andReturn(debugCounterService).anyTimes();
588
589 expect(controller.addActivatedEqualSwitch(1000, swImplBase))
590 .andReturn(true).once();
591 replay(controller);
592
593 expect(swImplBase.getStringId())
594 .andReturn(null).anyTimes();
595 //consult the role in sw to determine the next state.
596 //in this testing case, we are testing that channel handler
597 // will move to EQUAL state when switch role is in SLAVE.
598 expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
599 swImplBase.setRole(Role.SLAVE);
600 expectLastCall().once();
601
602 expect(swImplBase.getNextTransactionId())
603 .andReturn(xid).anyTimes();
604 expect(swImplBase.getId())
605 .andReturn(1000L).once();
606 swImplBase.startDriverHandshake();
607 expectLastCall().once();
608
609 //when this flag is true, don't need to move interim state
610 //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE. channel handler will
611 //move to corresponding state after consulting the role in sw
612 //This is essentially the same test as the one above,
613 //except for this line
614 expect(swImplBase.isDriverHandshakeComplete())
615 .andReturn(true).once();
616
617 replay(swImplBase);
618
619 // send the description stats reply
620 handler.messageReceived(ctx, messageEvent);
621
622 assertEquals(OFChannelHandler.ChannelState.EQUAL,
623 handler.getStateForTesting());
624 }
625
626 /**
627 * Move the channel from scratch to WAIT_INITIAL_ROLE state,
628 * then to MASTERL state based on the switch Role.
629 * This test basically test the switch with role support.
630 * Builds on moveToWaitInitialRole().
631 *
632 * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
633 * and PORT_STATUS), state machine will transit to MASTER or
634 * EQUAL state based on the switch role.
635 */
636 @Test
637 public void moveToMasterWithHandshakeComplete()
638 throws Exception {
639
640 moveToWaitInitialRole();
641
642 int xid = 2000;
643 resetChannel();
644 replay(channel);
645
646 reset(swImplBase);
647 // Set the role
648 setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
649 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
650 handler.getStateForTesting());
651
652 // build the stats reply
653 OFStatsReply sr = createDescriptionStatsReply();
654 OFMessage rr = getRoleReply(xid, Role.MASTER);
655 setupMessageEvent(Collections.<OFMessage>singletonList(rr));
656
657 // mock controller
658 reset(controller);
659 reset(swImplBase);
660
661 expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
662 .andReturn(swImplBase).anyTimes();
663
664 expect(controller.getDebugCounter())
665 .andReturn(debugCounterService).anyTimes();
666
667 expect(controller.addActivatedMasterSwitch(1000, swImplBase))
668 .andReturn(true).once();
669 replay(controller);
670
671 expect(swImplBase.getStringId())
672 .andReturn(null).anyTimes();
673 expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
674 swImplBase.setRole(Role.MASTER);
675 expectLastCall().once();
676
677 expect(swImplBase.getNextTransactionId())
678 .andReturn(xid).anyTimes();
679 expect(swImplBase.getId())
680 .andReturn(1000L).once();
681 swImplBase.startDriverHandshake();
682 expectLastCall().once();
683 expect(swImplBase.isDriverHandshakeComplete())
684 .andReturn(true).once();
685
686 replay(swImplBase);
687
688
689 // send the description stats reply
690 handler.messageReceived(ctx, messageEvent);
691
692 assertEquals(OFChannelHandler.ChannelState.MASTER,
693 handler.getStateForTesting());
694 }
695
696 /**
697 * Move the channel from scratch to
698 * WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
699 * Builds on moveToWaitSubHandshake().
700 */
701 @Test
702 public void moveToEqualViaWaitSubHandshake()
703 throws Exception {
704 moveToWaitSubHandshake();
705
706 long xid = 2000;
707 resetChannel();
708 replay(channel);
709
710 // build the stats reply
711 OFStatsReply sr = createDescriptionStatsReply();
712
713 setupMessageEvent(Collections.<OFMessage>singletonList(sr));
714
715 // mock controller
716 reset(controller);
717 reset(swImplBase);
718
719 expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
720 .andReturn(swImplBase).anyTimes();
721 expect(controller.getDebugCounter())
722 .andReturn(debugCounterService).anyTimes();
723
724 expect(controller.addActivatedEqualSwitch(1000, swImplBase))
725 .andReturn(true).once();
726 replay(controller);
727
728 expect(swImplBase.getStringId())
729 .andReturn(null).anyTimes();
730 expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
731 expect(swImplBase.getNextTransactionId())
732 .andReturn((int) xid).anyTimes();
733 expect(swImplBase.getId())
734 .andReturn(1000L).once();
735
736 swImplBase.processDriverHandshakeMessage(sr);
737 expectLastCall().once();
738 expect(swImplBase.isDriverHandshakeComplete())
739 .andReturn(true).once();
740
741 replay(swImplBase);
742
743 // send the description stats reply
744 handler.messageReceived(ctx, messageEvent);
745
746 assertEquals(OFChannelHandler.ChannelState.EQUAL,
747 handler.getStateForTesting());
748 }
749
750 /**
751 * Move the channel from scratch to
752 * WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
753 * Builds on moveToWaitSubHandshake().
754 */
755 @Test
756 public void moveToMasterViaWaitSubHandshake()
757 throws Exception {
758 moveToWaitSubHandshake();
759
760 long xid = 2000;
761 resetChannel();
762 replay(channel);
763
764 // In this state, any messages except echo request, port status and
765 // error go to the switch sub driver handshake. Once the switch reports
766 // that its sub driver handshake is complete (#isDriverHandshakeComplete
767 // return true) then the channel handle consults the switch role and
768 // moves the state machine to the appropriate state (MASTER or EQUALS).
769 // In this test we expect the state machine to end up in MASTER state.
770 OFStatsReply sr = createDescriptionStatsReply();
771
772 setupMessageEvent(Collections.<OFMessage>singletonList(sr));
773
774 // mock controller
775 reset(controller);
776 reset(swImplBase);
777
778 expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
779 .andReturn(swImplBase).anyTimes();
780
781 expect(controller.getDebugCounter())
782 .andReturn(debugCounterService).anyTimes();
783 expect(controller.addActivatedMasterSwitch(1000, swImplBase))
784 .andReturn(true).once();
785 replay(controller);
786
787 expect(swImplBase.getStringId())
788 .andReturn(null).anyTimes();
789 expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
790 expect(swImplBase.getNextTransactionId())
791 .andReturn((int) xid).anyTimes();
792 expect(swImplBase.getId())
793 .andReturn(1000L).once();
794
795 swImplBase.processDriverHandshakeMessage(sr);
796 expectLastCall().once();
797 expect(swImplBase.isDriverHandshakeComplete())
798 .andReturn(true).once();
799
800 replay(swImplBase);
801
802 // send the description stats reply
803 handler.messageReceived(ctx, messageEvent);
804 verify(controller);
805 assertEquals(OFChannelHandler.ChannelState.MASTER,
806 handler.getStateForTesting());
807 }
808
809 /**
810 * Test the behavior in WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
811 * ECHO_REQUEST message received case.
812 */
813 @Test
814 public void testWaitSwitchDriverSubhandshake() throws Exception {
815 moveToWaitSubHandshake();
816
817 long xid = 2000;
818 resetChannel();
819 channel.write(capture(writeCapture));
820 expectLastCall().andReturn(null).atLeastOnce();
821 replay(channel);
822
823 OFMessage er = buildOFMessage(OFType.ECHO_REQUEST);
824
825 setupMessageEvent(Collections.<OFMessage>singletonList(er));
826
827 // mock controller
828 reset(controller);
829 reset(swImplBase);
830
831 expect(controller.getOFMessageFactory10()).andReturn(factory10);
832 expect(controller.getDebugCounter())
833 .andReturn(debugCounterService).anyTimes();
834
835 replay(controller);
836
837 expect(swImplBase.getStringId())
838 .andReturn(null).anyTimes();
839 expect(swImplBase.getNextTransactionId())
840 .andReturn((int) xid).anyTimes();
841
842 replay(swImplBase);
843
844 handler.messageReceived(ctx, messageEvent);
845
846 List<OFMessage> msgs = getMessagesFromCapture();
847 assertEquals(1, msgs.size());
848 assertEquals(OFType.ECHO_REPLY, msgs.get(0).getType());
849 verifyUniqueXids(msgs);
850 assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
851 handler.getStateForTesting());
852 }
853
854 /**
855 * Helper.
856 * Verify that the given OFMessage is a correct Nicira RoleRequest message.
857 */
858 private void verifyNiciraMessage(OFExperimenter ofMessage) {
859
860 int vendor = (int) ofMessage.getExperimenter();
861 assertEquals(vendor, 0x2320); // magic number representing nicira
862 }
863
864 /**
865 * Setup the mock switch and write capture for a role request, set the
866 * role and verify mocks.
867 * @param supportsNxRole whether the switch supports role request messages
868 * to setup the attribute. This must be null (don't yet know if roles
869 * supported: send to check) or true.
870 * @param xid The xid to use in the role request
871 * @param role The role to send
872 * @throws IOException
873 */
874 private void setupSwitchSendRoleRequestAndVerify(Boolean supportsNxRole,
875 int xid,
876 Role role) throws IOException {
877
878 RoleRecvStatus expectation = RoleRecvStatus.MATCHED_SET_ROLE;
879
880 expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
881 .andReturn(supportsNxRole).atLeastOnce();
882
883 if (supportsNxRole != null && supportsNxRole) {
884 expect(swImplBase.getNextTransactionId()).andReturn(xid).once();
885 swImplBase.write(capture(writeCapture));
886 expectLastCall().anyTimes();
887 }
888 replay(swImplBase);
889
890 handler.sendRoleRequest(role, expectation);
891
892 if (supportsNxRole != null && supportsNxRole) {
893 List<OFMessage> msgs = getMessagesFromCapture();
894 assertEquals(1, msgs.size());
895 verifyNiciraMessage((OFExperimenter) msgs.get(0));
896 }
897 }
898
899 /**
900 * Setup the mock switch for a role change request where the switch
901 * does not support roles.
902 *
903 * Needs to verify and reset the controller since we need to set
904 * an expectation
905 */
906 private void setupSwitchRoleChangeUnsupported(int xid,
907 Role role) {
908 boolean supportsNxRole = false;
909 RoleRecvStatus expectation = RoleRecvStatus.NO_REPLY;
910 reset(swImplBase);
911 expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
912 .andReturn(supportsNxRole).atLeastOnce();
913 // TODO: hmmm. While it's not incorrect that we set the attribute
914 // again it looks odd. Maybe change
915 swImplBase.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole);
916 expectLastCall().anyTimes();
917
918 replay(swImplBase);
919
920 handler.sendRoleRequest(role, expectation);
921
922 verify(swImplBase);
923 }
924
925 /*
926 * Return a Nicira RoleReply message for the given role.
927 */
928 private OFMessage getRoleReply(long xid, Role role) {
929
930 OFNiciraControllerRole nr = null;
931
932 switch(role) {
933 case MASTER:
934 nr = OFNiciraControllerRole.ROLE_MASTER;
935 break;
936 case EQUAL:
937 nr = OFNiciraControllerRole.ROLE_SLAVE;
938 break;
939 case SLAVE:
940 nr = OFNiciraControllerRole.ROLE_SLAVE;
941 break;
942 default: //handled below
943 }
944 OFMessage m = factory10.buildNiciraControllerRoleReply()
945 .setRole(nr)
946 .setXid(xid)
947 .build();
948 return m;
949 }
950
951 /**
952 * Move the channel from scratch to MASTER state.
953 * Builds on moveToWaitInitialRole().
954 * adds testing for WAIT_INITAL_ROLE state.
955 *
956 * This method tests the case that the switch does NOT support roles.
957 * In ONOS if the switch-driver says that nicira-role messages are not
958 * supported, then ONOS does NOT send role-request messages
959 * (see handleUnsentRoleMessage())
960 */
961 @Test
962 public void testInitialMoveToMasterNoRole() throws Exception {
963 int xid = 43;
964 // first, move us to WAIT_INITIAL_ROLE_STATE
965
966 moveToWaitInitialRole();
967 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
968 handler.getStateForTesting());
969
970 OFStatsReply sr = createDescriptionStatsReply();
971
972 reset(controller);
973 reset(swImplBase);
974
975 expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
976 .andReturn(swImplBase).anyTimes();
977
978 expect(controller.getDebugCounter())
979 .andReturn(debugCounterService).anyTimes();
980
981 expect(controller.addActivatedMasterSwitch(1000, swImplBase))
982 .andReturn(true).once();
983 replay(controller);
984
985 reset(swImplBase);
986 swImplBase.setRole(Role.MASTER);
987 expectLastCall().once();
988 swImplBase.startDriverHandshake();
989 expectLastCall().once();
990 expect(swImplBase.isDriverHandshakeComplete())
991 .andReturn(true).once();
992 expect(swImplBase.getStringId())
993 .andReturn(null).anyTimes();
994 expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
995
996 expect(swImplBase.getId())
997 .andReturn(1000L).once();
998 // Set the role
999 setupSwitchSendRoleRequestAndVerify(false, xid, Role.MASTER);
1000
1001 assertEquals(OFChannelHandler.ChannelState.MASTER,
1002 handler.getStateForTesting());
1003 }
1004
1005 /**
1006 * Move the channel from scratch to WAIT_INITIAL_ROLE state.
1007 * Builds on moveToWaitInitialRole().
1008 * adds testing for WAIT_INITAL_ROLE state
1009 *
1010 * We let the initial role request time out. Role support should be
1011 * disabled but the switch should be activated.
1012 */
1013 /* TBD
1014 @Test
1015 public void testInitialMoveToMasterTimeout() throws Exception {
1016 int timeout = 50;
1017 handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
1018 int xid = 4343;
1019
1020 // first, move us to WAIT_INITIAL_ROLE_STATE
1021
1022 moveToWaitInitialRole();
1023 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
1024 handler.getStateForTesting());
1025
1026 // prepare mocks and inject the role reply message
1027 reset(swImplBase);
1028 // Set the role
1029 swImplBase.setRole(Role.MASTER);
1030 expectLastCall().once();
1031 swImplBase.startDriverHandshake();
1032 expectLastCall().once();
1033 expect(swImplBase.isDriverHandshakeComplete())
1034 .andReturn(false).once();
1035 if (ofVersion == OFVersion.OF_10) {
1036 expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
1037 .andReturn(true).once();
1038
1039 swImplBase.write(capture(writeCapture),
1040 EasyMock.<FloodlightContext>anyObject());
1041 expectLastCall().anyTimes();
1042 }
1043 expect(swImplBase.getNextTransactionId()).andReturn(xid).once();
1044
1045 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
1046 handler.getStateForTesting());
1047
1048 // Set the role
1049 setupSwitchSendRoleRequestAndVerify(null, xid, Role.MASTER);
1050 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
1051 handler.getStateForTesting());
1052
1053 OFMessage m = buildOFMessage(OFType.ECHO_REPLY);
1054
1055 setupMessageEvent(Collections.<OFMessage>singletonList(m));
1056
1057 Thread.sleep(timeout+5);
1058
1059 verify(controller);
1060 reset(controller);
1061
1062 expect(controller.addActivatedMasterSwitch(1000, swImplBase))
1063 .andReturn(true).once();
1064 controller.flushAll();
1065 expectLastCall().once();
1066
1067 replay(controller);
1068
1069 handler.messageReceived(ctx, messageEvent);
1070
1071 assertEquals(OFChannelHandler.ChannelState.MASTER,
1072 handler.getStateForTesting());
1073
1074 }
1075
1076 */
1077 /**
1078 * Move the channel from scratch to SLAVE state.
1079 * Builds on doMoveToWaitInitialRole().
1080 * adds testing for WAIT_INITAL_ROLE state
1081 *
1082 * This method tests the case that the switch does NOT support roles.
1083 * The channel handler still needs to send the initial request to find
1084 * out that whether the switch supports roles.
1085 *
1086 */
1087 @Test
1088 public void testInitialMoveToSlaveNoRole() throws Exception {
1089 int xid = 44;
1090 // first, move us to WAIT_INITIAL_ROLE_STATE
1091 moveToWaitInitialRole();
1092 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
1093 handler.getStateForTesting());
1094
1095 reset(swImplBase);
1096 // Set the role
1097 setupSwitchSendRoleRequestAndVerify(false, xid, Role.SLAVE);
1098 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
1099 handler.getStateForTesting());
1100
1101 }
1102
1103 /**
1104 * Move the channel from scratch to SLAVE state.
1105 * Builds on doMoveToWaitInitialRole().
1106 * adds testing for WAIT_INITAL_ROLE state
1107 *
1108 * We let the initial role request time out. The switch should be
1109 * disconnected
1110 */
1111 /* TBD
1112 @Test
1113 public void testInitialMoveToSlaveTimeout() throws Exception {
1114 int timeout = 50;
1115 handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
1116 int xid = 4444;
1117
1118 // first, move us to WAIT_INITIAL_ROLE_STATE
1119 moveToWaitInitialRole();
1120 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
1121 handler.getStateForTesting());
1122
1123 // Set the role
1124 setupSwitchSendRoleRequestAndVerify(null, xid, Role.SLAVE);
1125 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
1126 handler.getStateForTesting());
1127
1128 // prepare mocks and inject the role reply message
1129 reset(sw);
1130 sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
1131 expectLastCall().once();
1132 sw.setRole(Role.SLAVE);
1133 expectLastCall().once();
1134 sw.disconnectSwitch(); // Make sure we disconnect
1135 expectLastCall().once();
1136 replay(sw);
1137
1138 OFMessage m = buildOFMessage(OFType.ECHO_REPLY);
1139
1140 Thread.sleep(timeout+5);
1141
1142 sendMessageToHandlerWithControllerReset(Collections.singletonList(m));
1143 }
1144
1145 */
1146 /**
1147 * Move channel from scratch to WAIT_INITIAL_STATE, then MASTER,
1148 * then SLAVE for cases where the switch does not support roles.
1149 * I.e., the final SLAVE transition should disconnect the switch.
1150 */
1151 @Test
1152 public void testNoRoleInitialToMasterToSlave() throws Exception {
1153 int xid = 46;
1154 reset(swImplBase);
1155 replay(swImplBase);
1156
1157 reset(controller);
1158 replay(controller);
1159
1160 // First, lets move the state to MASTER without role support
1161 testInitialMoveToMasterNoRole();
1162 assertEquals(OFChannelHandler.ChannelState.MASTER,
1163 handler.getStateForTesting());
1164
1165 // try to set master role again. should be a no-op
1166 setupSwitchRoleChangeUnsupported(xid, Role.MASTER);
1167
1168 assertEquals(OFChannelHandler.ChannelState.MASTER,
1169 handler.getStateForTesting());
1170
1171 setupSwitchRoleChangeUnsupported(xid, Role.SLAVE);
1172 //switch does not support role message. there is no role set
1173 assertEquals(OFChannelHandler.ChannelState.MASTER,
1174 handler.getStateForTesting());
1175
1176 }
1177
1178 /**
1179 * Move the channel to MASTER state.
1180 * Expects that the channel is in MASTER or SLAVE state.
1181 *
1182 */
1183 public void changeRoleToMasterWithRequest() throws Exception {
1184 int xid = 4242;
1185
1186 assertTrue("This method can only be called when handler is in " +
1187 "MASTER or SLAVE role", handler.isHandshakeComplete());
1188
1189 reset(swImplBase);
1190 reset(controller);
1191 // Set the role
1192 setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
1193
1194 // prepare mocks and inject the role reply message
1195
1196 reset(controller);
1197 expect(controller.addActivatedMasterSwitch(1000, swImplBase))
1198 .andReturn(true).once();
1199 OFMessage reply = getRoleReply(xid, Role.MASTER);
1200
1201 // sendMessageToHandler will verify and rest controller mock
1202
1203 OFStatsReply sr = createDescriptionStatsReply();
1204 setupMessageEvent(Collections.<OFMessage>singletonList(reply));
1205
1206 // mock controller
1207 reset(controller);
1208 reset(swImplBase);
1209
1210 expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
1211 .andReturn(swImplBase).anyTimes();
1212
1213 expect(controller.getDebugCounter())
1214 .andReturn(debugCounterService).anyTimes();
1215 controller.transitionToMasterSwitch(1000);
1216 expectLastCall().once();
1217
1218 replay(controller);
1219
1220 expect(swImplBase.getStringId())
1221 .andReturn(null).anyTimes();
1222 expect(swImplBase.getRole()).andReturn(Role.EQUAL).atLeastOnce();
1223 expect(swImplBase.getNextTransactionId())
1224 .andReturn(xid).anyTimes();
1225 expect(swImplBase.getId())
1226 .andReturn(1000L).once();
1227
1228 swImplBase.setRole(Role.MASTER);
1229 expectLastCall().once();
1230 replay(swImplBase);
1231
1232 // send the description stats reply
1233 handler.messageReceived(ctx, messageEvent);
1234
1235 assertEquals(OFChannelHandler.ChannelState.MASTER,
1236 handler.getStateForTesting());
1237 }
1238
1239 /**
1240 * Move the channel to SLAVE state.
1241 * Expects that the channel is in MASTER or SLAVE state.
1242 *
1243 */
1244 public void changeRoleToSlaveWithRequest() throws Exception {
1245 int xid = 2323;
1246
1247 assertTrue("This method can only be called when handler is in " +
1248 "MASTER or SLAVE role", handler.isHandshakeComplete());
1249
1250 // Set the role
1251 reset(controller);
1252 reset(swImplBase);
1253
1254 swImplBase.write(capture(writeCapture));
1255 expectLastCall().anyTimes();
1256
1257 expect(swImplBase.getNextTransactionId())
1258 .andReturn(xid).anyTimes();
1259
1260
1261 if (ofVersion == OFVersion.OF_10) {
1262 expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
1263 .andReturn(true).once();
1264
1265 swImplBase.write(capture(writeCapture));
1266 expectLastCall().anyTimes();
1267 }
1268 replay(swImplBase);
1269
1270 handler.sendRoleRequest(Role.SLAVE, RoleRecvStatus.MATCHED_SET_ROLE);
1271
1272 List<OFMessage> msgs = getMessagesFromCapture();
1273 assertEquals(1, msgs.size());
1274 verifyNiciraMessage((OFExperimenter) msgs.get(0));
1275
1276
1277 OFMessage reply = getRoleReply(xid, Role.SLAVE);
1278 OFStatsReply sr = createDescriptionStatsReply();
1279 setupMessageEvent(Collections.<OFMessage>singletonList(reply));
1280
1281 // mock controller
1282 reset(controller);
1283 reset(swImplBase);
1284
1285 controller.transitionToEqualSwitch(1000);
1286 expectLastCall().once();
1287 expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
1288 .andReturn(swImplBase).anyTimes();
1289
1290 expect(controller.getDebugCounter())
1291 .andReturn(debugCounterService).anyTimes();
1292
1293 replay(controller);
1294
1295 expect(swImplBase.getStringId())
1296 .andReturn(null).anyTimes();
1297 expect(swImplBase.getRole()).andReturn(Role.MASTER).atLeastOnce();
1298 expect(swImplBase.getNextTransactionId())
1299 .andReturn(xid).anyTimes();
1300
1301 // prepare mocks and inject the role reply message
1302 swImplBase.setRole(Role.SLAVE);
1303 expectLastCall().once();
1304 expect(swImplBase.getId())
1305 .andReturn(1000L).once();
1306 replay(swImplBase);
1307
1308 handler.messageReceived(ctx, messageEvent);
1309
1310 assertEquals(OFChannelHandler.ChannelState.EQUAL,
1311 handler.getStateForTesting());
1312 }
1313
1314 @Test
1315 public void testMultiRoleChange1() throws Exception {
1316 moveToMasterWithHandshakeComplete();
1317 changeRoleToMasterWithRequest();
1318 changeRoleToSlaveWithRequest();
1319 changeRoleToSlaveWithRequest();
1320 changeRoleToMasterWithRequest();
1321 changeRoleToSlaveWithRequest();
1322 }
1323
1324 @Test
1325 public void testMultiRoleChange2() throws Exception {
1326 moveToSlaveWithHandshakeComplete();
1327 changeRoleToMasterWithRequest();
1328 changeRoleToSlaveWithRequest();
1329 changeRoleToSlaveWithRequest();
1330 changeRoleToMasterWithRequest();
1331 changeRoleToSlaveWithRequest();
1332 }
1333
1334 /**
1335 * Start from scratch and reply with an unexpected error to the role
1336 * change request.
1337 * Builds on doMoveToWaitInitialRole()
1338 * adds testing for WAIT_INITAL_ROLE state
1339 */
1340 /* TBD
1341 @Test
1342 public void testInitialRoleChangeOtherError() throws Exception {
1343 int xid = 4343;
1344 // first, move us to WAIT_INITIAL_ROLE_STATE
1345 moveToWaitInitialRole();
1346 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
1347 handler.getStateForTesting());
1348
1349 reset(swImplBase);
1350 // Set the role
1351 setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
1352 assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
1353 handler.getStateForTesting());
1354
1355
1356 // FIXME: shouldn't use ordinal(), but OFError is broken
1357
1358 OFMessage err = factory.errorMsgs().buildBadActionErrorMsg()
1359 .setCode(OFBadActionCode.BAD_LEN)
1360 .setXid(2000)
1361 .build();
1362 verify(swImplBase);
1363 reset(swImplBase);
1364 replay(swImplBase);
1365 sendMessageToHandlerWithControllerReset(Collections.singletonList(err));
1366
1367 verifyExceptionCaptured(SwitchStateException.class);
1368 }
1369 */
1370 /**
1371 * Test dispatch of messages while in MASTER role.
1372 */
1373 @Test
1374 public void testMessageDispatchMaster() throws Exception {
1375
1376 moveToMasterWithHandshakeComplete();
1377
1378 // Send packet in. expect dispatch
1379 OFPacketIn pi = (OFPacketIn)
1380 buildOFMessage(OFType.PACKET_IN);
1381 setupMessageEvent(Collections.<OFMessage>singletonList(pi));
1382
1383 reset(swImplBase);
1384 swImplBase.handleMessage(pi);
1385 expectLastCall().once();
1386 replay(swImplBase);
1387 // send the description stats reply
1388 handler.messageReceived(ctx, messageEvent);
1389
1390 assertEquals(OFChannelHandler.ChannelState.MASTER,
1391 handler.getStateForTesting());
1392
1393 verify(controller);
1394 // TODO: many more to go
1395 }
1396
1397 /**
1398 * Test port status message handling while MASTER.
1399 *
1400 */
1401 /* Patrick: TBD
1402 @Test
1403 public void testPortStatusMessageMaster() throws Exception {
1404 long dpid = featuresReply.getDatapathId().getLong();
1405 testInitialMoveToMasterWithRole();
1406 List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
1407 // A dummy port.
1408 OFPortDesc p = factory.buildPortDesc()
1409 .setName("Eth1")
1410 .setPortNo(OFPort.ofInt(1))
1411 .build();
1412 ports.add(p);
1413
1414 p.setName("Port1");
1415 p.setPortNumber((short)1);
1416
1417 OFPortStatus ps = (OFPortStatus)buildOFMessage(OFType.PORT_STATUS);
1418 ps.setDesc(p);
1419
1420 // The events we expect sw.handlePortStatus to return
1421 // We'll just use the same list for all valid OFPortReasons and add
1422 // arbitrary events for arbitrary ports that are not necessarily
1423 // related to the port status message. Our goal
1424 // here is not to return the correct set of events but the make sure
1425 // that a) sw.handlePortStatus is called
1426 // b) the list of events sw.handlePortStatus returns is sent
1427 // as IOFSwitchListener notifications.
1428 OrderedCollection<PortChangeEvent> events =
1429 new LinkedHashSetWrapper<PortChangeEvent>();
1430 ImmutablePort p1 = ImmutablePort.create("eth1", (short)1);
1431 ImmutablePort p2 = ImmutablePort.create("eth2", (short)2);
1432 ImmutablePort p3 = ImmutablePort.create("eth3", (short)3);
1433 ImmutablePort p4 = ImmutablePort.create("eth4", (short)4);
1434 ImmutablePort p5 = ImmutablePort.create("eth5", (short)5);
1435 events.add(new PortChangeEvent(p1, PortChangeType.ADD));
1436 events.add(new PortChangeEvent(p2, PortChangeType.DELETE));
1437 events.add(new PortChangeEvent(p3, PortChangeType.UP));
1438 events.add(new PortChangeEvent(p4, PortChangeType.DOWN));
1439 events.add(new PortChangeEvent(p5, PortChangeType.OTHER_UPDATE));
1440
1441
1442 for (OFPortReason reason: OFPortReason.values()) {
1443 ps.setReason(reason.getReasonCode());
1444
1445 reset(sw);
1446 expect(sw.getId()).andReturn(dpid).anyTimes();
1447
1448 expect(sw.processOFPortStatus(ps)).andReturn(events).once();
1449 replay(sw);
1450
1451 reset(controller);
1452 controller.notifyPortChanged(sw, p1, PortChangeType.ADD);
1453 controller.notifyPortChanged(sw, p2, PortChangeType.DELETE);
1454 controller.notifyPortChanged(sw, p3, PortChangeType.UP);
1455 controller.notifyPortChanged(sw, p4, PortChangeType.DOWN);
1456 controller.notifyPortChanged(sw, p5, PortChangeType.OTHER_UPDATE);
1457 sendMessageToHandlerNoControllerReset(
1458 Collections.<OFMessage>singletonList(ps));
1459 verify(sw);
1460 verify(controller);
1461 }
1462 }
1463
1464 */
1465 /**
1466 * Build an OF message.
1467 * @throws IOException
1468 */
1469 private OFMessage buildOFMessage(OFType t) throws IOException {
1470 OFMessage m = null;
1471 switch (t) {
1472
1473 case HELLO:
1474 // The OF protocol requires us to start things off by sending the highest
1475 // version of the protocol supported.
1476
1477 // bitmap represents OF1.0 (ofp_version=0x01) and OF1.3 (ofp_version=0x04)
1478 // see Sec. 7.5.1 of the OF1.3.4 spec
1479 if (ofVersion == OFVersion.OF_13) {
1480 U32 bitmap = U32.ofRaw(0x00000012);
1481 OFHelloElem hem = factory13.buildHelloElemVersionbitmap()
1482 .setBitmaps(Collections.singletonList(bitmap))
1483 .build();
1484 m = factory13.buildHello()
1485 .setXid(2000)
1486 .setElements(Collections.singletonList(hem))
1487 .build();
1488 } else {
1489 m = factory10.buildHello()
1490 .setXid(2000)
1491 .build();
1492 }
1493 break;
1494 case FEATURES_REQUEST:
1495 m = factory.buildFeaturesRequest()
1496 .setXid(2000)
1497 .build();
1498 break;
1499 case FEATURES_REPLY:
1500
1501 m = factory.buildFeaturesReply()
1502 .setDatapathId(DatapathId.of(1000L))
1503 .setXid(2000)
1504 .build();
1505 break;
1506 case SET_CONFIG:
1507 m = factory.buildSetConfig()
1508 .setMissSendLen((short) 0xffff)
1509 .setXid(2000)
1510 .build();
1511 break;
1512 case BARRIER_REQUEST:
1513 m = factory.buildBarrierRequest()
1514 .setXid(2000)
1515 .build();
1516 break;
1517 case GET_CONFIG_REQUEST:
1518 m = factory.buildGetConfigRequest()
1519 .setXid(2000)
1520 .build();
1521 break;
1522 case GET_CONFIG_REPLY:
1523 m = factory.buildGetConfigReply()
1524 .setMissSendLen((short) 0xffff)
1525 .setXid(2000)
1526 .build();
1527 break;
1528 case STATS_REQUEST:
1529 break;
1530 case STATS_REPLY:
1531 m = factory.buildDescStatsReply()
1532 .setDpDesc("Datapath Description")
1533 .setHwDesc("Hardware Secription")
1534 .setMfrDesc("Manufacturer Desctiption")
1535 .setSerialNum("Serial Number")
1536 .setSwDesc("Software Desription")
1537 .build();
1538 break;
1539 case ECHO_REQUEST:
1540 m = factory.buildEchoRequest()
1541 .setXid(2000)
1542 .build();
1543 break;
1544 case FLOW_REMOVED:
1545 break;
1546
1547 case PACKET_IN:
1548 m = factory.buildPacketIn()
1549 .setReason(OFPacketInReason.NO_MATCH)
1550 .setTotalLen(1500)
1551 .setXid(2000)
1552 .build();
1553 break;
1554 case PORT_STATUS:
1555 m = factory.buildPortStatus()
1556 .setXid(2000)
1557 .build();
1558 break;
1559
1560 default:
1561 m = factory.buildFeaturesRequest()
1562 .setXid(2000)
1563 .build();
1564 break;
1565 }
1566
1567 return (m);
1568 }
1569}