blob: 9f80d4b338e4e1b20af8ec00f2f550dae767521a [file] [log] [blame]
Dan Talayco79c6c4d2010-06-08 14:01:53 -07001"""
2Basic capabilities and capacities tests
3
4"""
5
6import logging
7
8import unittest
9
Rich Lane477f4812012-10-04 22:49:00 -070010from oftest import config
Dan Talayco79c6c4d2010-06-08 14:01:53 -070011import oftest.controller as controller
12import oftest.cstruct as ofp
13import oftest.message as message
14import oftest.dataplane as dataplane
15import oftest.action as action
16import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070017import oftest.base_tests as base_tests
Dan Talayco79c6c4d2010-06-08 14:01:53 -070018
Rich Laneda3b5ad2012-10-03 09:05:32 -070019from oftest.testutils import *
Dan Talayco79c6c4d2010-06-08 14:01:53 -070020
Dan Talayco79c6c4d2010-06-08 14:01:53 -070021def flow_caps_common(obj, is_exact=True):
22 """
23 The common function for
24
25 @param obj The calling object
26 @param is_exact If True, checking exact match; else wildcard
27 """
28
Rich Lane477f4812012-10-04 22:49:00 -070029 of_ports = config["port_map"].keys()
Dan Talayco79c6c4d2010-06-08 14:01:53 -070030 of_ports.sort()
31
Rich Lane9a003812012-10-04 17:17:59 -070032 rv = delete_all_flows(obj.controller)
Dan Talayco79c6c4d2010-06-08 14:01:53 -070033 obj.assertEqual(rv, 0, "Failed to delete all flows")
34
35 pkt = simple_tcp_packet()
Ed Swierk6192e512012-08-22 11:41:40 -070036 match = packet_to_flow_match(obj, pkt)
Dan Talayco79c6c4d2010-06-08 14:01:53 -070037 obj.assertTrue(match is not None, "Could not generate flow match from pkt")
38 for port in of_ports:
39 break;
40 match.in_port = port
41 match.nw_src = 1
42 request = message.flow_mod()
43 count_check = 101 # fixme: better way to determine this.
44 if is_exact:
45 match.wildcards = 0
46 else:
47 match.wildcards |= ofp.OFPFW_DL_SRC
48
49 request.match = match
Rob Sherwood9130bcd2012-03-07 12:23:50 -080050 request.buffer_id = 0xffffffff # set to NONE
Rich Lane9a003812012-10-04 17:17:59 -070051 logging.info(request.show())
Dan Talayco79c6c4d2010-06-08 14:01:53 -070052
53 tstats = message.table_stats_request()
54 try: # Determine the table index to check (or "all")
Rich Lane477f4812012-10-04 22:49:00 -070055 table_idx = config["caps_table_idx"]
Dan Talayco79c6c4d2010-06-08 14:01:53 -070056 except:
57 table_idx = -1 # Accumulate all table counts
58
59 # Make sure we can install at least one flow
Rich Lane9a003812012-10-04 17:17:59 -070060 logging.info("Inserting initial flow")
Rich Lane5c3151c2013-01-03 17:15:41 -080061 obj.controller.message_send(request)
Shudong Zhoub7f12462012-11-20 13:01:12 -080062 obj.assertEqual(do_barrier(obj.controller, timeout=10), 0, "Barrier failed")
Dan Talayco79c6c4d2010-06-08 14:01:53 -070063 flow_count = 1
64
Rich Lane9a003812012-10-04 17:17:59 -070065 logging.info("Table idx: " + str(table_idx))
66 logging.info("Check every " + str(count_check) + " inserts")
Dan Talayco79c6c4d2010-06-08 14:01:53 -070067
68 while True:
69 request.match.nw_src += 1
Rich Lane5c3151c2013-01-03 17:15:41 -080070 obj.controller.message_send(request)
Dan Talayco79c6c4d2010-06-08 14:01:53 -070071 flow_count += 1
72 if flow_count % count_check == 0:
Shudong Zhoub7f12462012-11-20 13:01:12 -080073 obj.assertEqual(do_barrier(obj.controller, timeout=10), 0, "Barrier failed")
Rich Lanec8aaa3e2012-07-26 19:28:02 -070074 response, pkt = obj.controller.transact(tstats)
Dan Talayco79c6c4d2010-06-08 14:01:53 -070075 obj.assertTrue(response is not None, "Get tab stats failed")
Rich Lane9a003812012-10-04 17:17:59 -070076 logging.info(response.show())
Dan Talayco79c6c4d2010-06-08 14:01:53 -070077 if table_idx == -1: # Accumulate for all tables
78 active_flows = 0
79 for stats in response.stats:
80 active_flows += stats.active_count
81 else: # Table index to use specified in config
82 active_flows = response.stats[table_idx].active_count
83 if active_flows != flow_count:
84 break
85
Rich Lane9a003812012-10-04 17:17:59 -070086 logging.error("RESULT: " + str(flow_count) + " flows inserted")
87 logging.error("RESULT: " + str(active_flows) + " flows reported")
Dan Talayco79c6c4d2010-06-08 14:01:53 -070088
Shudong Zhoud71c4a72012-11-18 14:37:43 -080089 # clean up and wait a bit in case the table is really big
90 rv = delete_all_flows(obj.controller)
91 time.sleep(flow_count / 100)
92
93
Dan Talayco79c6c4d2010-06-08 14:01:53 -070094
Rich Laneb90a1c42012-10-05 09:16:05 -070095class FillTableExact(base_tests.SimpleProtocol):
Dan Talayco79c6c4d2010-06-08 14:01:53 -070096 """
Dan Talayco8f91a5b2010-07-20 14:07:21 -070097 Fill the flow table with exact matches; can take a while
Dan Talayco79c6c4d2010-06-08 14:01:53 -070098
99 Fill table until no more flows can be added. Report result.
100 Increment the source IP address. Assume the flow table will
101 fill in less than 4 billion inserts
102
103 To check the number of flows in the tables is expensive, so
104 it's only done periodically. This is controlled by the
105 count_check variable.
106
107 A switch may have multiple tables. The default behaviour
108 is to count all the flows in all the tables. By setting
109 the parameter "caps_table_idx" in the configuration array,
110 you can control which table to check.
111 """
Rich Laned1d9c282012-10-04 22:07:10 -0700112
113 priority = -1
114
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700115 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700116 logging.info("Running " + str(self))
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700117 flow_caps_common(self)
118
Rich Laneb90a1c42012-10-05 09:16:05 -0700119class FillTableWC(base_tests.SimpleProtocol):
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700120 """
121 Fill the flow table with wildcard matches
122
123 Fill table using wildcard entries until no more flows can be
124 added. Report result.
125 Increment the source IP address. Assume the flow table will
126 fill in less than 4 billion inserts
127
128 To check the number of flows in the tables is expensive, so
129 it's only done periodically. This is controlled by the
130 count_check variable.
131
132 A switch may have multiple tables. The default behaviour
133 is to count all the flows in all the tables. By setting
134 the parameter "caps_table_idx" in the configuration array,
135 you can control which table to check.
136
137 """
Rich Laned1d9c282012-10-04 22:07:10 -0700138
139 priority = -1
140
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700141 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700142 logging.info("Running " + str(self))
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700143 flow_caps_common(self, is_exact=False)