blob: ecd565b46a3806e0c0595ac7699ea4417e3be703 [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 Lane0a4f6372013-01-02 14:40:22 -080033@nonstandard
Rich Laneb90a1c42012-10-05 09:16:05 -070034class LoadBarrier(base_tests.SimpleProtocol):
Dan Talayco942f5302012-04-12 22:32:34 -070035 """
36 Test barrier under load with loopback
37
38 This test assumes there is a pair of ports on the switch with
39 a loopback cable connected and that spanning tree is disabled.
40 A flow is installed to cause a storm of packet-in messages
41 when a packet is sent to the loopbacked interface. After causing
42 this storm, a barrier request is sent.
43
44 The test succeeds if the barrier response is received. Otherwise
45 the test fails.
46 """
Rich Laned1d9c282012-10-04 22:07:10 -070047
Dan Talayco942f5302012-04-12 22:32:34 -070048 def runTest(self):
49 # Set up flow to send from port 1 to port 2 and copy to CPU
50 # Test parameter gives LB port base (assumes consecutive)
Rich Lane2014f9b2012-10-05 15:29:40 -070051 lb_port = test_param_get('lb_port', default=1)
52 barrier_count = test_param_get('barrier_count',
Dan Talayco942f5302012-04-12 22:32:34 -070053 default=10)
54
55 # Set controller to filter packet ins
56 self.controller.filter_packet_in = True
57 self.controller.pkt_in_filter_limit = 10
58
59 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -070060 match = packet_to_flow_match(self, pkt)
Dan Talayco942f5302012-04-12 22:32:34 -070061 match.wildcards &= ~ofp.OFPFW_IN_PORT
62 match.in_port = lb_port
63 act = action.action_output()
64 act.port = lb_port + 1
65
66 request = message.flow_mod()
67 request.match = match
68 request.hard_timeout = 2 * barrier_count
69
70 request.buffer_id = 0xffffffff
71 self.assertTrue(request.actions.add(act), "Could not add action")
72
73 act = action.action_output()
74 act.port = ofp.OFPP_CONTROLLER
75 self.assertTrue(request.actions.add(act), "Could not add action")
76
77 rv = self.controller.message_send(request)
78 self.assertTrue(rv != -1, "Error installing flow mod")
79 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
80
81 # Create packet out and send to port lb_port + 1
82 msg = message.packet_out()
Rich Laneafcf4672012-11-14 13:19:27 -080083 msg.in_port = lb_port
Dan Talayco942f5302012-04-12 22:32:34 -070084 msg.data = str(pkt)
85 act = action.action_output()
86 act.port = lb_port + 1
87 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
Rich Lane9a003812012-10-04 17:17:59 -070088 logging.info("Sleeping before starting storm")
Dan Talayco942f5302012-04-12 22:32:34 -070089 time.sleep(1) # Root causing issue with fast disconnects
Rich Lane9a003812012-10-04 17:17:59 -070090 logging.info("Sending packet out to %d" % (lb_port + 1))
Dan Talayco942f5302012-04-12 22:32:34 -070091 rv = self.controller.message_send(msg)
92 self.assertTrue(rv == 0, "Error sending out message")
93
94 for idx in range(0, barrier_count):
95 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
96 # To do: Add some interesting functionality here
Rich Lane9a003812012-10-04 17:17:59 -070097 logging.info("Barrier %d completed" % idx)
Dan Talayco942f5302012-04-12 22:32:34 -070098
99 # Clear the flow table when done
Rich Lane9a003812012-10-04 17:17:59 -0700100 logging.debug("Deleting all flows from switch")
101 rc = delete_all_flows(self.controller)
Dan Talayco942f5302012-04-12 22:32:34 -0700102 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talaycod0832852012-10-10 09:49:53 -0700103
104class PacketInLoad(base_tests.SimpleDataPlane):
105 """
106 Generate lots of packet-in messages
107
108 Test packet-in function by sending lots of packets to the dataplane.
109 This test tracks the number of pkt-ins received but does not enforce
110 any requirements about the number received.
111 """
112 def runTest(self):
113 # Construct packet to send to dataplane
114 # Send packet to dataplane, once to each port
115 # Poll controller with expect message type packet in
116
117 rc = delete_all_flows(self.controller)
118 self.assertEqual(rc, 0, "Failed to delete all flows")
119 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
120 out_count = 0
121 in_count = 0
122
123 of_ports = config["port_map"].keys()
124 for of_port in of_ports:
125 for pkt, pt in [
126 (simple_tcp_packet(), "simple TCP packet"),
127 (simple_tcp_packet(dl_vlan_enable=True,pktlen=108),
128 "simple tagged TCP packet"),
129 (simple_eth_packet(), "simple Ethernet packet"),
130 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
131
132 logging.info("PKT IN test with %s, port %s" % (pt, of_port))
133 for count in range(100):
134 out_count += 1
135 self.dataplane.send(of_port, str(pkt))
136 time.sleep(2)
137 while True:
138 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,
139 timeout=0)
140 if not response:
141 break
142 in_count += 1
143 logging.info("PacketInLoad Sent %d. Got %d." % (out_count, in_count))
144
145
146
147class PacketOutLoad(base_tests.SimpleDataPlane):
148 """
149 Generate lots of packet-out messages
150
151 Test packet-out function by sending lots of packet-out msgs
152 to the switch. This test tracks the number of packets received in
153 the dataplane, but does not enforce any requirements about the
154 number received.
155 """
156 def runTest(self):
157 # Construct packet to send to dataplane
158 # Send packet to dataplane
159 # Poll controller with expect message type packet in
160
161 rc = delete_all_flows(self.controller)
162 self.assertEqual(rc, 0, "Failed to delete all flows")
163
164 # These will get put into function
165 of_ports = config["port_map"].keys()
166 of_ports.sort()
167 out_count = 0
168 in_count = 0
169 xid = 100
170 for dp_port in of_ports:
171 for outpkt, opt in [
172 (simple_tcp_packet(), "simple TCP packet"),
173 (simple_eth_packet(), "simple Ethernet packet"),
174 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
175
176 logging.info("PKT OUT test with %s, port %s" % (opt, dp_port))
177 msg = message.packet_out()
Rich Laneafcf4672012-11-14 13:19:27 -0800178 msg.in_port = ofp.OFPP_NONE
Dan Talaycod0832852012-10-10 09:49:53 -0700179 msg.data = str(outpkt)
180 act = action.action_output()
181 act.port = dp_port
182 self.assertTrue(msg.actions.add(act), 'Could not add action to msg')
183
184 logging.info("PacketOutLoad to: " + str(dp_port))
185 for count in range(100):
186 msg.xid = xid
187 xid += 1
188 rv = self.controller.message_send(msg)
189 self.assertTrue(rv == 0, "Error sending out message")
190 out_count += 1
191
192 exp_pkt_arg = None
193 exp_port = None
194 time.sleep(2)
195 while True:
196 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=0)
197 if pkt is None:
198 break
199 in_count += 1
200 logging.info("PacketOutLoad Sent %d. Got %d." % (out_count, in_count))
Ed Swierke6fca642012-11-30 12:00:54 -0800201
202class FlowModLoad(base_tests.SimpleProtocol):
203
204 def checkBarrier(self):
205 msg, pkt = self.controller.transact(message.barrier_request(), timeout=60)
206 self.assertNotEqual(msg, None, "Barrier failed")
207 while self.controller.packets:
208 msg = self.controller.packets.pop(0)[0]
209 self.assertNotEqual(msg.header.type, message.OFPT_ERROR,
210 "Error received")
211
212 def runTest(self):
213 msg, pkt = self.controller.transact(message.table_stats_request())
Rich Lane30ca70c2012-12-31 16:53:55 -0800214
215 # Some switches report an extremely high max_entries that would cause
216 # us to run out of memory attempting to create all the flow-mods.
217 num_flows = min(msg.stats[0].max_entries, 32678)
218
219 logging.info("Creating %d flow-mods messages", num_flows)
Ed Swierke6fca642012-11-30 12:00:54 -0800220
221 requests = []
222 for i in range(num_flows):
223 match = ofp.ofp_match()
224 match.wildcards = ofp.OFPFW_ALL & ~ofp.OFPFW_DL_VLAN & ~ofp.OFPFW_DL_DST
225 match.dl_vlan = ofp.OFP_VLAN_NONE
226 match.dl_dst = [0, 1, 2, 3, i / 256, i % 256]
227 act = action.action_output()
228 act.port = ofp.OFPP_CONTROLLER
229 request = message.flow_mod()
230 request.command = ofp.OFPFC_ADD
231 request.buffer_id = 0xffffffff
232 request.priority = num_flows - i
233 request.out_port = ofp.OFPP_NONE
234 request.match = match
235 request.actions.add(act)
236 requests.append(request)
237
Rich Lane82c35e82012-12-31 10:59:36 -0800238 for i in range(3):
Ed Swierke6fca642012-11-30 12:00:54 -0800239 logging.info("Iteration %d: delete all flows" % i)
240 self.assertEqual(delete_all_flows(self.controller), 0,
241 "Failed to delete all flows")
242 self.checkBarrier()
243
244 logging.info("Iteration %d: add %s flows" % (i, num_flows))
Rich Laned9ef7c32012-12-31 11:00:30 -0800245 random.shuffle(requests)
Ed Swierke6fca642012-11-30 12:00:54 -0800246 for request in requests:
247 self.assertNotEqual(self.controller.message_send(request), -1,
248 "Error installing flow mod")
249 self.checkBarrier()