blob: 946a266f1de9b7fd0cd4f02fa4c40ef4d00f951c [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")
Dan Talayco79c6c4d2010-06-08 14:01:53 -070061 rv = obj.controller.message_send(request)
62 obj.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco2757e0a2012-05-02 09:28:52 -070063 obj.assertEqual(do_barrier(obj.controller), 0, "Barrier failed")
Dan Talayco79c6c4d2010-06-08 14:01:53 -070064 flow_count = 1
65
Rich Lane9a003812012-10-04 17:17:59 -070066 logging.info("Table idx: " + str(table_idx))
67 logging.info("Check every " + str(count_check) + " inserts")
Dan Talayco79c6c4d2010-06-08 14:01:53 -070068
69 while True:
70 request.match.nw_src += 1
71 rv = obj.controller.message_send(request)
Dan Talayco79c6c4d2010-06-08 14:01:53 -070072 flow_count += 1
73 if flow_count % count_check == 0:
Dan Talayco2757e0a2012-05-02 09:28:52 -070074 obj.assertEqual(do_barrier(obj.controller), 0, "Barrier failed")
Rich Lanec8aaa3e2012-07-26 19:28:02 -070075 response, pkt = obj.controller.transact(tstats)
Dan Talayco79c6c4d2010-06-08 14:01:53 -070076 obj.assertTrue(response is not None, "Get tab stats failed")
Rich Lane9a003812012-10-04 17:17:59 -070077 logging.info(response.show())
Dan Talayco79c6c4d2010-06-08 14:01:53 -070078 if table_idx == -1: # Accumulate for all tables
79 active_flows = 0
80 for stats in response.stats:
81 active_flows += stats.active_count
82 else: # Table index to use specified in config
83 active_flows = response.stats[table_idx].active_count
84 if active_flows != flow_count:
85 break
86
Rich Lane9a003812012-10-04 17:17:59 -070087 logging.error("RESULT: " + str(flow_count) + " flows inserted")
88 logging.error("RESULT: " + str(active_flows) + " flows reported")
Dan Talayco79c6c4d2010-06-08 14:01:53 -070089
Shudong Zhoud71c4a72012-11-18 14:37:43 -080090 # clean up and wait a bit in case the table is really big
91 rv = delete_all_flows(obj.controller)
92 time.sleep(flow_count / 100)
93
94
Dan Talayco79c6c4d2010-06-08 14:01:53 -070095
Rich Laneb90a1c42012-10-05 09:16:05 -070096class FillTableExact(base_tests.SimpleProtocol):
Dan Talayco79c6c4d2010-06-08 14:01:53 -070097 """
Dan Talayco8f91a5b2010-07-20 14:07:21 -070098 Fill the flow table with exact matches; can take a while
Dan Talayco79c6c4d2010-06-08 14:01:53 -070099
100 Fill table until no more flows can be added. Report result.
101 Increment the source IP address. Assume the flow table will
102 fill in less than 4 billion inserts
103
104 To check the number of flows in the tables is expensive, so
105 it's only done periodically. This is controlled by the
106 count_check variable.
107
108 A switch may have multiple tables. The default behaviour
109 is to count all the flows in all the tables. By setting
110 the parameter "caps_table_idx" in the configuration array,
111 you can control which table to check.
112 """
Rich Laned1d9c282012-10-04 22:07:10 -0700113
114 priority = -1
115
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700116 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700117 logging.info("Running " + str(self))
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700118 flow_caps_common(self)
119
Rich Laneb90a1c42012-10-05 09:16:05 -0700120class FillTableWC(base_tests.SimpleProtocol):
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700121 """
122 Fill the flow table with wildcard matches
123
124 Fill table using wildcard entries until no more flows can be
125 added. Report result.
126 Increment the source IP address. Assume the flow table will
127 fill in less than 4 billion inserts
128
129 To check the number of flows in the tables is expensive, so
130 it's only done periodically. This is controlled by the
131 count_check variable.
132
133 A switch may have multiple tables. The default behaviour
134 is to count all the flows in all the tables. By setting
135 the parameter "caps_table_idx" in the configuration array,
136 you can control which table to check.
137
138 """
Rich Laned1d9c282012-10-04 22:07:10 -0700139
140 priority = -1
141
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700142 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700143 logging.info("Running " + str(self))
Dan Talayco79c6c4d2010-06-08 14:01:53 -0700144 flow_caps_common(self, is_exact=False)