blob: 6c8bda45e99724d289d0f403d2a9361d3ecf5209 [file] [log] [blame]
Dan Talayco942f5302012-04-12 22:32:34 -07001"""
2Prototype test cases related to operation under load
3
4It is recommended that these definitions be kept in their own
5namespace as different groups of tests will likely define
6similar identifiers.
7
Rich Lane477f4812012-10-04 22:49:00 -07008The switch is actively attempting to contact the controller at the address
9indicated in config.
Dan Talayco942f5302012-04-12 22:32:34 -070010
11In general these test cases make some assumption about the external
12configuration of the switch under test. For now, the assumption is
13that the first two OF ports are connected by a loopback cable.
14"""
15
16import copy
Rich Laned9ef7c32012-12-31 11:00:30 -080017import random
Dan Talayco942f5302012-04-12 22:32:34 -070018import logging
Dan Talayco942f5302012-04-12 22:32:34 -070019import unittest
20
Rich Lane477f4812012-10-04 22:49:00 -070021from oftest import config
Dan Talayco942f5302012-04-12 22:32:34 -070022import oftest.controller as controller
23import oftest.cstruct as ofp
24import oftest.message as message
25import oftest.dataplane as dataplane
26import oftest.action as action
27import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070028import oftest.base_tests as base_tests
Dan Talayco942f5302012-04-12 22:32:34 -070029import time
30
Rich Laneda3b5ad2012-10-03 09:05:32 -070031from oftest.testutils import *
Dan Talayco942f5302012-04-12 22:32:34 -070032
Rich Laneb90a1c42012-10-05 09:16:05 -070033class LoadBarrier(base_tests.SimpleProtocol):
Dan Talayco942f5302012-04-12 22:32:34 -070034 """
35 Test barrier under load with loopback
36
37 This test assumes there is a pair of ports on the switch with
38 a loopback cable connected and that spanning tree is disabled.
39 A flow is installed to cause a storm of packet-in messages
40 when a packet is sent to the loopbacked interface. After causing
41 this storm, a barrier request is sent.
42
43 The test succeeds if the barrier response is received. Otherwise
44 the test fails.
45 """
Rich Laned1d9c282012-10-04 22:07:10 -070046
47 priority = -1
48
Dan Talayco942f5302012-04-12 22:32:34 -070049 def runTest(self):
50 # Set up flow to send from port 1 to port 2 and copy to CPU
51 # Test parameter gives LB port base (assumes consecutive)
Rich Lane2014f9b2012-10-05 15:29:40 -070052 lb_port = test_param_get('lb_port', default=1)
53 barrier_count = test_param_get('barrier_count',
Dan Talayco942f5302012-04-12 22:32:34 -070054 default=10)
55
56 # Set controller to filter packet ins
57 self.controller.filter_packet_in = True
58 self.controller.pkt_in_filter_limit = 10
59
60 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -070061 match = packet_to_flow_match(self, pkt)
Dan Talayco942f5302012-04-12 22:32:34 -070062 match.wildcards &= ~ofp.OFPFW_IN_PORT
63 match.in_port = lb_port
64 act = action.action_output()
65 act.port = lb_port + 1
66
67 request = message.flow_mod()
68 request.match = match
69 request.hard_timeout = 2 * barrier_count
70
71 request.buffer_id = 0xffffffff
72 self.assertTrue(request.actions.add(act), "Could not add action")
73
74 act = action.action_output()
75 act.port = ofp.OFPP_CONTROLLER
76 self.assertTrue(request.actions.add(act), "Could not add action")
77
78 rv = self.controller.message_send(request)
79 self.assertTrue(rv != -1, "Error installing flow mod")
80 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
81
82 # Create packet out and send to port lb_port + 1
83 msg = message.packet_out()
Rich Laneafcf4672012-11-14 13:19:27 -080084 msg.in_port = lb_port
Dan Talayco942f5302012-04-12 22:32:34 -070085 msg.data = str(pkt)
86 act = action.action_output()
87 act.port = lb_port + 1
88 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
Rich Lane9a003812012-10-04 17:17:59 -070089 logging.info("Sleeping before starting storm")
Dan Talayco942f5302012-04-12 22:32:34 -070090 time.sleep(1) # Root causing issue with fast disconnects
Rich Lane9a003812012-10-04 17:17:59 -070091 logging.info("Sending packet out to %d" % (lb_port + 1))
Dan Talayco942f5302012-04-12 22:32:34 -070092 rv = self.controller.message_send(msg)
93 self.assertTrue(rv == 0, "Error sending out message")
94
95 for idx in range(0, barrier_count):
96 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
97 # To do: Add some interesting functionality here
Rich Lane9a003812012-10-04 17:17:59 -070098 logging.info("Barrier %d completed" % idx)
Dan Talayco942f5302012-04-12 22:32:34 -070099
100 # Clear the flow table when done
Rich Lane9a003812012-10-04 17:17:59 -0700101 logging.debug("Deleting all flows from switch")
102 rc = delete_all_flows(self.controller)
Dan Talayco942f5302012-04-12 22:32:34 -0700103 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talaycod0832852012-10-10 09:49:53 -0700104
105class PacketInLoad(base_tests.SimpleDataPlane):
106 """
107 Generate lots of packet-in messages
108
109 Test packet-in function by sending lots of packets to the dataplane.
110 This test tracks the number of pkt-ins received but does not enforce
111 any requirements about the number received.
112 """
113 def runTest(self):
114 # Construct packet to send to dataplane
115 # Send packet to dataplane, once to each port
116 # Poll controller with expect message type packet in
117
118 rc = delete_all_flows(self.controller)
119 self.assertEqual(rc, 0, "Failed to delete all flows")
120 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
121 out_count = 0
122 in_count = 0
123
124 of_ports = config["port_map"].keys()
125 for of_port in of_ports:
126 for pkt, pt in [
127 (simple_tcp_packet(), "simple TCP packet"),
128 (simple_tcp_packet(dl_vlan_enable=True,pktlen=108),
129 "simple tagged TCP packet"),
130 (simple_eth_packet(), "simple Ethernet packet"),
131 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
132
133 logging.info("PKT IN test with %s, port %s" % (pt, of_port))
134 for count in range(100):
135 out_count += 1
136 self.dataplane.send(of_port, str(pkt))
137 time.sleep(2)
138 while True:
139 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,
140 timeout=0)
141 if not response:
142 break
143 in_count += 1
144 logging.info("PacketInLoad Sent %d. Got %d." % (out_count, in_count))
145
146
147
148class PacketOutLoad(base_tests.SimpleDataPlane):
149 """
150 Generate lots of packet-out messages
151
152 Test packet-out function by sending lots of packet-out msgs
153 to the switch. This test tracks the number of packets received in
154 the dataplane, but does not enforce any requirements about the
155 number received.
156 """
157 def runTest(self):
158 # Construct packet to send to dataplane
159 # Send packet to dataplane
160 # Poll controller with expect message type packet in
161
162 rc = delete_all_flows(self.controller)
163 self.assertEqual(rc, 0, "Failed to delete all flows")
164
165 # These will get put into function
166 of_ports = config["port_map"].keys()
167 of_ports.sort()
168 out_count = 0
169 in_count = 0
170 xid = 100
171 for dp_port in of_ports:
172 for outpkt, opt in [
173 (simple_tcp_packet(), "simple TCP packet"),
174 (simple_eth_packet(), "simple Ethernet packet"),
175 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
176
177 logging.info("PKT OUT test with %s, port %s" % (opt, dp_port))
178 msg = message.packet_out()
Rich Laneafcf4672012-11-14 13:19:27 -0800179 msg.in_port = ofp.OFPP_NONE
Dan Talaycod0832852012-10-10 09:49:53 -0700180 msg.data = str(outpkt)
181 act = action.action_output()
182 act.port = dp_port
183 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
184
185 logging.info("PacketOutLoad to: " + str(dp_port))
186 for count in range(100):
187 msg.xid = xid
188 xid += 1
189 rv = self.controller.message_send(msg)
190 self.assertTrue(rv == 0, "Error sending out message")
191 out_count += 1
192
193 exp_pkt_arg = None
194 exp_port = None
195 time.sleep(2)
196 while True:
197 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=0)
198 if pkt is None:
199 break
200 in_count += 1
201 logging.info("PacketOutLoad Sent %d. Got %d." % (out_count, in_count))
Ed Swierke6fca642012-11-30 12:00:54 -0800202
203class FlowModLoad(base_tests.SimpleProtocol):
204
205 def checkBarrier(self):
206 msg, pkt = self.controller.transact(message.barrier_request(), timeout=60)
207 self.assertNotEqual(msg, None, "Barrier failed")
208 while self.controller.packets:
209 msg = self.controller.packets.pop(0)[0]
210 self.assertNotEqual(msg.header.type, message.OFPT_ERROR,
211 "Error received")
212
213 def runTest(self):
214 msg, pkt = self.controller.transact(message.table_stats_request())
Rich Lane30ca70c2012-12-31 16:53:55 -0800215
216 # Some switches report an extremely high max_entries that would cause
217 # us to run out of memory attempting to create all the flow-mods.
218 num_flows = min(msg.stats[0].max_entries, 32678)
219
220 logging.info("Creating %d flow-mods messages", num_flows)
Ed Swierke6fca642012-11-30 12:00:54 -0800221
222 requests = []
223 for i in range(num_flows):
224 match = ofp.ofp_match()
225 match.wildcards = ofp.OFPFW_ALL & ~ofp.OFPFW_DL_VLAN & ~ofp.OFPFW_DL_DST
226 match.dl_vlan = ofp.OFP_VLAN_NONE
227 match.dl_dst = [0, 1, 2, 3, i / 256, i % 256]
228 act = action.action_output()
229 act.port = ofp.OFPP_CONTROLLER
230 request = message.flow_mod()
231 request.command = ofp.OFPFC_ADD
232 request.buffer_id = 0xffffffff
233 request.priority = num_flows - i
234 request.out_port = ofp.OFPP_NONE
235 request.match = match
236 request.actions.add(act)
237 requests.append(request)
238
Rich Lane82c35e82012-12-31 10:59:36 -0800239 for i in range(3):
Ed Swierke6fca642012-11-30 12:00:54 -0800240 logging.info("Iteration %d: delete all flows" % i)
241 self.assertEqual(delete_all_flows(self.controller), 0,
242 "Failed to delete all flows")
243 self.checkBarrier()
244
245 logging.info("Iteration %d: add %s flows" % (i, num_flows))
Rich Laned9ef7c32012-12-31 11:00:30 -0800246 random.shuffle(requests)
Ed Swierke6fca642012-11-30 12:00:54 -0800247 for request in requests:
248 self.assertNotEqual(self.controller.message_send(request), -1,
249 "Error installing flow mod")
250 self.checkBarrier()