alshabib
Committed by Ali "The Bomb" Al-Shabibi

added unit tests

Change-Id: Ic743a05b907456e1414a9bc587696de631d3f382

commented the controller test class

Change-Id: Id9afb0e60afb3839f65a41b04e7129db1010ca19

added OFChannelHandler tests

Change-Id: I45169988f0e4242a6e1c0baf34b1104f53873bb7
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
44 44
45 <module name="Checker"> 45 <module name="Checker">
46 <module name="SuppressionFilter"> 46 <module name="SuppressionFilter">
47 - <property name="file" value="${samedir}/suppressions.xml"/> 47 + <property name="file" value="${config_loc}/suppressions.xml"/>
48 </module> 48 </module>
49 <!-- 49 <!--
50 If you set the basedir property below, then all reported file 50 If you set the basedir property below, then all reported file
......
...@@ -174,7 +174,6 @@ ...@@ -174,7 +174,6 @@
174 https://issues.jboss.org/browse/JASSIST-228 --> 174 https://issues.jboss.org/browse/JASSIST-228 -->
175 <argLine>-XX:MaxPermSize=256m -XX:-UseSplitVerifier</argLine> 175 <argLine>-XX:MaxPermSize=256m -XX:-UseSplitVerifier</argLine>
176 <redirectTestOutputToFile>false</redirectTestOutputToFile> 176 <redirectTestOutputToFile>false</redirectTestOutputToFile>
177 - <excludedGroups>net.onrc.onos.core.util.IntegrationTest</excludedGroups>
178 </configuration> 177 </configuration>
179 </plugin> 178 </plugin>
180 <!-- TODO exec:java no longer used remove at some point? --> 179 <!-- TODO exec:java no longer used remove at some point? -->
......
...@@ -69,8 +69,6 @@ public interface IOFSwitch { ...@@ -69,8 +69,6 @@ public interface IOFSwitch {
69 69
70 /** 70 /**
71 * Writes to the OFMessage to the output stream. 71 * Writes to the OFMessage to the output stream.
72 - * The message will be handed to the floodlightProvider for possible filtering
73 - * and processing by message listeners
74 * 72 *
75 * @param m 73 * @param m
76 * @param bc 74 * @param bc
...@@ -80,8 +78,6 @@ public interface IOFSwitch { ...@@ -80,8 +78,6 @@ public interface IOFSwitch {
80 78
81 /** 79 /**
82 * Writes the list of messages to the output stream. 80 * Writes the list of messages to the output stream.
83 - * The message will be handed to the floodlightProvider for possible filtering
84 - * and processing by message listeners.
85 * 81 *
86 * @param msglist 82 * @param msglist
87 * @param bc 83 * @param bc
...@@ -333,8 +329,7 @@ public interface IOFSwitch { ...@@ -333,8 +329,7 @@ public interface IOFSwitch {
333 329
334 /** 330 /**
335 * Add or modify a switch port. This is called by the core controller 331 * Add or modify a switch port. This is called by the core controller
336 - * code in response to a OFPortStatus message. It should not typically be 332 + * code in response to a OFPortStatus message.
337 - * called by other floodlight applications.
338 * 333 *
339 * OFPPR_MODIFY and OFPPR_ADD will be treated as equivalent. The OpenFlow 334 * OFPPR_MODIFY and OFPPR_ADD will be treated as equivalent. The OpenFlow
340 * spec is not clear on whether portNames are portNumbers are considered 335 * spec is not clear on whether portNames are portNumbers are considered
...@@ -402,29 +397,6 @@ public interface IOFSwitch { ...@@ -402,29 +397,6 @@ public interface IOFSwitch {
402 public OrderedCollection<PortChangeEvent> 397 public OrderedCollection<PortChangeEvent>
403 setPorts(Collection<OFPortDesc> ports); 398 setPorts(Collection<OFPortDesc> ports);
404 399
405 -// XXX S The odd use of providing an API call to 'set ports' (above) would
406 -// logically suggest that there should be a way to delete or unset the ports.
407 -// Right now we forbid this. We should probably not use setPorts too.
408 -//
409 -// /**
410 -// * Delete a port for the switch. This is called by the core controller
411 -// * code in response to a OFPortStatus message. It should not typically be
412 -// * called by other floodlight applications.
413 -// *
414 -// * @param portNumber
415 -// */
416 -// public void deletePort(short portNumber);
417 -//
418 -// /**
419 -// * Delete a port for the switch. This is called by the core controller
420 -// * code in response to a OFPortStatus message. It should not typically be
421 -// * called by other floodlight applications.
422 -// *
423 -// * @param portName
424 -// */
425 -// public void deletePort(String portName);
426 -
427 -
428 //******************************************* 400 //*******************************************
429 // IOFSwitch object attributes 401 // IOFSwitch object attributes
430 //************************ 402 //************************
......
...@@ -127,7 +127,7 @@ public interface IDebugCounterService { ...@@ -127,7 +127,7 @@ public interface IDebugCounterService {
127 /** 127 /**
128 * Flush all thread-local counter values (from the current thread) 128 * Flush all thread-local counter values (from the current thread)
129 * to the global counter store. This method is not intended for use by any 129 * to the global counter store. This method is not intended for use by any
130 - * module. It's typical usage is from floodlight core and it is meant 130 + * module. It's typical usage is from core and it is meant
131 * to flush those counters that are updated in the packet-processing pipeline, 131 * to flush those counters that are updated in the packet-processing pipeline,
132 * typically with the 'updateCounterNoFlush" methods in IDebugCounter. 132 * typically with the 'updateCounterNoFlush" methods in IDebugCounter.
133 */ 133 */
......
...@@ -144,8 +144,8 @@ public class Controller { ...@@ -144,8 +144,8 @@ public class Controller {
144 + "activated: dpid {}. Found in activeMaster: {} " 144 + "activated: dpid {}. Found in activeMaster: {} "
145 + "Found in activeEqual: {}. Aborting ..", new Object[] { 145 + "Found in activeEqual: {}. Aborting ..", new Object[] {
146 HexString.toHexString(dpid), 146 HexString.toHexString(dpid),
147 - (activeMasterSwitches.get(dpid) == null) ? 'Y' : 'N', 147 + (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
148 - (activeEqualSwitches.get(dpid) == null) ? 'Y' : 'N'}); 148 + (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
149 counters.switchWithSameDpidActivated.updateCounterWithFlush(); 149 counters.switchWithSameDpidActivated.updateCounterWithFlush();
150 return false; 150 return false;
151 } 151 }
...@@ -372,17 +372,13 @@ public class Controller { ...@@ -372,17 +372,13 @@ public class Controller {
372 HexString.toHexString(dpidLong)); 372 HexString.toHexString(dpidLong));
373 return; 373 return;
374 } 374 }
375 - if (h.controlRequested) { 375 + if (registryService != null && h.controlRequested) {
376 + //TODO the above is not good for testing need to change controlrequest to method call.
376 registryService.releaseControl(dpidLong); 377 registryService.releaseControl(dpidLong);
377 } 378 }
378 } 379 }
379 380
380 381
381 -
382 - // ***************
383 - // IFloodlightProviderService
384 - // ***************
385 -
386 // FIXME: remove this method 382 // FIXME: remove this method
387 public Map<Long, IOFSwitch> getSwitches() { 383 public Map<Long, IOFSwitch> getSwitches() {
388 return getMasterSwitches(); 384 return getMasterSwitches();
...@@ -472,11 +468,6 @@ public class Controller { ...@@ -472,11 +468,6 @@ public class Controller {
472 } 468 }
473 469
474 470
475 - public void setAlwaysClearFlowsOnSwAdd(boolean value) {
476 - this.alwaysClearFlowsOnSwAdd = value;
477 - }
478 -
479 -
480 public InstanceId getInstanceId() { 471 public InstanceId getInstanceId() {
481 return instanceId; 472 return instanceId;
482 } 473 }
...@@ -587,15 +578,6 @@ public class Controller { ...@@ -587,15 +578,6 @@ public class Controller {
587 this.counters = new Counters(); 578 this.counters = new Counters();
588 this.multiCacheLock = new Object(); 579 this.multiCacheLock = new Object();
589 580
590 -
591 - String option = configParams.get("flushSwitchesOnReconnect");
592 - if (option != null && option.equalsIgnoreCase("true")) {
593 - this.setAlwaysClearFlowsOnSwActivate(true);
594 - log.info("Flush switches on reconnect -- Enabled.");
595 - } else {
596 - this.setAlwaysClearFlowsOnSwActivate(false);
597 - log.info("Flush switches on reconnect -- Disabled");
598 - }
599 } 581 }
600 582
601 /** 583 /**
...@@ -819,12 +801,6 @@ public class Controller { ...@@ -819,12 +801,6 @@ public class Controller {
819 // Utility methods 801 // Utility methods
820 // ************** 802 // **************
821 803
822 -
823 - public void setAlwaysClearFlowsOnSwActivate(boolean value) {
824 - //this.alwaysClearFlowsOnSwActivate = value;
825 - // XXX S need to be a little more careful about this
826 - }
827 -
828 public Map<String, Long> getMemory() { 804 public Map<String, Long> getMemory() {
829 Map<String, Long> m = new HashMap<String, Long>(); 805 Map<String, Long> m = new HashMap<String, Long>();
830 Runtime runtime = Runtime.getRuntime(); 806 Runtime runtime = Runtime.getRuntime();
......
...@@ -785,7 +785,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { ...@@ -785,7 +785,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
785 * description stats message, we: 785 * description stats message, we:
786 * - use the switch driver to bind the switch and get an IOFSwitch instance 786 * - use the switch driver to bind the switch and get an IOFSwitch instance
787 * - setup the IOFSwitch instance 787 * - setup the IOFSwitch instance
788 - * - add switch to FloodlightProvider(Controller) and send the initial role 788 + * - add switch controller and send the initial role
789 * request to the switch. 789 * request to the switch.
790 * Next state: WAIT_INITIAL_ROLE 790 * Next state: WAIT_INITIAL_ROLE
791 * In the typical case, where switches support role request messages 791 * In the typical case, where switches support role request messages
......
1 +/**
2 + * Copyright 2011, Big Switch Networks, Inc.
3 + * Originally created by David Erickson, Stanford University
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 + * not use this file except in compliance with the License. You may obtain
7 + * a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 + * License for the specific language governing permissions and limitations
15 + * under the License.
16 + **/
17 +
18 +package net.onrc.onos.of.ctl.internal;
19 +
20 +import junit.framework.TestCase;
21 +import net.onrc.onos.of.ctl.IOFSwitch;
22 +
23 +import org.easymock.EasyMock;
24 +import org.junit.After;
25 +import org.junit.Before;
26 +import org.junit.Test;
27 +
28 +
29 +public class ControllerTest extends TestCase {
30 +
31 + private Controller controller;
32 + private IOFSwitch sw;
33 + private OFChannelHandler h;
34 +
35 + @Override
36 + @Before
37 + public void setUp() throws Exception {
38 + super.setUp();
39 + sw = EasyMock.createMock(IOFSwitch.class);
40 + h = EasyMock.createMock(OFChannelHandler.class);
41 + controller = new Controller();
42 + ControllerRunThread t = new ControllerRunThread();
43 + t.start();
44 + /*
45 + * Making sure the thread is properly started before making calls
46 + * to controller class.
47 + */
48 + Thread.sleep(200);
49 + }
50 +
51 + /**
52 + * Starts the base mocks used in these tests.
53 + */
54 + private void startMocks() {
55 + EasyMock.replay(sw, h);
56 + }
57 +
58 + /**
59 + * Reset the mocks to a known state.
60 + * Automatically called after tests.
61 + */
62 + @After
63 + private void resetMocks() {
64 + EasyMock.reset(sw);
65 + }
66 +
67 + /**
68 + * Fetches the controller instance.
69 + * @return the controller
70 + */
71 + public Controller getController() {
72 + return controller;
73 + }
74 +
75 + /**
76 + * Run the controller's main loop so that updates are processed.
77 + */
78 + protected class ControllerRunThread extends Thread {
79 + @Override
80 + public void run() {
81 + controller.openFlowPort = 0; // Don't listen
82 + controller.activate();
83 + }
84 + }
85 +
86 + /**
87 + * Verify that we are able to add a switch that just connected.
88 + * If it already exists then this should fail
89 + *
90 + * @throws Exception error
91 + */
92 + @Test
93 + public void testAddConnectedSwitches() throws Exception {
94 + startMocks();
95 + assertTrue(controller.addConnectedSwitch(0, h));
96 + assertFalse(controller.addConnectedSwitch(0, h));
97 + }
98 +
99 + /**
100 + * Add active master but cannot re-add active master.
101 + * @throws Exception an error occurred.
102 + */
103 + @Test
104 + public void testAddActivatedMasterSwitch() throws Exception {
105 + startMocks();
106 + controller.addConnectedSwitch(0, h);
107 + assertTrue(controller.addActivatedMasterSwitch(0, sw));
108 + assertFalse(controller.addActivatedMasterSwitch(0, sw));
109 + }
110 +
111 + /**
112 + * Tests that an activated switch can be added but cannot be re-added.
113 + *
114 + * @throws Exception an error occurred
115 + */
116 + @Test
117 + public void testAddActivatedEqualSwitch() throws Exception {
118 + startMocks();
119 + controller.addConnectedSwitch(0, h);
120 + assertTrue(controller.addActivatedEqualSwitch(0, sw));
121 + assertFalse(controller.addActivatedEqualSwitch(0, sw));
122 + }
123 +
124 + /**
125 + * Move an equal switch to master.
126 + * @throws Exception an error occurred
127 + */
128 + @Test
129 + public void testTranstitionToMaster() throws Exception {
130 + startMocks();
131 + controller.addConnectedSwitch(0, h);
132 + controller.addActivatedEqualSwitch(0, sw);
133 + controller.transitionToMasterSwitch(0);
134 + assertNotNull(controller.getMasterSwitch(0));
135 + }
136 +
137 + /**
138 + * Transition a master switch to equal state.
139 + * @throws Exception an error occurred
140 + */
141 + @Test
142 + public void testTranstitionToEqual() throws Exception {
143 + startMocks();
144 + controller.addConnectedSwitch(0, h);
145 + controller.addActivatedMasterSwitch(0, sw);
146 + controller.transitionToEqualSwitch(0);
147 + assertNotNull(controller.getEqualSwitch(0));
148 + }
149 +
150 + /**
151 + * Remove the switch from the controller instance.
152 + * @throws Exception an error occurred
153 + */
154 + @Test
155 + public void testRemoveSwitch() throws Exception {
156 + sw.cancelAllStatisticsReplies();
157 + EasyMock.expectLastCall().once();
158 + sw.setConnected(false);
159 + EasyMock.expectLastCall().once();
160 + startMocks();
161 + controller.addConnectedSwitch(0, h);
162 + controller.addActivatedMasterSwitch(0, sw);
163 + controller.removeConnectedSwitch(0);
164 + assertNull(controller.getSwitch(0));
165 + EasyMock.verify(sw, h);
166 + }
167 +}
1 +package net.onrc.onos.of.ctl.internal;
2 +
3 +import static org.easymock.EasyMock.capture;
4 +import static org.easymock.EasyMock.createMock;
5 +import static org.easymock.EasyMock.expect;
6 +import static org.easymock.EasyMock.expectLastCall;
7 +import static org.easymock.EasyMock.replay;
8 +import static org.easymock.EasyMock.reset;
9 +import static org.easymock.EasyMock.verify;
10 +import static org.junit.Assert.assertEquals;
11 +import static org.junit.Assert.assertFalse;
12 +import static org.junit.Assert.assertTrue;
13 +
14 +import java.io.IOException;
15 +import java.util.ArrayList;
16 +import java.util.Collections;
17 +import java.util.HashSet;
18 +import java.util.List;
19 +import java.util.Set;
20 +
21 +import net.onrc.onos.of.ctl.IOFSwitch;
22 +import net.onrc.onos.of.ctl.Role;
23 +import net.onrc.onos.of.ctl.debugcounter.DebugCounter;
24 +import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService;
25 +import net.onrc.onos.of.ctl.internal.OFChannelHandler.RoleRecvStatus;
26 +
27 +import org.easymock.Capture;
28 +import org.easymock.CaptureType;
29 +import org.jboss.netty.channel.Channel;
30 +import org.jboss.netty.channel.ChannelHandlerContext;
31 +import org.jboss.netty.channel.ChannelPipeline;
32 +import org.jboss.netty.channel.ChannelStateEvent;
33 +import org.jboss.netty.channel.ExceptionEvent;
34 +import org.jboss.netty.channel.MessageEvent;
35 +import org.junit.After;
36 +import org.junit.Before;
37 +import org.junit.Test;
38 +import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
39 +import org.projectfloodlight.openflow.protocol.OFExperimenter;
40 +import org.projectfloodlight.openflow.protocol.OFFactories;
41 +import org.projectfloodlight.openflow.protocol.OFFactory;
42 +import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
43 +import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
44 +import org.projectfloodlight.openflow.protocol.OFHelloElem;
45 +import org.projectfloodlight.openflow.protocol.OFMessage;
46 +import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
47 +import org.projectfloodlight.openflow.protocol.OFPacketIn;
48 +import org.projectfloodlight.openflow.protocol.OFPacketInReason;
49 +import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
50 +import org.projectfloodlight.openflow.protocol.OFSetConfig;
51 +import org.projectfloodlight.openflow.protocol.OFStatsReply;
52 +import org.projectfloodlight.openflow.protocol.OFStatsRequest;
53 +import org.projectfloodlight.openflow.protocol.OFStatsType;
54 +import org.projectfloodlight.openflow.protocol.OFType;
55 +import org.projectfloodlight.openflow.protocol.OFVersion;
56 +import org.projectfloodlight.openflow.types.DatapathId;
57 +import 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 + */
66 +public 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 +}