blob: 9f43fcd264358d2308976853131fb785213371e8 [file] [log] [blame]
Dan Talaycodba244e2010-02-15 14:08:53 -08001"""
Dan Talayco79f36082010-03-11 16:53:53 -08002Basic protocol and dataplane test cases
Dan Talaycodba244e2010-02-15 14:08:53 -08003
Dan Talayco48370102010-03-03 15:17:33 -08004It is recommended that these definitions be kept in their own
5namespace as different groups of tests will likely define
6similar identifiers.
7
Dan Talaycodba244e2010-02-15 14:08:53 -08008Current Assumptions:
9
Dan Talayco41eae8b2010-03-10 13:57:06 -080010 The function test_set_init is called with a complete configuration
11dictionary prior to the invocation of any tests from this file.
12
Dan Talaycodba244e2010-02-15 14:08:53 -080013 The switch is actively attempting to contact the controller at the address
14indicated oin oft_config
15
16"""
17
Dan Talaycodba244e2010-02-15 14:08:53 -080018import time
Dan Talayco710438c2010-02-18 15:16:07 -080019import signal
Dan Talaycodba244e2010-02-15 14:08:53 -080020import sys
Dan Talayco48370102010-03-03 15:17:33 -080021import logging
Dan Talaycodba244e2010-02-15 14:08:53 -080022
Dan Talayco2c0dba32010-03-06 22:47:06 -080023import unittest
24
25import oftest.controller as controller
26import oftest.cstruct as ofp
27import oftest.message as message
28import oftest.dataplane as dataplane
29import oftest.action as action
30
Dan Talayco6ce963a2010-03-07 21:58:13 -080031from testutils import *
32
33#@var basic_port_map Local copy of the configuration map from OF port
34# numbers to OS interfaces
Dan Talayco48370102010-03-03 15:17:33 -080035basic_port_map = None
Dan Talayco6ce963a2010-03-07 21:58:13 -080036#@var basic_logger Local logger object
Dan Talayco48370102010-03-03 15:17:33 -080037basic_logger = None
Dan Talayco6ce963a2010-03-07 21:58:13 -080038#@var basic_config Local copy of global configuration data
Dan Talayco48370102010-03-03 15:17:33 -080039basic_config = None
40
Dan Talaycoc24aaae2010-07-08 14:05:24 -070041test_prio = {}
42
Dan Talayco48370102010-03-03 15:17:33 -080043def test_set_init(config):
44 """
45 Set up function for basic test classes
46
47 @param config The configuration dictionary; see oft
Dan Talayco48370102010-03-03 15:17:33 -080048 """
49
50 global basic_port_map
51 global basic_logger
52 global basic_config
53
54 basic_logger = logging.getLogger("basic")
55 basic_logger.info("Initializing test set")
56 basic_port_map = config["port_map"]
57 basic_config = config
Dan Talayco48370102010-03-03 15:17:33 -080058
Dan Talayco6ce963a2010-03-07 21:58:13 -080059class SimpleProtocol(unittest.TestCase):
Dan Talaycodba244e2010-02-15 14:08:53 -080060 """
61 Root class for setting up the controller
62 """
63
Dan Talaycoef701f42010-05-07 09:22:35 -070064 def sig_handler(self, v1, v2):
Dan Talayco48370102010-03-03 15:17:33 -080065 basic_logger.critical("Received interrupt signal; exiting")
Dan Talayco710438c2010-02-18 15:16:07 -080066 print "Received interrupt signal; exiting"
Dan Talayco2c0dba32010-03-06 22:47:06 -080067 self.clean_shutdown = False
68 self.tearDown()
Dan Talayco710438c2010-02-18 15:16:07 -080069 sys.exit(1)
70
Dan Talaycodba244e2010-02-15 14:08:53 -080071 def setUp(self):
Dan Talayco551befa2010-07-15 17:05:32 -070072 self.logger = basic_logger
Dan Talayco285a8382010-07-20 14:06:55 -070073 self.config = basic_config
Dan Talayco710438c2010-02-18 15:16:07 -080074 signal.signal(signal.SIGINT, self.sig_handler)
Dan Talayco9f47f4d2010-06-03 13:54:37 -070075 basic_logger.info("** START TEST CASE " + str(self))
Dan Talayco2c0dba32010-03-06 22:47:06 -080076 self.controller = controller.Controller(
77 host=basic_config["controller_host"],
78 port=basic_config["controller_port"])
Dan Talaycof8f41402010-03-12 22:17:39 -080079 # clean_shutdown should be set to False to force quit app
Dan Talayco2c0dba32010-03-06 22:47:06 -080080 self.clean_shutdown = True
Dan Talayco710438c2010-02-18 15:16:07 -080081 self.controller.start()
Dan Talaycoef701f42010-05-07 09:22:35 -070082 #@todo Add an option to wait for a pkt transaction to ensure version
83 # compatibilty?
Dan Talayco710438c2010-02-18 15:16:07 -080084 self.controller.connect(timeout=20)
Dan Talaycoef701f42010-05-07 09:22:35 -070085 if not self.controller.active:
86 print "Controller startup failed; exiting"
87 sys.exit(1)
Dan Talayco677c0b72011-08-23 22:53:38 -070088 if self.controller.switch_addr is None:
89 print "Controller startup failed (no switch addr); exiting"
90 sys.exit(1)
Dan Talayco48370102010-03-03 15:17:33 -080091 basic_logger.info("Connected " + str(self.controller.switch_addr))
Dan Talaycodba244e2010-02-15 14:08:53 -080092
Dan Talayco677cc112012-03-27 10:28:58 -070093 def inheritSetup(self, parent):
94 """
95 Inherit the setup of a parent
96
97 This allows running at test from within another test. Do the
98 following:
99
100 sub_test = SomeTestClass() # Create an instance of the test class
101 sub_test.inheritSetup(self) # Inherit setup of parent
102 sub_test.runTest() # Run the test
103
104 Normally, only the parent's setUp and tearDown are called and
105 the state after the sub_test is run must be taken into account
106 by subsequent operations.
107 """
108 self.logger = parent.logger
109 self.config = parent.config
110 basic_logger.info("** Setup " + str(self) + " inheriting from "
111 + str(parent))
112 self.controller = parent.controller
113
Dan Talaycodba244e2010-02-15 14:08:53 -0800114 def tearDown(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700115 basic_logger.info("** END TEST CASE " + str(self))
Dan Talaycodba244e2010-02-15 14:08:53 -0800116 self.controller.shutdown()
Dan Talayco2c0dba32010-03-06 22:47:06 -0800117 #@todo Review if join should be done on clean_shutdown
Dan Talaycof8f41402010-03-12 22:17:39 -0800118 if self.clean_shutdown:
119 self.controller.join()
Dan Talaycodba244e2010-02-15 14:08:53 -0800120
121 def runTest(self):
Dan Talayco710438c2010-02-18 15:16:07 -0800122 # Just a simple sanity check as illustration
Dan Talayco48370102010-03-03 15:17:33 -0800123 basic_logger.info("Running simple proto test")
Dan Talayco710438c2010-02-18 15:16:07 -0800124 self.assertTrue(self.controller.switch_socket is not None,
Dan Talaycodba244e2010-02-15 14:08:53 -0800125 str(self) + 'No connection to switch')
126
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700127 def assertTrue(self, cond, msg):
128 if not cond:
129 basic_logger.error("** FAILED ASSERTION: " + msg)
130 unittest.TestCase.assertTrue(self, cond, msg)
131
Dan Talaycoc24aaae2010-07-08 14:05:24 -0700132test_prio["SimpleProtocol"] = 1
133
Dan Talayco6ce963a2010-03-07 21:58:13 -0800134class SimpleDataPlane(SimpleProtocol):
Dan Talaycodba244e2010-02-15 14:08:53 -0800135 """
136 Root class that sets up the controller and dataplane
137 """
138 def setUp(self):
Dan Talayco6ce963a2010-03-07 21:58:13 -0800139 SimpleProtocol.setUp(self)
Dan Talayco2c0dba32010-03-06 22:47:06 -0800140 self.dataplane = dataplane.DataPlane()
Dan Talayco48370102010-03-03 15:17:33 -0800141 for of_port, ifname in basic_port_map.items():
Dan Talaycodba244e2010-02-15 14:08:53 -0800142 self.dataplane.port_add(ifname, of_port)
143
Dan Talayco677cc112012-03-27 10:28:58 -0700144 def inheritSetup(self, parent):
145 """
146 Inherit the setup of a parent
147
148 See SimpleProtocol.inheritSetup
149 """
150 SimpleProtocol.inheritSetup(self, parent)
151 self.dataplane = parent.dataplane
152
Dan Talaycodba244e2010-02-15 14:08:53 -0800153 def tearDown(self):
Dan Talayco48370102010-03-03 15:17:33 -0800154 basic_logger.info("Teardown for simple dataplane test")
Dan Talayco6ce963a2010-03-07 21:58:13 -0800155 SimpleProtocol.tearDown(self)
Dan Talayco2c0dba32010-03-06 22:47:06 -0800156 self.dataplane.kill(join_threads=self.clean_shutdown)
Dan Talayco48370102010-03-03 15:17:33 -0800157 basic_logger.info("Teardown done")
Dan Talaycodba244e2010-02-15 14:08:53 -0800158
159 def runTest(self):
Dan Talayco710438c2010-02-18 15:16:07 -0800160 self.assertTrue(self.controller.switch_socket is not None,
Dan Talaycodba244e2010-02-15 14:08:53 -0800161 str(self) + 'No connection to switch')
162 # self.dataplane.show()
163 # Would like an assert that checks the data plane
164
Dan Talayco551befa2010-07-15 17:05:32 -0700165class DataPlaneOnly(unittest.TestCase):
166 """
167 Root class that sets up only the dataplane
168 """
169
170 def sig_handler(self, v1, v2):
171 basic_logger.critical("Received interrupt signal; exiting")
172 print "Received interrupt signal; exiting"
173 self.clean_shutdown = False
174 self.tearDown()
175 sys.exit(1)
176
177 def setUp(self):
178 self.clean_shutdown = False
179 self.logger = basic_logger
Dan Talayco285a8382010-07-20 14:06:55 -0700180 self.config = basic_config
Dan Talayco551befa2010-07-15 17:05:32 -0700181 signal.signal(signal.SIGINT, self.sig_handler)
182 basic_logger.info("** START DataPlaneOnly CASE " + str(self))
183 self.dataplane = dataplane.DataPlane()
184 for of_port, ifname in basic_port_map.items():
185 self.dataplane.port_add(ifname, of_port)
186
187 def tearDown(self):
188 basic_logger.info("Teardown for simple dataplane test")
189 self.dataplane.kill(join_threads=self.clean_shutdown)
190 basic_logger.info("Teardown done")
191
192 def runTest(self):
Dan Talaycoba4fd4f2010-07-21 21:49:41 -0700193 basic_logger.info("DataPlaneOnly")
Dan Talayco285a8382010-07-20 14:06:55 -0700194 # self.dataplane.show()
Dan Talayco551befa2010-07-15 17:05:32 -0700195 # Would like an assert that checks the data plane
196
Dan Talayco6ce963a2010-03-07 21:58:13 -0800197class Echo(SimpleProtocol):
Dan Talaycodba244e2010-02-15 14:08:53 -0800198 """
199 Test echo response with no data
200 """
201 def runTest(self):
Dan Talayco2c0dba32010-03-06 22:47:06 -0800202 request = message.echo_request()
Dan Talaycoe226eb12010-02-18 23:06:30 -0800203 response, pkt = self.controller.transact(request)
Dan Talayco2c0dba32010-03-06 22:47:06 -0800204 self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,
Dan Talaycoa92e75b2010-02-16 20:53:56 -0800205 'response is not echo_reply')
Dan Talaycodba244e2010-02-15 14:08:53 -0800206 self.assertEqual(request.header.xid, response.header.xid,
207 'response xid != request xid')
208 self.assertEqual(len(response.data), 0, 'response data non-empty')
209
Dan Talayco6ce963a2010-03-07 21:58:13 -0800210class EchoWithData(SimpleProtocol):
Dan Talaycodba244e2010-02-15 14:08:53 -0800211 """
212 Test echo response with short string data
213 """
214 def runTest(self):
Dan Talayco2c0dba32010-03-06 22:47:06 -0800215 request = message.echo_request()
Dan Talaycodba244e2010-02-15 14:08:53 -0800216 request.data = 'OpenFlow Will Rule The World'
Dan Talaycoe226eb12010-02-18 23:06:30 -0800217 response, pkt = self.controller.transact(request)
Dan Talayco2c0dba32010-03-06 22:47:06 -0800218 self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,
Dan Talaycoa92e75b2010-02-16 20:53:56 -0800219 'response is not echo_reply')
Dan Talaycodba244e2010-02-15 14:08:53 -0800220 self.assertEqual(request.header.xid, response.header.xid,
221 'response xid != request xid')
222 self.assertEqual(request.data, response.data,
223 'response data does not match request')
224
Dan Talayco6ce963a2010-03-07 21:58:13 -0800225class PacketIn(SimpleDataPlane):
Dan Talaycodba244e2010-02-15 14:08:53 -0800226 """
227 Test packet in function
Dan Talayco6ce963a2010-03-07 21:58:13 -0800228
229 Send a packet to each dataplane port and verify that a packet
230 in message is received from the controller for each
Dan Talaycodba244e2010-02-15 14:08:53 -0800231 """
232 def runTest(self):
233 # Construct packet to send to dataplane
Dan Talaycoe226eb12010-02-18 23:06:30 -0800234 # Send packet to dataplane, once to each port
Dan Talaycodba244e2010-02-15 14:08:53 -0800235 # Poll controller with expect message type packet in
Dan Talaycoe226eb12010-02-18 23:06:30 -0800236
Dan Talayco6ce963a2010-03-07 21:58:13 -0800237 rc = delete_all_flows(self.controller, basic_logger)
238 self.assertEqual(rc, 0, "Failed to delete all flows")
Ed Swierk0caeb1e2012-03-19 15:01:56 -0700239 do_barrier(self.controller)
Dan Talayco6ce963a2010-03-07 21:58:13 -0800240
Dan Talayco48370102010-03-03 15:17:33 -0800241 for of_port in basic_port_map.keys():
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700242 for pkt, pt in [
243 (simple_tcp_packet(), "simple TCP packet"),
244 (simple_eth_packet(), "simple Ethernet packet"),
245 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
Dan Talaycodba244e2010-02-15 14:08:53 -0800246
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700247 basic_logger.info("PKT IN test with %s, port %s" % (pt, of_port))
248 self.dataplane.send(of_port, str(pkt))
249 #@todo Check for unexpected messages?
250 count = 0
251 while True:
252 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN, 2)
253 if not response: # Timeout
254 break
Ed Swierk506614a2012-03-29 08:16:59 -0700255 if dataplane.match_exp_pkt(pkt, response.data): # Got match
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700256 break
257 if not basic_config["relax"]: # Only one attempt to match
258 break
259 count += 1
260 if count > 10: # Too many tries
261 break
Dan Talayco48370102010-03-03 15:17:33 -0800262
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700263 self.assertTrue(response is not None,
264 'Packet in message not received on port ' +
265 str(of_port))
Ed Swierk506614a2012-03-29 08:16:59 -0700266 if not dataplane.match_exp_pkt(pkt, response.data):
Dan Talayco2baf8b52012-03-30 09:55:42 -0700267 basic_logger.debug("Sent %s" % format_packet(pkt))
268 basic_logger.debug("Resp %s" % format_packet(response.data))
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700269 self.assertTrue(False,
270 'Response packet does not match send packet' +
271 ' for port ' + str(of_port))
Dan Talaycodba244e2010-02-15 14:08:53 -0800272
Dan Talayco6ce963a2010-03-07 21:58:13 -0800273class PacketOut(SimpleDataPlane):
Dan Talaycodba244e2010-02-15 14:08:53 -0800274 """
275 Test packet out function
Dan Talayco6ce963a2010-03-07 21:58:13 -0800276
277 Send packet out message to controller for each dataplane port and
278 verify the packet appears on the appropriate dataplane port
Dan Talaycodba244e2010-02-15 14:08:53 -0800279 """
280 def runTest(self):
281 # Construct packet to send to dataplane
282 # Send packet to dataplane
283 # Poll controller with expect message type packet in
Dan Talayco41eae8b2010-03-10 13:57:06 -0800284
285 rc = delete_all_flows(self.controller, basic_logger)
286 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talaycodba244e2010-02-15 14:08:53 -0800287
288 # These will get put into function
Dan Talayco48370102010-03-03 15:17:33 -0800289 of_ports = basic_port_map.keys()
290 of_ports.sort()
291 for dp_port in of_ports:
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700292 for outpkt, opt in [
293 (simple_tcp_packet(), "simple TCP packet"),
294 (simple_eth_packet(), "simple Ethernet packet"),
295 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
Dan Talaycodba244e2010-02-15 14:08:53 -0800296
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700297 basic_logger.info("PKT OUT test with %s, port %s" % (opt, dp_port))
298 msg = message.packet_out()
299 msg.data = str(outpkt)
300 act = action.action_output()
301 act.port = dp_port
302 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
Dan Talaycodba244e2010-02-15 14:08:53 -0800303
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700304 basic_logger.info("PacketOut to: " + str(dp_port))
305 rv = self.controller.message_send(msg)
306 self.assertTrue(rv == 0, "Error sending out message")
Dan Talaycodba244e2010-02-15 14:08:53 -0800307
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700308 exp_pkt_arg = None
309 exp_port = None
310 if basic_config["relax"]:
311 exp_pkt_arg = outpkt
312 exp_port = dp_port
313 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=1,
314 port_number=exp_port,
315 exp_pkt=exp_pkt_arg)
316
317 self.assertTrue(pkt is not None, 'Packet not received')
318 basic_logger.info("PacketOut: got pkt from " + str(of_port))
319 if of_port is not None:
320 self.assertEqual(of_port, dp_port, "Unexpected receive port")
Ed Swierk506614a2012-03-29 08:16:59 -0700321 if not dataplane.match_exp_pkt(outpkt, pkt):
Dan Talayco2baf8b52012-03-30 09:55:42 -0700322 basic_logger.debug("Sent %s" % format_packet(outpkt))
323 basic_logger.debug("Resp %s" % format_packet(
324 str(pkt)[:len(str(outpkt))]))
Dan Talaycodc6fca32012-03-30 10:05:49 -0700325 self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
326 'Response packet does not match send packet')
Dan Talaycodba244e2010-02-15 14:08:53 -0800327
Dan Talayco6ce963a2010-03-07 21:58:13 -0800328class FlowStatsGet(SimpleProtocol):
329 """
330 Get stats
Dan Talayco2c0dba32010-03-06 22:47:06 -0800331
Dan Talayco6ce963a2010-03-07 21:58:13 -0800332 Simply verify stats get transaction
333 """
334 def runTest(self):
335 basic_logger.info("Running StatsGet")
Dan Talayco41eae8b2010-03-10 13:57:06 -0800336 basic_logger.info("Inserting trial flow")
Dan Talayco677c0b72011-08-23 22:53:38 -0700337 request = flow_mod_gen(basic_port_map, True)
Dan Talayco41eae8b2010-03-10 13:57:06 -0800338 rv = self.controller.message_send(request)
339 self.assertTrue(rv != -1, "Failed to insert test flow")
340
341 basic_logger.info("Sending flow request")
Dan Talayco6ce963a2010-03-07 21:58:13 -0800342 request = message.flow_stats_request()
343 request.out_port = ofp.OFPP_NONE
Dan Talayco41eae8b2010-03-10 13:57:06 -0800344 request.table_id = 0xff
345 request.match.wildcards = 0 # ofp.OFPFW_ALL
Dan Talayco6ce963a2010-03-07 21:58:13 -0800346 response, pkt = self.controller.transact(request, timeout=2)
347 self.assertTrue(response is not None, "Did not get response")
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700348 basic_logger.debug(response.show())
Dan Talayco6ce963a2010-03-07 21:58:13 -0800349
Dan Talayco677c0b72011-08-23 22:53:38 -0700350test_prio["FlowStatsGet"] = -1
351
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700352class TableStatsGet(SimpleProtocol):
353 """
354 Get table stats
355
356 Simply verify table stats get transaction
357 """
358 def runTest(self):
359 basic_logger.info("Running TableStatsGet")
360 basic_logger.info("Inserting trial flow")
Dan Talayco677c0b72011-08-23 22:53:38 -0700361 request = flow_mod_gen(basic_port_map, True)
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700362 rv = self.controller.message_send(request)
363 self.assertTrue(rv != -1, "Failed to insert test flow")
364
365 basic_logger.info("Sending table stats request")
366 request = message.table_stats_request()
367 response, pkt = self.controller.transact(request, timeout=2)
368 self.assertTrue(response is not None, "Did not get response")
369 basic_logger.debug(response.show())
370
Dan Talayco6ce963a2010-03-07 21:58:13 -0800371class FlowMod(SimpleProtocol):
372 """
373 Insert a flow
374
375 Simple verification of a flow mod transaction
376 """
377
378 def runTest(self):
379 basic_logger.info("Running " + str(self))
Dan Talayco677c0b72011-08-23 22:53:38 -0700380 request = flow_mod_gen(basic_port_map, True)
Dan Talayco6ce963a2010-03-07 21:58:13 -0800381 rv = self.controller.message_send(request)
Dan Talayco41eae8b2010-03-10 13:57:06 -0800382 self.assertTrue(rv != -1, "Error installing flow mod")
383
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700384class PortConfigMod(SimpleProtocol):
385 """
386 Modify a bit in port config and verify changed
387
388 Get the switch configuration, modify the port configuration
389 and write it back; get the config again and verify changed.
390 Then set it back to the way it was.
391 """
392
393 def runTest(self):
394 basic_logger.info("Running " + str(self))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700395 for of_port, ifname in basic_port_map.items(): # Grab first port
396 break
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700397
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700398 (hw_addr, config, advert) = \
399 port_config_get(self.controller, of_port, basic_logger)
400 self.assertTrue(config is not None, "Did not get port config")
401
402 basic_logger.debug("No flood bit port " + str(of_port) + " is now " +
403 str(config & ofp.OFPPC_NO_FLOOD))
404
405 rv = port_config_set(self.controller, of_port,
406 config ^ ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
407 basic_logger)
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700408 self.assertTrue(rv != -1, "Error sending port mod")
409
410 # Verify change took place with same feature request
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700411 (hw_addr, config2, advert) = \
412 port_config_get(self.controller, of_port, basic_logger)
413 basic_logger.debug("No flood bit port " + str(of_port) + " is now " +
414 str(config2 & ofp.OFPPC_NO_FLOOD))
415 self.assertTrue(config2 is not None, "Did not get port config2")
416 self.assertTrue(config2 & ofp.OFPPC_NO_FLOOD !=
417 config & ofp.OFPPC_NO_FLOOD,
418 "Bit change did not take")
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700419 # Set it back
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700420 rv = port_config_set(self.controller, of_port, config,
421 ofp.OFPPC_NO_FLOOD, basic_logger)
422 self.assertTrue(rv != -1, "Error sending port mod")
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700423
Dan Talaycodba244e2010-02-15 14:08:53 -0800424if __name__ == "__main__":
Dan Talayco2c0dba32010-03-06 22:47:06 -0800425 print "Please run through oft script: ./oft --test_spec=basic"