blob: 471fb2ab73a648bd8975932a1444be23015579b2 [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
Ken Chiang1bf01602012-04-04 10:48:23 -070024import random
Dan Talayco2c0dba32010-03-06 22:47:06 -080025
26import oftest.controller as controller
27import oftest.cstruct as ofp
28import oftest.message as message
29import oftest.dataplane as dataplane
30import oftest.action as action
31
Dan Talayco6ce963a2010-03-07 21:58:13 -080032from testutils import *
33
34#@var basic_port_map Local copy of the configuration map from OF port
35# numbers to OS interfaces
Dan Talayco48370102010-03-03 15:17:33 -080036basic_port_map = None
Dan Talayco6ce963a2010-03-07 21:58:13 -080037#@var basic_logger Local logger object
Dan Talayco48370102010-03-03 15:17:33 -080038basic_logger = None
Dan Talayco6ce963a2010-03-07 21:58:13 -080039#@var basic_config Local copy of global configuration data
Dan Talayco48370102010-03-03 15:17:33 -080040basic_config = None
41
Dan Talaycoc24aaae2010-07-08 14:05:24 -070042test_prio = {}
43
Dan Talayco48370102010-03-03 15:17:33 -080044def test_set_init(config):
45 """
46 Set up function for basic test classes
47
48 @param config The configuration dictionary; see oft
Dan Talayco48370102010-03-03 15:17:33 -080049 """
50
51 global basic_port_map
52 global basic_logger
53 global basic_config
54
55 basic_logger = logging.getLogger("basic")
56 basic_logger.info("Initializing test set")
57 basic_port_map = config["port_map"]
58 basic_config = config
Dan Talayco48370102010-03-03 15:17:33 -080059
Dan Talayco6ce963a2010-03-07 21:58:13 -080060class SimpleProtocol(unittest.TestCase):
Dan Talaycodba244e2010-02-15 14:08:53 -080061 """
62 Root class for setting up the controller
63 """
64
Dan Talaycoef701f42010-05-07 09:22:35 -070065 def sig_handler(self, v1, v2):
Dan Talayco48370102010-03-03 15:17:33 -080066 basic_logger.critical("Received interrupt signal; exiting")
Dan Talayco710438c2010-02-18 15:16:07 -080067 print "Received interrupt signal; exiting"
Dan Talayco2c0dba32010-03-06 22:47:06 -080068 self.clean_shutdown = False
69 self.tearDown()
Dan Talayco710438c2010-02-18 15:16:07 -080070 sys.exit(1)
71
Dan Talaycodba244e2010-02-15 14:08:53 -080072 def setUp(self):
Dan Talayco551befa2010-07-15 17:05:32 -070073 self.logger = basic_logger
Dan Talayco285a8382010-07-20 14:06:55 -070074 self.config = basic_config
Dan Talayco710438c2010-02-18 15:16:07 -080075 signal.signal(signal.SIGINT, self.sig_handler)
Dan Talayco9f47f4d2010-06-03 13:54:37 -070076 basic_logger.info("** START TEST CASE " + str(self))
Dan Talayco2c0dba32010-03-06 22:47:06 -080077 self.controller = controller.Controller(
78 host=basic_config["controller_host"],
79 port=basic_config["controller_port"])
Dan Talaycof8f41402010-03-12 22:17:39 -080080 # clean_shutdown should be set to False to force quit app
Dan Talayco2c0dba32010-03-06 22:47:06 -080081 self.clean_shutdown = True
Dan Talayco710438c2010-02-18 15:16:07 -080082 self.controller.start()
Dan Talaycoef701f42010-05-07 09:22:35 -070083 #@todo Add an option to wait for a pkt transaction to ensure version
84 # compatibilty?
Dan Talayco710438c2010-02-18 15:16:07 -080085 self.controller.connect(timeout=20)
Dan Talaycoef701f42010-05-07 09:22:35 -070086 if not self.controller.active:
87 print "Controller startup failed; exiting"
88 sys.exit(1)
Dan Talayco677c0b72011-08-23 22:53:38 -070089 if self.controller.switch_addr is None:
90 print "Controller startup failed (no switch addr); exiting"
91 sys.exit(1)
Dan Talayco48370102010-03-03 15:17:33 -080092 basic_logger.info("Connected " + str(self.controller.switch_addr))
Dan Talaycodba244e2010-02-15 14:08:53 -080093
Dan Talayco677cc112012-03-27 10:28:58 -070094 def inheritSetup(self, parent):
95 """
96 Inherit the setup of a parent
97
98 This allows running at test from within another test. Do the
99 following:
100
101 sub_test = SomeTestClass() # Create an instance of the test class
102 sub_test.inheritSetup(self) # Inherit setup of parent
103 sub_test.runTest() # Run the test
104
105 Normally, only the parent's setUp and tearDown are called and
106 the state after the sub_test is run must be taken into account
107 by subsequent operations.
108 """
109 self.logger = parent.logger
110 self.config = parent.config
111 basic_logger.info("** Setup " + str(self) + " inheriting from "
112 + str(parent))
113 self.controller = parent.controller
114
Dan Talaycodba244e2010-02-15 14:08:53 -0800115 def tearDown(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700116 basic_logger.info("** END TEST CASE " + str(self))
Dan Talaycodba244e2010-02-15 14:08:53 -0800117 self.controller.shutdown()
Dan Talayco2c0dba32010-03-06 22:47:06 -0800118 #@todo Review if join should be done on clean_shutdown
Dan Talaycof8f41402010-03-12 22:17:39 -0800119 if self.clean_shutdown:
120 self.controller.join()
Dan Talaycodba244e2010-02-15 14:08:53 -0800121
122 def runTest(self):
Dan Talayco710438c2010-02-18 15:16:07 -0800123 # Just a simple sanity check as illustration
Dan Talayco48370102010-03-03 15:17:33 -0800124 basic_logger.info("Running simple proto test")
Dan Talayco710438c2010-02-18 15:16:07 -0800125 self.assertTrue(self.controller.switch_socket is not None,
Dan Talaycodba244e2010-02-15 14:08:53 -0800126 str(self) + 'No connection to switch')
127
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700128 def assertTrue(self, cond, msg):
129 if not cond:
130 basic_logger.error("** FAILED ASSERTION: " + msg)
131 unittest.TestCase.assertTrue(self, cond, msg)
132
Dan Talaycoc24aaae2010-07-08 14:05:24 -0700133test_prio["SimpleProtocol"] = 1
134
Dan Talayco6ce963a2010-03-07 21:58:13 -0800135class SimpleDataPlane(SimpleProtocol):
Dan Talaycodba244e2010-02-15 14:08:53 -0800136 """
137 Root class that sets up the controller and dataplane
138 """
139 def setUp(self):
Dan Talayco6ce963a2010-03-07 21:58:13 -0800140 SimpleProtocol.setUp(self)
Dan Talayco2c0dba32010-03-06 22:47:06 -0800141 self.dataplane = dataplane.DataPlane()
Dan Talayco48370102010-03-03 15:17:33 -0800142 for of_port, ifname in basic_port_map.items():
Dan Talaycodba244e2010-02-15 14:08:53 -0800143 self.dataplane.port_add(ifname, of_port)
144
Dan Talayco677cc112012-03-27 10:28:58 -0700145 def inheritSetup(self, parent):
146 """
147 Inherit the setup of a parent
148
149 See SimpleProtocol.inheritSetup
150 """
151 SimpleProtocol.inheritSetup(self, parent)
152 self.dataplane = parent.dataplane
153
Dan Talaycodba244e2010-02-15 14:08:53 -0800154 def tearDown(self):
Dan Talayco48370102010-03-03 15:17:33 -0800155 basic_logger.info("Teardown for simple dataplane test")
Dan Talayco6ce963a2010-03-07 21:58:13 -0800156 SimpleProtocol.tearDown(self)
Dan Talayco2c0dba32010-03-06 22:47:06 -0800157 self.dataplane.kill(join_threads=self.clean_shutdown)
Dan Talayco48370102010-03-03 15:17:33 -0800158 basic_logger.info("Teardown done")
Dan Talaycodba244e2010-02-15 14:08:53 -0800159
160 def runTest(self):
Dan Talayco710438c2010-02-18 15:16:07 -0800161 self.assertTrue(self.controller.switch_socket is not None,
Dan Talaycodba244e2010-02-15 14:08:53 -0800162 str(self) + 'No connection to switch')
163 # self.dataplane.show()
164 # Would like an assert that checks the data plane
165
Dan Talayco551befa2010-07-15 17:05:32 -0700166class DataPlaneOnly(unittest.TestCase):
167 """
168 Root class that sets up only the dataplane
169 """
170
171 def sig_handler(self, v1, v2):
172 basic_logger.critical("Received interrupt signal; exiting")
173 print "Received interrupt signal; exiting"
174 self.clean_shutdown = False
175 self.tearDown()
176 sys.exit(1)
177
178 def setUp(self):
179 self.clean_shutdown = False
180 self.logger = basic_logger
Dan Talayco285a8382010-07-20 14:06:55 -0700181 self.config = basic_config
Dan Talayco551befa2010-07-15 17:05:32 -0700182 signal.signal(signal.SIGINT, self.sig_handler)
183 basic_logger.info("** START DataPlaneOnly CASE " + str(self))
184 self.dataplane = dataplane.DataPlane()
185 for of_port, ifname in basic_port_map.items():
186 self.dataplane.port_add(ifname, of_port)
187
188 def tearDown(self):
189 basic_logger.info("Teardown for simple dataplane test")
190 self.dataplane.kill(join_threads=self.clean_shutdown)
191 basic_logger.info("Teardown done")
192
193 def runTest(self):
Dan Talaycoba4fd4f2010-07-21 21:49:41 -0700194 basic_logger.info("DataPlaneOnly")
Dan Talayco285a8382010-07-20 14:06:55 -0700195 # self.dataplane.show()
Dan Talayco551befa2010-07-15 17:05:32 -0700196 # Would like an assert that checks the data plane
197
Dan Talayco6ce963a2010-03-07 21:58:13 -0800198class Echo(SimpleProtocol):
Dan Talaycodba244e2010-02-15 14:08:53 -0800199 """
200 Test echo response with no data
201 """
202 def runTest(self):
Dan Talayco2c0dba32010-03-06 22:47:06 -0800203 request = message.echo_request()
Dan Talaycoe226eb12010-02-18 23:06:30 -0800204 response, pkt = self.controller.transact(request)
Dan Talayco2c0dba32010-03-06 22:47:06 -0800205 self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,
Dan Talaycoa92e75b2010-02-16 20:53:56 -0800206 'response is not echo_reply')
Dan Talaycodba244e2010-02-15 14:08:53 -0800207 self.assertEqual(request.header.xid, response.header.xid,
208 'response xid != request xid')
209 self.assertEqual(len(response.data), 0, 'response data non-empty')
210
Dan Talayco6ce963a2010-03-07 21:58:13 -0800211class EchoWithData(SimpleProtocol):
Dan Talaycodba244e2010-02-15 14:08:53 -0800212 """
213 Test echo response with short string data
214 """
215 def runTest(self):
Dan Talayco2c0dba32010-03-06 22:47:06 -0800216 request = message.echo_request()
Dan Talaycodba244e2010-02-15 14:08:53 -0800217 request.data = 'OpenFlow Will Rule The World'
Dan Talaycoe226eb12010-02-18 23:06:30 -0800218 response, pkt = self.controller.transact(request)
Dan Talayco2c0dba32010-03-06 22:47:06 -0800219 self.assertEqual(response.header.type, ofp.OFPT_ECHO_REPLY,
Dan Talaycoa92e75b2010-02-16 20:53:56 -0800220 'response is not echo_reply')
Dan Talaycodba244e2010-02-15 14:08:53 -0800221 self.assertEqual(request.header.xid, response.header.xid,
222 'response xid != request xid')
223 self.assertEqual(request.data, response.data,
224 'response data does not match request')
225
Dan Talayco6ce963a2010-03-07 21:58:13 -0800226class PacketIn(SimpleDataPlane):
Dan Talaycodba244e2010-02-15 14:08:53 -0800227 """
228 Test packet in function
Dan Talayco6ce963a2010-03-07 21:58:13 -0800229
230 Send a packet to each dataplane port and verify that a packet
231 in message is received from the controller for each
Dan Talaycodba244e2010-02-15 14:08:53 -0800232 """
233 def runTest(self):
234 # Construct packet to send to dataplane
Dan Talaycoe226eb12010-02-18 23:06:30 -0800235 # Send packet to dataplane, once to each port
Dan Talaycodba244e2010-02-15 14:08:53 -0800236 # Poll controller with expect message type packet in
Dan Talaycoe226eb12010-02-18 23:06:30 -0800237
Dan Talayco6ce963a2010-03-07 21:58:13 -0800238 rc = delete_all_flows(self.controller, basic_logger)
239 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700240 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco6ce963a2010-03-07 21:58:13 -0800241
Dan Talayco48370102010-03-03 15:17:33 -0800242 for of_port in basic_port_map.keys():
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700243 for pkt, pt in [
244 (simple_tcp_packet(), "simple TCP packet"),
245 (simple_eth_packet(), "simple Ethernet packet"),
246 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
Dan Talaycodba244e2010-02-15 14:08:53 -0800247
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700248 basic_logger.info("PKT IN test with %s, port %s" % (pt, of_port))
249 self.dataplane.send(of_port, str(pkt))
250 #@todo Check for unexpected messages?
251 count = 0
252 while True:
253 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN, 2)
254 if not response: # Timeout
255 break
Ed Swierk506614a2012-03-29 08:16:59 -0700256 if dataplane.match_exp_pkt(pkt, response.data): # Got match
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700257 break
258 if not basic_config["relax"]: # Only one attempt to match
259 break
260 count += 1
261 if count > 10: # Too many tries
262 break
Dan Talayco48370102010-03-03 15:17:33 -0800263
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700264 self.assertTrue(response is not None,
265 'Packet in message not received on port ' +
266 str(of_port))
Ed Swierk506614a2012-03-29 08:16:59 -0700267 if not dataplane.match_exp_pkt(pkt, response.data):
Dan Talayco2baf8b52012-03-30 09:55:42 -0700268 basic_logger.debug("Sent %s" % format_packet(pkt))
269 basic_logger.debug("Resp %s" % format_packet(response.data))
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700270 self.assertTrue(False,
271 'Response packet does not match send packet' +
272 ' for port ' + str(of_port))
Dan Talaycodba244e2010-02-15 14:08:53 -0800273
Dan Talayco6ce963a2010-03-07 21:58:13 -0800274class PacketOut(SimpleDataPlane):
Dan Talaycodba244e2010-02-15 14:08:53 -0800275 """
276 Test packet out function
Dan Talayco6ce963a2010-03-07 21:58:13 -0800277
278 Send packet out message to controller for each dataplane port and
279 verify the packet appears on the appropriate dataplane port
Dan Talaycodba244e2010-02-15 14:08:53 -0800280 """
281 def runTest(self):
282 # Construct packet to send to dataplane
283 # Send packet to dataplane
284 # Poll controller with expect message type packet in
Dan Talayco41eae8b2010-03-10 13:57:06 -0800285
286 rc = delete_all_flows(self.controller, basic_logger)
287 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talaycodba244e2010-02-15 14:08:53 -0800288
289 # These will get put into function
Dan Talayco48370102010-03-03 15:17:33 -0800290 of_ports = basic_port_map.keys()
291 of_ports.sort()
292 for dp_port in of_ports:
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700293 for outpkt, opt in [
294 (simple_tcp_packet(), "simple TCP packet"),
295 (simple_eth_packet(), "simple Ethernet packet"),
296 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
Dan Talaycodba244e2010-02-15 14:08:53 -0800297
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700298 basic_logger.info("PKT OUT test with %s, port %s" % (opt, dp_port))
299 msg = message.packet_out()
300 msg.data = str(outpkt)
301 act = action.action_output()
302 act.port = dp_port
303 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
Dan Talaycodba244e2010-02-15 14:08:53 -0800304
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700305 basic_logger.info("PacketOut to: " + str(dp_port))
306 rv = self.controller.message_send(msg)
307 self.assertTrue(rv == 0, "Error sending out message")
Dan Talaycodba244e2010-02-15 14:08:53 -0800308
Ed Swierk0aeff8c2012-03-23 20:27:18 -0700309 exp_pkt_arg = None
310 exp_port = None
311 if basic_config["relax"]:
312 exp_pkt_arg = outpkt
313 exp_port = dp_port
314 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=1,
315 port_number=exp_port,
316 exp_pkt=exp_pkt_arg)
317
318 self.assertTrue(pkt is not None, 'Packet not received')
319 basic_logger.info("PacketOut: got pkt from " + str(of_port))
320 if of_port is not None:
321 self.assertEqual(of_port, dp_port, "Unexpected receive port")
Ed Swierk506614a2012-03-29 08:16:59 -0700322 if not dataplane.match_exp_pkt(outpkt, pkt):
Dan Talayco2baf8b52012-03-30 09:55:42 -0700323 basic_logger.debug("Sent %s" % format_packet(outpkt))
324 basic_logger.debug("Resp %s" % format_packet(
325 str(pkt)[:len(str(outpkt))]))
Dan Talaycodc6fca32012-03-30 10:05:49 -0700326 self.assertEqual(str(outpkt), str(pkt)[:len(str(outpkt))],
327 'Response packet does not match send packet')
Dan Talaycodba244e2010-02-15 14:08:53 -0800328
Ken Chiang1bf01602012-04-04 10:48:23 -0700329class PacketOutMC(SimpleDataPlane):
330 """
331 Test packet out to multiple output ports
332
333 Send packet out message to controller for 1 to N dataplane ports and
334 verify the packet appears on the appropriate ports
335 """
336 def runTest(self):
337 # Construct packet to send to dataplane
338 # Send packet to dataplane
339 # Poll controller with expect message type packet in
340
341 rc = delete_all_flows(self.controller, basic_logger)
342 self.assertEqual(rc, 0, "Failed to delete all flows")
343
344 # These will get put into function
345 of_ports = basic_port_map.keys()
346 random.shuffle(of_ports)
347 for num_ports in range(1,len(of_ports)+1):
348 for outpkt, opt in [
349 (simple_tcp_packet(), "simple TCP packet"),
350 (simple_eth_packet(), "simple Ethernet packet"),
351 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
352
353 dp_ports = of_ports[0:num_ports]
354 basic_logger.info("PKT OUT test with " + opt +
355 ", ports " + str(dp_ports))
356 msg = message.packet_out()
357 msg.data = str(outpkt)
358 act = action.action_output()
359 for i in range(0,num_ports):
360 act.port = dp_ports[i]
361 self.assertTrue(msg.actions.add(act),
362 'Could not add action to msg')
363
364 basic_logger.info("PacketOut to: " + str(dp_ports))
365 rv = self.controller.message_send(msg)
366 self.assertTrue(rv == 0, "Error sending out message")
367
368 receive_pkt_check(self.dataplane, outpkt, dp_ports,
369 set(of_ports).difference(dp_ports),
370 self, basic_logger, basic_config)
371
Dan Talayco6ce963a2010-03-07 21:58:13 -0800372class FlowStatsGet(SimpleProtocol):
373 """
374 Get stats
Dan Talayco2c0dba32010-03-06 22:47:06 -0800375
Dan Talayco6ce963a2010-03-07 21:58:13 -0800376 Simply verify stats get transaction
377 """
378 def runTest(self):
379 basic_logger.info("Running StatsGet")
Dan Talayco41eae8b2010-03-10 13:57:06 -0800380 basic_logger.info("Inserting trial flow")
Dan Talayco677c0b72011-08-23 22:53:38 -0700381 request = flow_mod_gen(basic_port_map, True)
Dan Talayco41eae8b2010-03-10 13:57:06 -0800382 rv = self.controller.message_send(request)
383 self.assertTrue(rv != -1, "Failed to insert test flow")
384
385 basic_logger.info("Sending flow request")
Dan Talayco6ce963a2010-03-07 21:58:13 -0800386 request = message.flow_stats_request()
387 request.out_port = ofp.OFPP_NONE
Dan Talayco41eae8b2010-03-10 13:57:06 -0800388 request.table_id = 0xff
389 request.match.wildcards = 0 # ofp.OFPFW_ALL
Dan Talayco6ce963a2010-03-07 21:58:13 -0800390 response, pkt = self.controller.transact(request, timeout=2)
391 self.assertTrue(response is not None, "Did not get response")
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700392 basic_logger.debug(response.show())
Dan Talayco6ce963a2010-03-07 21:58:13 -0800393
Dan Talayco677c0b72011-08-23 22:53:38 -0700394test_prio["FlowStatsGet"] = -1
395
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700396class TableStatsGet(SimpleProtocol):
397 """
398 Get table stats
399
400 Simply verify table stats get transaction
401 """
402 def runTest(self):
403 basic_logger.info("Running TableStatsGet")
404 basic_logger.info("Inserting trial flow")
Dan Talayco677c0b72011-08-23 22:53:38 -0700405 request = flow_mod_gen(basic_port_map, True)
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700406 rv = self.controller.message_send(request)
407 self.assertTrue(rv != -1, "Failed to insert test flow")
408
409 basic_logger.info("Sending table stats request")
410 request = message.table_stats_request()
411 response, pkt = self.controller.transact(request, timeout=2)
412 self.assertTrue(response is not None, "Did not get response")
413 basic_logger.debug(response.show())
414
Ed Swierkae74c362012-04-02 08:21:41 -0700415class DescStatsGet(SimpleProtocol):
416 """
417 Get stats
418
419 Simply verify stats get transaction
420 """
421 def runTest(self):
422 basic_logger.info("Running DescStatsGet")
423
424 basic_logger.info("Sending stats request")
425 request = message.desc_stats_request()
426 response, pkt = self.controller.transact(request, timeout=2)
427 self.assertTrue(response is not None, "Did not get response")
428 basic_logger.debug(response.show())
429
Dan Talayco6ce963a2010-03-07 21:58:13 -0800430class FlowMod(SimpleProtocol):
431 """
432 Insert a flow
433
434 Simple verification of a flow mod transaction
435 """
436
437 def runTest(self):
438 basic_logger.info("Running " + str(self))
Dan Talayco677c0b72011-08-23 22:53:38 -0700439 request = flow_mod_gen(basic_port_map, True)
Dan Talayco6ce963a2010-03-07 21:58:13 -0800440 rv = self.controller.message_send(request)
Dan Talayco41eae8b2010-03-10 13:57:06 -0800441 self.assertTrue(rv != -1, "Error installing flow mod")
442
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700443class PortConfigMod(SimpleProtocol):
444 """
445 Modify a bit in port config and verify changed
446
447 Get the switch configuration, modify the port configuration
448 and write it back; get the config again and verify changed.
449 Then set it back to the way it was.
450 """
451
452 def runTest(self):
453 basic_logger.info("Running " + str(self))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700454 for of_port, ifname in basic_port_map.items(): # Grab first port
455 break
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700456
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700457 (hw_addr, config, advert) = \
458 port_config_get(self.controller, of_port, basic_logger)
459 self.assertTrue(config is not None, "Did not get port config")
460
461 basic_logger.debug("No flood bit port " + str(of_port) + " is now " +
462 str(config & ofp.OFPPC_NO_FLOOD))
463
464 rv = port_config_set(self.controller, of_port,
465 config ^ ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
466 basic_logger)
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700467 self.assertTrue(rv != -1, "Error sending port mod")
468
469 # Verify change took place with same feature request
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700470 (hw_addr, config2, advert) = \
471 port_config_get(self.controller, of_port, basic_logger)
472 basic_logger.debug("No flood bit port " + str(of_port) + " is now " +
473 str(config2 & ofp.OFPPC_NO_FLOOD))
474 self.assertTrue(config2 is not None, "Did not get port config2")
475 self.assertTrue(config2 & ofp.OFPPC_NO_FLOOD !=
476 config & ofp.OFPPC_NO_FLOOD,
477 "Bit change did not take")
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700478 # Set it back
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700479 rv = port_config_set(self.controller, of_port, config,
480 ofp.OFPPC_NO_FLOOD, basic_logger)
481 self.assertTrue(rv != -1, "Error sending port mod")
Dan Talaycob3f43fe2010-05-13 14:24:20 -0700482
Dan Talaycodba244e2010-02-15 14:08:53 -0800483if __name__ == "__main__":
Dan Talayco2c0dba32010-03-06 22:47:06 -0800484 print "Please run through oft script: ./oft --test_spec=basic"