blob: 37c2e5251a9c09d2b3557a6087f5b6b6573ab430 [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
Rich Laned7b0ffa2013-03-08 15:53:42 -080015import ofp
Ken Chiangd6f5f862012-09-28 15:40:33 -070016import 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 Chiangd6f5f862012-09-28 15:40:33 -070028 def controllerSetup(self, host, port):
Ken Chiangadc950f2012-10-05 13:50:03 -070029 con = controller.Controller(host=host,port=port)
Ken Chiangd6f5f862012-09-28 15:40:33 -070030
31 # clean_shutdown should be set to False to force quit app
32 self.clean_shutdown = True
33 # disable initial hello so hello is under control of test
Ken Chiangadc950f2012-10-05 13:50:03 -070034 con.initial_hello = False
Ken Chiangd6f5f862012-09-28 15:40:33 -070035
Ken Chiangadc950f2012-10-05 13:50:03 -070036 con.start()
37 self.controllers.append(con)
Ken Chiangd6f5f862012-09-28 15:40:33 -070038
39 def setUp(self):
Rich Lane9a003812012-10-04 17:17:59 -070040 logging.info("** START TEST CASE " + str(self))
Ken Chiangd6f5f862012-09-28 15:40:33 -070041
Ed Swierkcfdcbd32013-01-02 18:44:52 -080042 self.controllers = []
Ken Chiange875baf2012-10-09 15:24:40 -070043 self.default_timeout = test_param_get('default_timeout',
44 default=2)
Ken Chiangd6f5f862012-09-28 15:40:33 -070045
Ken Chiangd6f5f862012-09-28 15:40:33 -070046 def tearDown(self):
Rich Lane9a003812012-10-04 17:17:59 -070047 logging.info("** END TEST CASE " + str(self))
Ken Chiangadc950f2012-10-05 13:50:03 -070048 for con in self.controllers:
49 con.shutdown()
50 if self.clean_shutdown:
51 con.join()
Ken Chiangd6f5f862012-09-28 15:40:33 -070052
53 def runTest(self):
54 # do nothing in the base case
55 pass
56
57 def assertTrue(self, cond, msg):
58 if not cond:
Rich Lane9a003812012-10-04 17:17:59 -070059 logging.error("** FAILED ASSERTION: " + msg)
Ken Chiangd6f5f862012-09-28 15:40:33 -070060 unittest.TestCase.assertTrue(self, cond, msg)
61
Ken Chiangd6f5f862012-09-28 15:40:33 -070062class HandshakeNoHello(BaseHandshake):
Ken Chiang35a74372012-10-01 15:39:25 -070063 """
64 TCP connect to switch, but do not sent hello,
65 and wait for disconnect.
66 """
Ken Chiangd6f5f862012-09-28 15:40:33 -070067 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -070068 self.controllerSetup(config["controller_host"],
69 config["controller_port"])
Ken Chiangadc950f2012-10-05 13:50:03 -070070 self.controllers[0].connect(self.default_timeout)
Ken Chiangd6f5f862012-09-28 15:40:33 -070071
Rich Lane9a003812012-10-04 17:17:59 -070072 logging.info("TCP Connected " +
Ken Chiange875baf2012-10-09 15:24:40 -070073 str(self.controllers[0].switch_addr))
Rich Lane9a003812012-10-04 17:17:59 -070074 logging.info("Hello not sent, waiting for timeout")
Ken Chiangd6f5f862012-09-28 15:40:33 -070075
76 # wait for controller to die
Ken Chiangadc950f2012-10-05 13:50:03 -070077 self.assertTrue(self.controllers[0].wait_disconnected(timeout=10),
78 "Not notified of controller disconnect")
Ken Chiangd6f5f862012-09-28 15:40:33 -070079
80class HandshakeNoFeaturesRequest(BaseHandshake):
Ken Chiang35a74372012-10-01 15:39:25 -070081 """
82 TCP connect to switch, send hello, but do not send features request,
83 and wait for disconnect.
84 """
Ken Chiangd6f5f862012-09-28 15:40:33 -070085 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -070086 self.controllerSetup(config["controller_host"],
87 config["controller_port"])
Ken Chiangadc950f2012-10-05 13:50:03 -070088 self.controllers[0].connect(self.default_timeout)
Ken Chiangd6f5f862012-09-28 15:40:33 -070089
Rich Lane9a003812012-10-04 17:17:59 -070090 logging.info("TCP Connected " +
Ken Chiange875baf2012-10-09 15:24:40 -070091 str(self.controllers[0].switch_addr))
Rich Lane9a003812012-10-04 17:17:59 -070092 logging.info("Sending hello")
Ken Chiangadc950f2012-10-05 13:50:03 -070093 self.controllers[0].message_send(message.hello())
Ken Chiangd6f5f862012-09-28 15:40:33 -070094
Rich Lane9a003812012-10-04 17:17:59 -070095 logging.info("Features request not sent, waiting for timeout")
Ken Chiangd6f5f862012-09-28 15:40:33 -070096
97 # wait for controller to die
Ken Chiangadc950f2012-10-05 13:50:03 -070098 self.assertTrue(self.controllers[0].wait_disconnected(timeout=10),
99 "Not notified of controller disconnect")
Ken Chiangd6f5f862012-09-28 15:40:33 -0700100
Rich Lane0a4f6372013-01-02 14:40:22 -0800101@disabled
Ken Chiang9c93e672012-12-18 12:00:14 -0800102class CompleteHandshake(BaseHandshake):
Ken Chiang35a74372012-10-01 15:39:25 -0700103 """
Ken Chiang9c93e672012-12-18 12:00:14 -0800104 Set up multiple controllers and complete handshake, but otherwise do nothing.
Ken Chiang35a74372012-10-01 15:39:25 -0700105 """
Rich Laned1d9c282012-10-04 22:07:10 -0700106
Ken Chiang9c93e672012-12-18 12:00:14 -0800107 def buildControllerList(self):
108 # controller_list is a list of IP:port tuples
109 con_list = test_param_get('controller_list')
110 if con_list is not None:
111 self.controller_list = []
112 for controller in con_list:
113 ip,portstr = controller.split(':')
114 try:
115 port = int(portstr)
116 except:
117 self.assertTrue(0, "failure converting port " +
118 portstr + " to integer")
119 self.controller_list.append( (ip, int(port)) )
120 else:
121 self.controller_list = [(config["controller_host"],
122 config["controller_port"])]
Ken Chiang35a74372012-10-01 15:39:25 -0700123
Ken Chiang9c93e672012-12-18 12:00:14 -0800124 def __init__(self, keep_alive=True, cxn_cycles=5,
125 controller_timeout=-1, hello_timeout=5,
126 features_req_timeout=5, disconnected_timeout=3):
127 BaseHandshake.__init__(self)
128 self.buildControllerList()
129 self.keep_alive = keep_alive
130 self.cxn_cycles = test_param_get('cxn_cycles') \
131 or cxn_cycles
132 self.controller_timeout = test_param_get('controller_timeout') \
133 or controller_timeout
134 self.hello_timeout = test_param_get('hello_timeout') \
135 or hello_timeout
136 self.features_req_timeout = test_param_get('features_req_timeout') \
137 or features_req_timeout
138 self.disconnected_timeout = test_param_get('disconnected_timeout') \
139 or disconnected_timeout
140
141 def runTest(self):
142 for conspec in self.controller_list:
143 self.controllerSetup(conspec[0], conspec[1])
144 for i in range(len(self.controller_list)):
Ken Chiang77173992012-10-30 15:44:39 -0700145 self.controllers[i].cstate = 0
Ken Chiang9c93e672012-12-18 12:00:14 -0800146 self.controllers[i].keep_alive = self.keep_alive
Ken Chiang74be4722012-12-21 13:07:03 -0800147 self.controllers[i].saved_switch_addr = None
Ken Chiang77173992012-10-30 15:44:39 -0700148 tick = 0.1 # time period in seconds at which controllers are handled
Ken Chiang35a74372012-10-01 15:39:25 -0700149
Ken Chiang9c93e672012-12-18 12:00:14 -0800150 disconnected_count = 0
151 cycle = 0
Ken Chiangadc950f2012-10-05 13:50:03 -0700152 while True:
Ken Chiang9c93e672012-12-18 12:00:14 -0800153 states = []
Ken Chiangadc950f2012-10-05 13:50:03 -0700154 for con in self.controllers:
Ken Chiang77173992012-10-30 15:44:39 -0700155 condesc = con.host + ":" + str(con.port) + ": "
156 logging.debug("Checking " + condesc)
Ken Chiang35a74372012-10-01 15:39:25 -0700157
Ken Chiang74be4722012-12-21 13:07:03 -0800158 if con.switch_socket:
159 if con.switch_addr != con.saved_switch_addr:
160 con.saved_switch_addr = con.switch_addr
161 con.cstate = 0
162
Ken Chiang77173992012-10-30 15:44:39 -0700163 if con.cstate == 0:
164 logging.info(condesc + "Sending hello to " +
165 str(con.switch_addr))
166 con.message_send(message.hello())
167 con.cstate = 1
168 con.count = 0
169 elif con.cstate == 1:
170 reply, pkt = con.poll(exp_msg=ofp.OFPT_HELLO,
171 timeout=0)
172 if reply is not None:
173 logging.info(condesc +
174 "Hello received from " +
175 str(con.switch_addr))
176 con.cstate = 2
177 else:
178 con.count = con.count + 1
179 # fall back to previous state on timeout
180 if con.count >= self.hello_timeout/tick:
181 logging.info(condesc +
182 "Timeout hello from " +
183 str(con.switch_addr))
184 con.cstate = 0
185 elif con.cstate == 2:
186 logging.info(condesc + "Sending features request to " +
187 str(con.switch_addr))
188 con.message_send(message.features_request())
189 con.cstate = 3
190 con.count = 0
191 elif con.cstate == 3:
192 reply, pkt = con.poll(exp_msg=ofp.OFPT_FEATURES_REPLY,
193 timeout=0)
194 if reply is not None:
195 logging.info(condesc +
196 "Features request received from " +
197 str(con.switch_addr))
198 con.cstate = 4
199 con.count = 0
Ken Chiang9c93e672012-12-18 12:00:14 -0800200 cycle = cycle + 1
Ken Chiang74be4722012-12-21 13:07:03 -0800201 logging.info("Cycle " + str(cycle))
Ken Chiang77173992012-10-30 15:44:39 -0700202 else:
203 con.count = con.count + 1
204 # fall back to previous state on timeout
205 if con.count >= self.features_req_timeout/tick:
206 logging.info(condesc +
207 "Timeout features request from " +
208 str(con.switch_addr))
209 con.cstate = 2
210 elif con.cstate == 4:
211 if (self.controller_timeout < 0 or
212 con.count < self.controller_timeout/tick):
213 logging.debug(condesc +
214 "Maintaining connection to " +
215 str(con.switch_addr))
216 con.count = con.count + 1
217 else:
218 logging.info(condesc +
219 "Disconnecting from " +
220 str(con.switch_addr))
221 con.disconnect()
222 con.cstate = 0
223 else:
224 con.cstate = 0
Ken Chiang9c93e672012-12-18 12:00:14 -0800225
226 states.append(con.cstate)
Ken Chiang77173992012-10-30 15:44:39 -0700227
Ken Chiang9c93e672012-12-18 12:00:14 -0800228 logging.debug("Cycle " + str(cycle) +
229 ", states " + str(states) +
230 ", disconnected_count " + str(disconnected_count))
231 if 4 in states:
232 disconnected_count = 0
233 else:
234 disconnected_count = disconnected_count + 1
235 if cycle != 0:
236 self.assertTrue(disconnected_count < self.disconnected_timeout/tick,
237 "Timeout expired connecting to controller")
238 else:
239 # on first cycle, allow more time for initial connect
240 self.assertTrue(disconnected_count < 2*self.disconnected_timeout/tick,
241 "Timeout expired connecting to controller on init")
242
243 if cycle > self.cxn_cycles:
244 break
Ken Chiang77173992012-10-30 15:44:39 -0700245 time.sleep(tick)
Ken Chiang9c93e672012-12-18 12:00:14 -0800246
Rich Lane0a4f6372013-01-02 14:40:22 -0800247@disabled
Ken Chiang9c93e672012-12-18 12:00:14 -0800248class HandshakeAndKeepalive(CompleteHandshake):
249 """
250 Complete handshake and respond to echo request, but otherwise do nothing.
251 Good for manual testing.
252 """
253
Ken Chiang9c93e672012-12-18 12:00:14 -0800254 def __init__(self):
255 CompleteHandshake.__init__(self, keep_alive=True)
256
Rich Lane0a4f6372013-01-02 14:40:22 -0800257@disabled
Ken Chiang9c93e672012-12-18 12:00:14 -0800258class HandshakeNoEcho(CompleteHandshake):
259 """
260 Complete handshake, but otherwise do nothing, and do not respond to echo.
261 """
262
Ken Chiang9c93e672012-12-18 12:00:14 -0800263 def __init__(self):
264 CompleteHandshake.__init__(self, keep_alive=False)
265
Rich Lane0a4f6372013-01-02 14:40:22 -0800266@disabled
Ken Chiang9c93e672012-12-18 12:00:14 -0800267class HandshakeAndDrop(CompleteHandshake):
268 """
269 Complete handshake, but otherwise do nothing, and drop connection after a while.
270 """
271
Ken Chiang9c93e672012-12-18 12:00:14 -0800272 def __init__(self):
273 CompleteHandshake.__init__(self, keep_alive=True, controller_timeout=10)
274