blob: 2c566921105b8de9624dba00dc87df840a502ca1 [file] [log] [blame]
Ken Chiangd6f5f862012-09-28 15:40:33 -07001"""
2Connection test cases
3
4"""
5
6import time
7import signal
8import sys
9import logging
10
11import unittest
12import random
13
14import 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
22#@var cxn_port_map Local copy of the configuration map from OF port
23# numbers to OS interfaces
24cxn_port_map = None
Ken Chiangd6f5f862012-09-28 15:40:33 -070025#@var cxn_config Local copy of global configuration data
26cxn_config = None
27
28test_prio = {}
29
30def test_set_init(config):
31 """
32 Set up function for connection test classes
33
34 @param config The configuration dictionary; see oft
35 """
36
37 global cxn_port_map
Ken Chiangd6f5f862012-09-28 15:40:33 -070038 global cxn_config
39
Ken Chiangd6f5f862012-09-28 15:40:33 -070040 cxn_port_map = config["port_map"]
41 cxn_config = config
42
43class BaseHandshake(unittest.TestCase):
44 """
45 Base handshake case to set up controller, but do not send hello.
46 """
47
48 def sig_handler(self, v1, v2):
Rich Lane9a003812012-10-04 17:17:59 -070049 logging.critical("Received interrupt signal; exiting")
Ken Chiangd6f5f862012-09-28 15:40:33 -070050 print "Received interrupt signal; exiting"
51 self.clean_shutdown = False
52 self.tearDown()
53 sys.exit(1)
54
55 def controllerSetup(self, host, port):
56 self.controller = controller.Controller(host=host,port=port)
57
58 # clean_shutdown should be set to False to force quit app
59 self.clean_shutdown = True
60 # disable initial hello so hello is under control of test
61 self.controller.initial_hello = False
62
63 self.controller.start()
64 #@todo Add an option to wait for a pkt transaction to ensure version
65 # compatibilty?
66 self.controller.connect(timeout=10)
67 self.assertTrue(self.controller.active,
68 "Controller startup failed, not active")
69 self.assertTrue(self.controller.switch_addr is not None,
70 "Controller startup failed, no switch addr")
71
72 def setUp(self):
Ken Chiangd6f5f862012-09-28 15:40:33 -070073 self.config = cxn_config
74 #@todo Test cases shouldn't monkey with signals; move SIGINT handler
75 # to top-level oft
76 try:
77 signal.signal(signal.SIGINT, self.sig_handler)
78 except ValueError, e:
Rich Lane9a003812012-10-04 17:17:59 -070079 logging.info("Could not set SIGINT handler: %s" % e)
80 logging.info("** START TEST CASE " + str(self))
Ken Chiangd6f5f862012-09-28 15:40:33 -070081
82 self.test_timeout = test_param_get(cxn_config,
83 'handshake_timeout') or 60
84
85 def inheritSetup(self, parent):
86 """
87 Inherit the setup of a parent
88
89 This allows running at test from within another test. Do the
90 following:
91
92 sub_test = SomeTestClass() # Create an instance of the test class
93 sub_test.inheritSetup(self) # Inherit setup of parent
94 sub_test.runTest() # Run the test
95
96 Normally, only the parent's setUp and tearDown are called and
97 the state after the sub_test is run must be taken into account
98 by subsequent operations.
99 """
Ken Chiangd6f5f862012-09-28 15:40:33 -0700100 self.config = parent.config
Rich Lane9a003812012-10-04 17:17:59 -0700101 logging.info("** Setup " + str(self) +
Ken Chiangd6f5f862012-09-28 15:40:33 -0700102 " inheriting from " + str(parent))
103 self.controller = parent.controller
104
105 def tearDown(self):
Rich Lane9a003812012-10-04 17:17:59 -0700106 logging.info("** END TEST CASE " + str(self))
Ken Chiangd6f5f862012-09-28 15:40:33 -0700107 self.controller.shutdown()
108 if self.clean_shutdown:
109 self.controller.join()
110
111 def runTest(self):
112 # do nothing in the base case
113 pass
114
115 def assertTrue(self, cond, msg):
116 if not cond:
Rich Lane9a003812012-10-04 17:17:59 -0700117 logging.error("** FAILED ASSERTION: " + msg)
Ken Chiangd6f5f862012-09-28 15:40:33 -0700118 unittest.TestCase.assertTrue(self, cond, msg)
119
120test_prio["BaseHandshake"] = -1
121
122class HandshakeNoHello(BaseHandshake):
Ken Chiang35a74372012-10-01 15:39:25 -0700123 """
124 TCP connect to switch, but do not sent hello,
125 and wait for disconnect.
126 """
Ken Chiangd6f5f862012-09-28 15:40:33 -0700127 def runTest(self):
128 self.controllerSetup(cxn_config["controller_host"],
129 cxn_config["controller_port"])
130
Rich Lane9a003812012-10-04 17:17:59 -0700131 logging.info("TCP Connected " +
Ken Chiangd6f5f862012-09-28 15:40:33 -0700132 str(self.controller.switch_addr))
Rich Lane9a003812012-10-04 17:17:59 -0700133 logging.info("Hello not sent, waiting for timeout")
Ken Chiangd6f5f862012-09-28 15:40:33 -0700134
135 # wait for controller to die
136 count = 0
137 while self.controller.active and count < self.test_timeout:
138 time.sleep(1)
139 count = count + 1
140 self.assertTrue(not self.controller.active,
141 "Expected controller disconnect, but still active")
142
143class HandshakeNoFeaturesRequest(BaseHandshake):
Ken Chiang35a74372012-10-01 15:39:25 -0700144 """
145 TCP connect to switch, send hello, but do not send features request,
146 and wait for disconnect.
147 """
Ken Chiangd6f5f862012-09-28 15:40:33 -0700148 def runTest(self):
149 self.controllerSetup(cxn_config["controller_host"],
150 cxn_config["controller_port"])
151
Rich Lane9a003812012-10-04 17:17:59 -0700152 logging.info("TCP Connected " +
Ken Chiangd6f5f862012-09-28 15:40:33 -0700153 str(self.controller.switch_addr))
Rich Lane9a003812012-10-04 17:17:59 -0700154 logging.info("Sending hello")
Ken Chiangd6f5f862012-09-28 15:40:33 -0700155 self.controller.message_send(message.hello())
156
Rich Lane9a003812012-10-04 17:17:59 -0700157 logging.info("Features request not sent, waiting for timeout")
Ken Chiangd6f5f862012-09-28 15:40:33 -0700158
159 # wait for controller to die
160 count = 0
161 while self.controller.active and count < self.test_timeout:
162 time.sleep(1)
163 count = count + 1
164 self.assertTrue(not self.controller.active,
165 "Expected controller disconnect, but still active")
166
Ken Chiang35a74372012-10-01 15:39:25 -0700167class HandshakeAndKeepalive(BaseHandshake):
168 """
169 Complete handshake and respond to echo request, but otherwise do nothing.
170 Good for manual testing.
171 """
172 def runTest(self):
173 self.controllerSetup(cxn_config["controller_host"],
174 cxn_config["controller_port"])
175
Rich Lane9a003812012-10-04 17:17:59 -0700176 logging.info("TCP Connected " +
Ken Chiang35a74372012-10-01 15:39:25 -0700177 str(self.controller.switch_addr))
Rich Lane9a003812012-10-04 17:17:59 -0700178 logging.info("Sending hello")
Ken Chiang35a74372012-10-01 15:39:25 -0700179 self.controller.message_send(message.hello())
180
181 request = message.features_request()
182 reply, pkt = self.controller.transact(request, timeout=20)
183 self.assertTrue(reply is not None,
184 "Did not complete features_request for handshake")
Rich Lane9a003812012-10-04 17:17:59 -0700185 logging.info("Handshake complete with " +
Ken Chiang35a74372012-10-01 15:39:25 -0700186 str(self.controller.switch_addr))
187
188 self.controller.keep_alive = True
189
190 # keep controller up forever
191 while self.controller.active:
192 time.sleep(1)
193
194 self.assertTrue(not self.controller.active,
195 "Expected controller disconnect, but still active")
196
197test_prio["HandshakeAndKeepalive"] = -1
198