blob: 4b3ee59bc1ab7688afb7b9a1a579bffea7839930 [file] [log] [blame]
Ken Chiangd6f5f862012-09-28 15:40:33 -07001"""
2Connection test cases
3
4"""
5
6import time
Ken Chiangd6f5f862012-09-28 15:40:33 -07007import sys
8import logging
9
10import unittest
11import random
12
Rich Lane477f4812012-10-04 22:49:00 -070013from oftest import config
Ken Chiangd6f5f862012-09-28 15:40:33 -070014import oftest.controller as controller
15import oftest.cstruct as ofp
16import oftest.message as message
17import oftest.dataplane as dataplane
18import oftest.action as action
19
Rich Laneda3b5ad2012-10-03 09:05:32 -070020from oftest.testutils import *
Ken Chiangd6f5f862012-09-28 15:40:33 -070021
Rich Lane0a4f6372013-01-02 14:40:22 -080022@disabled
Ken Chiangd6f5f862012-09-28 15:40:33 -070023class BaseHandshake(unittest.TestCase):
24 """
25 Base handshake case to set up controller, but do not send hello.
26 """
27
Ken Chiangadc950f2012-10-05 13:50:03 -070028 controllers = []
29 default_timeout = 2
30
Ken Chiangd6f5f862012-09-28 15:40:33 -070031 def controllerSetup(self, host, port):
Ken Chiangadc950f2012-10-05 13:50:03 -070032 con = controller.Controller(host=host,port=port)
Ken Chiangd6f5f862012-09-28 15:40:33 -070033
34 # clean_shutdown should be set to False to force quit app
35 self.clean_shutdown = True
36 # disable initial hello so hello is under control of test
Ken Chiangadc950f2012-10-05 13:50:03 -070037 con.initial_hello = False
Ken Chiangd6f5f862012-09-28 15:40:33 -070038
Ken Chiangadc950f2012-10-05 13:50:03 -070039 con.start()
40 self.controllers.append(con)
Ken Chiangd6f5f862012-09-28 15:40:33 -070041
42 def setUp(self):
Rich Lane9a003812012-10-04 17:17:59 -070043 logging.info("** START TEST CASE " + str(self))
Ken Chiangd6f5f862012-09-28 15:40:33 -070044
Ken Chiange875baf2012-10-09 15:24:40 -070045 self.default_timeout = test_param_get('default_timeout',
46 default=2)
Ken Chiangd6f5f862012-09-28 15:40:33 -070047
Ken Chiangd6f5f862012-09-28 15:40:33 -070048 def tearDown(self):
Rich Lane9a003812012-10-04 17:17:59 -070049 logging.info("** END TEST CASE " + str(self))
Ken Chiangadc950f2012-10-05 13:50:03 -070050 for con in self.controllers:
51 con.shutdown()
52 if self.clean_shutdown:
53 con.join()
Ken Chiangd6f5f862012-09-28 15:40:33 -070054
55 def runTest(self):
56 # do nothing in the base case
57 pass
58
59 def assertTrue(self, cond, msg):
60 if not cond:
Rich Lane9a003812012-10-04 17:17:59 -070061 logging.error("** FAILED ASSERTION: " + msg)
Ken Chiangd6f5f862012-09-28 15:40:33 -070062 unittest.TestCase.assertTrue(self, cond, msg)
63
Ken Chiangd6f5f862012-09-28 15:40:33 -070064class HandshakeNoHello(BaseHandshake):
Ken Chiang35a74372012-10-01 15:39:25 -070065 """
66 TCP connect to switch, but do not sent hello,
67 and wait for disconnect.
68 """
Ken Chiangd6f5f862012-09-28 15:40:33 -070069 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -070070 self.controllerSetup(config["controller_host"],
71 config["controller_port"])
Ken Chiangadc950f2012-10-05 13:50:03 -070072 self.controllers[0].connect(self.default_timeout)
Ken Chiangd6f5f862012-09-28 15:40:33 -070073
Rich Lane9a003812012-10-04 17:17:59 -070074 logging.info("TCP Connected " +
Ken Chiange875baf2012-10-09 15:24:40 -070075 str(self.controllers[0].switch_addr))
Rich Lane9a003812012-10-04 17:17:59 -070076 logging.info("Hello not sent, waiting for timeout")
Ken Chiangd6f5f862012-09-28 15:40:33 -070077
78 # wait for controller to die
Ken Chiangadc950f2012-10-05 13:50:03 -070079 self.assertTrue(self.controllers[0].wait_disconnected(timeout=10),
80 "Not notified of controller disconnect")
Ken Chiangd6f5f862012-09-28 15:40:33 -070081
82class HandshakeNoFeaturesRequest(BaseHandshake):
Ken Chiang35a74372012-10-01 15:39:25 -070083 """
84 TCP connect to switch, send hello, but do not send features request,
85 and wait for disconnect.
86 """
Ken Chiangd6f5f862012-09-28 15:40:33 -070087 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -070088 self.controllerSetup(config["controller_host"],
89 config["controller_port"])
Ken Chiangadc950f2012-10-05 13:50:03 -070090 self.controllers[0].connect(self.default_timeout)
Ken Chiangd6f5f862012-09-28 15:40:33 -070091
Rich Lane9a003812012-10-04 17:17:59 -070092 logging.info("TCP Connected " +
Ken Chiange875baf2012-10-09 15:24:40 -070093 str(self.controllers[0].switch_addr))
Rich Lane9a003812012-10-04 17:17:59 -070094 logging.info("Sending hello")
Ken Chiangadc950f2012-10-05 13:50:03 -070095 self.controllers[0].message_send(message.hello())
Ken Chiangd6f5f862012-09-28 15:40:33 -070096
Rich Lane9a003812012-10-04 17:17:59 -070097 logging.info("Features request not sent, waiting for timeout")
Ken Chiangd6f5f862012-09-28 15:40:33 -070098
99 # wait for controller to die
Ken Chiangadc950f2012-10-05 13:50:03 -0700100 self.assertTrue(self.controllers[0].wait_disconnected(timeout=10),
101 "Not notified of controller disconnect")
Ken Chiangd6f5f862012-09-28 15:40:33 -0700102
Rich Lane0a4f6372013-01-02 14:40:22 -0800103@disabled
Ken Chiang9c93e672012-12-18 12:00:14 -0800104class CompleteHandshake(BaseHandshake):
Ken Chiang35a74372012-10-01 15:39:25 -0700105 """
Ken Chiang9c93e672012-12-18 12:00:14 -0800106 Set up multiple controllers and complete handshake, but otherwise do nothing.
Ken Chiang35a74372012-10-01 15:39:25 -0700107 """
Rich Laned1d9c282012-10-04 22:07:10 -0700108
Ken Chiang9c93e672012-12-18 12:00:14 -0800109 def buildControllerList(self):
110 # controller_list is a list of IP:port tuples
111 con_list = test_param_get('controller_list')
112 if con_list is not None:
113 self.controller_list = []
114 for controller in con_list:
115 ip,portstr = controller.split(':')
116 try:
117 port = int(portstr)
118 except:
119 self.assertTrue(0, "failure converting port " +
120 portstr + " to integer")
121 self.controller_list.append( (ip, int(port)) )
122 else:
123 self.controller_list = [(config["controller_host"],
124 config["controller_port"])]
Ken Chiang35a74372012-10-01 15:39:25 -0700125
Ken Chiang9c93e672012-12-18 12:00:14 -0800126 def __init__(self, keep_alive=True, cxn_cycles=5,
127 controller_timeout=-1, hello_timeout=5,
128 features_req_timeout=5, disconnected_timeout=3):
129 BaseHandshake.__init__(self)
130 self.buildControllerList()
131 self.keep_alive = keep_alive
132 self.cxn_cycles = test_param_get('cxn_cycles') \
133 or cxn_cycles
134 self.controller_timeout = test_param_get('controller_timeout') \
135 or controller_timeout
136 self.hello_timeout = test_param_get('hello_timeout') \
137 or hello_timeout
138 self.features_req_timeout = test_param_get('features_req_timeout') \
139 or features_req_timeout
140 self.disconnected_timeout = test_param_get('disconnected_timeout') \
141 or disconnected_timeout
142
143 def runTest(self):
144 for conspec in self.controller_list:
145 self.controllerSetup(conspec[0], conspec[1])
146 for i in range(len(self.controller_list)):
Ken Chiang77173992012-10-30 15:44:39 -0700147 self.controllers[i].cstate = 0
Ken Chiang9c93e672012-12-18 12:00:14 -0800148 self.controllers[i].keep_alive = self.keep_alive
Ken Chiang74be4722012-12-21 13:07:03 -0800149 self.controllers[i].saved_switch_addr = None
Ken Chiang77173992012-10-30 15:44:39 -0700150 tick = 0.1 # time period in seconds at which controllers are handled
Ken Chiang35a74372012-10-01 15:39:25 -0700151
Ken Chiang9c93e672012-12-18 12:00:14 -0800152 disconnected_count = 0
153 cycle = 0
Ken Chiangadc950f2012-10-05 13:50:03 -0700154 while True:
Ken Chiang9c93e672012-12-18 12:00:14 -0800155 states = []
Ken Chiangadc950f2012-10-05 13:50:03 -0700156 for con in self.controllers:
Ken Chiang77173992012-10-30 15:44:39 -0700157 condesc = con.host + ":" + str(con.port) + ": "
158 logging.debug("Checking " + condesc)
Ken Chiang35a74372012-10-01 15:39:25 -0700159
Ken Chiang74be4722012-12-21 13:07:03 -0800160 if con.switch_socket:
161 if con.switch_addr != con.saved_switch_addr:
162 con.saved_switch_addr = con.switch_addr
163 con.cstate = 0
164
Ken Chiang77173992012-10-30 15:44:39 -0700165 if con.cstate == 0:
166 logging.info(condesc + "Sending hello to " +
167 str(con.switch_addr))
168 con.message_send(message.hello())
169 con.cstate = 1
170 con.count = 0
171 elif con.cstate == 1:
172 reply, pkt = con.poll(exp_msg=ofp.OFPT_HELLO,
173 timeout=0)
174 if reply is not None:
175 logging.info(condesc +
176 "Hello received from " +
177 str(con.switch_addr))
178 con.cstate = 2
179 else:
180 con.count = con.count + 1
181 # fall back to previous state on timeout
182 if con.count >= self.hello_timeout/tick:
183 logging.info(condesc +
184 "Timeout hello from " +
185 str(con.switch_addr))
186 con.cstate = 0
187 elif con.cstate == 2:
188 logging.info(condesc + "Sending features request to " +
189 str(con.switch_addr))
190 con.message_send(message.features_request())
191 con.cstate = 3
192 con.count = 0
193 elif con.cstate == 3:
194 reply, pkt = con.poll(exp_msg=ofp.OFPT_FEATURES_REPLY,
195 timeout=0)
196 if reply is not None:
197 logging.info(condesc +
198 "Features request received from " +
199 str(con.switch_addr))
200 con.cstate = 4
201 con.count = 0
Ken Chiang9c93e672012-12-18 12:00:14 -0800202 cycle = cycle + 1
Ken Chiang74be4722012-12-21 13:07:03 -0800203 logging.info("Cycle " + str(cycle))
Ken Chiang77173992012-10-30 15:44:39 -0700204 else:
205 con.count = con.count + 1
206 # fall back to previous state on timeout
207 if con.count >= self.features_req_timeout/tick:
208 logging.info(condesc +
209 "Timeout features request from " +
210 str(con.switch_addr))
211 con.cstate = 2
212 elif con.cstate == 4:
213 if (self.controller_timeout < 0 or
214 con.count < self.controller_timeout/tick):
215 logging.debug(condesc +
216 "Maintaining connection to " +
217 str(con.switch_addr))
218 con.count = con.count + 1
219 else:
220 logging.info(condesc +
221 "Disconnecting from " +
222 str(con.switch_addr))
223 con.disconnect()
224 con.cstate = 0
225 else:
226 con.cstate = 0
Ken Chiang9c93e672012-12-18 12:00:14 -0800227
228 states.append(con.cstate)
Ken Chiang77173992012-10-30 15:44:39 -0700229
Ken Chiang9c93e672012-12-18 12:00:14 -0800230 logging.debug("Cycle " + str(cycle) +
231 ", states " + str(states) +
232 ", disconnected_count " + str(disconnected_count))
233 if 4 in states:
234 disconnected_count = 0
235 else:
236 disconnected_count = disconnected_count + 1
237 if cycle != 0:
238 self.assertTrue(disconnected_count < self.disconnected_timeout/tick,
239 "Timeout expired connecting to controller")
240 else:
241 # on first cycle, allow more time for initial connect
242 self.assertTrue(disconnected_count < 2*self.disconnected_timeout/tick,
243 "Timeout expired connecting to controller on init")
244
245 if cycle > self.cxn_cycles:
246 break
Ken Chiang77173992012-10-30 15:44:39 -0700247 time.sleep(tick)
Ken Chiang9c93e672012-12-18 12:00:14 -0800248
Rich Lane0a4f6372013-01-02 14:40:22 -0800249@disabled
Ken Chiang9c93e672012-12-18 12:00:14 -0800250class HandshakeAndKeepalive(CompleteHandshake):
251 """
252 Complete handshake and respond to echo request, but otherwise do nothing.
253 Good for manual testing.
254 """
255
Ken Chiang9c93e672012-12-18 12:00:14 -0800256 def __init__(self):
257 CompleteHandshake.__init__(self, keep_alive=True)
258
Rich Lane0a4f6372013-01-02 14:40:22 -0800259@disabled
Ken Chiang9c93e672012-12-18 12:00:14 -0800260class HandshakeNoEcho(CompleteHandshake):
261 """
262 Complete handshake, but otherwise do nothing, and do not respond to echo.
263 """
264
Ken Chiang9c93e672012-12-18 12:00:14 -0800265 def __init__(self):
266 CompleteHandshake.__init__(self, keep_alive=False)
267
Rich Lane0a4f6372013-01-02 14:40:22 -0800268@disabled
Ken Chiang9c93e672012-12-18 12:00:14 -0800269class HandshakeAndDrop(CompleteHandshake):
270 """
271 Complete handshake, but otherwise do nothing, and drop connection after a while.
272 """
273
Ken Chiang9c93e672012-12-18 12:00:14 -0800274 def __init__(self):
275 CompleteHandshake.__init__(self, keep_alive=True, controller_timeout=10)
276