blob: 7f9e0051919f61c1c783daef2fc3ff5f44829280 [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
Rich Laned7b0ffa2013-03-08 15:53:42 -080023import ofp
Dan Talayco942f5302012-04-12 22:32:34 -070024import oftest.dataplane as dataplane
Dan Talayco942f5302012-04-12 22:32:34 -070025import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070026import oftest.base_tests as base_tests
Dan Talayco942f5302012-04-12 22:32:34 -070027import time
28
Rich Laneda3b5ad2012-10-03 09:05:32 -070029from oftest.testutils import *
Dan Talayco942f5302012-04-12 22:32:34 -070030
Rich Lane0a4f6372013-01-02 14:40:22 -080031@nonstandard
Rich Laneb90a1c42012-10-05 09:16:05 -070032class LoadBarrier(base_tests.SimpleProtocol):
Dan Talayco942f5302012-04-12 22:32:34 -070033 """
34 Test barrier under load with loopback
35
36 This test assumes there is a pair of ports on the switch with
37 a loopback cable connected and that spanning tree is disabled.
38 A flow is installed to cause a storm of packet-in messages
39 when a packet is sent to the loopbacked interface. After causing
40 this storm, a barrier request is sent.
41
42 The test succeeds if the barrier response is received. Otherwise
43 the test fails.
44 """
Rich Laned1d9c282012-10-04 22:07:10 -070045
Dan Talayco942f5302012-04-12 22:32:34 -070046 def runTest(self):
47 # Set up flow to send from port 1 to port 2 and copy to CPU
48 # Test parameter gives LB port base (assumes consecutive)
Rich Lane2014f9b2012-10-05 15:29:40 -070049 lb_port = test_param_get('lb_port', default=1)
50 barrier_count = test_param_get('barrier_count',
Dan Talayco942f5302012-04-12 22:32:34 -070051 default=10)
52
53 # Set controller to filter packet ins
54 self.controller.filter_packet_in = True
55 self.controller.pkt_in_filter_limit = 10
56
57 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -070058 match = packet_to_flow_match(self, pkt)
Dan Talayco942f5302012-04-12 22:32:34 -070059 match.wildcards &= ~ofp.OFPFW_IN_PORT
60 match.in_port = lb_port
Rich Lane9d3cc6b2013-03-08 16:33:08 -080061 act = ofp.action.output()
Dan Talayco942f5302012-04-12 22:32:34 -070062 act.port = lb_port + 1
63
Rich Laneba3f0e22013-03-11 16:43:57 -070064 request = ofp.message.flow_add()
Dan Talayco942f5302012-04-12 22:32:34 -070065 request.match = match
66 request.hard_timeout = 2 * barrier_count
67
68 request.buffer_id = 0xffffffff
Rich Lanec495d9e2013-03-08 17:43:36 -080069 request.actions.append(act)
Dan Talayco942f5302012-04-12 22:32:34 -070070
Rich Lane9d3cc6b2013-03-08 16:33:08 -080071 act = ofp.action.output()
Dan Talayco942f5302012-04-12 22:32:34 -070072 act.port = ofp.OFPP_CONTROLLER
Rich Lanec495d9e2013-03-08 17:43:36 -080073 request.actions.append(act)
Dan Talayco942f5302012-04-12 22:32:34 -070074
Rich Lane5c3151c2013-01-03 17:15:41 -080075 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -080076 do_barrier(self.controller)
Dan Talayco942f5302012-04-12 22:32:34 -070077
78 # Create packet out and send to port lb_port + 1
Rich Lane28fa9272013-03-08 16:00:25 -080079 msg = ofp.message.packet_out()
Rich Laneafcf4672012-11-14 13:19:27 -080080 msg.in_port = lb_port
Dan Talayco942f5302012-04-12 22:32:34 -070081 msg.data = str(pkt)
Rich Laneea8c4722013-04-04 15:30:20 -070082 msg.buffer_id = 0xffffffff
Rich Lane9d3cc6b2013-03-08 16:33:08 -080083 act = ofp.action.output()
Dan Talayco942f5302012-04-12 22:32:34 -070084 act.port = lb_port + 1
Rich Lanec495d9e2013-03-08 17:43:36 -080085 msg.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -070086 logging.info("Sleeping before starting storm")
Dan Talayco942f5302012-04-12 22:32:34 -070087 time.sleep(1) # Root causing issue with fast disconnects
Rich Lane9a003812012-10-04 17:17:59 -070088 logging.info("Sending packet out to %d" % (lb_port + 1))
Rich Lane5c3151c2013-01-03 17:15:41 -080089 self.controller.message_send(msg)
Dan Talayco942f5302012-04-12 22:32:34 -070090
91 for idx in range(0, barrier_count):
Rich Lane3a261d52013-01-03 17:45:08 -080092 do_barrier(self.controller)
Dan Talayco942f5302012-04-12 22:32:34 -070093 # To do: Add some interesting functionality here
Rich Lane9a003812012-10-04 17:17:59 -070094 logging.info("Barrier %d completed" % idx)
Dan Talayco942f5302012-04-12 22:32:34 -070095
96 # Clear the flow table when done
Rich Lane9a003812012-10-04 17:17:59 -070097 logging.debug("Deleting all flows from switch")
Rich Lane32bf9482013-01-03 17:26:30 -080098 delete_all_flows(self.controller)
Dan Talaycod0832852012-10-10 09:49:53 -070099
100class PacketInLoad(base_tests.SimpleDataPlane):
101 """
102 Generate lots of packet-in messages
103
104 Test packet-in function by sending lots of packets to the dataplane.
105 This test tracks the number of pkt-ins received but does not enforce
106 any requirements about the number received.
107 """
108 def runTest(self):
109 # Construct packet to send to dataplane
110 # Send packet to dataplane, once to each port
111 # Poll controller with expect message type packet in
112
Rich Lane32bf9482013-01-03 17:26:30 -0800113 delete_all_flows(self.controller)
Rich Lane3a261d52013-01-03 17:45:08 -0800114 do_barrier(self.controller)
Dan Talaycod0832852012-10-10 09:49:53 -0700115 out_count = 0
116 in_count = 0
117
118 of_ports = config["port_map"].keys()
119 for of_port in of_ports:
120 for pkt, pt in [
121 (simple_tcp_packet(), "simple TCP packet"),
122 (simple_tcp_packet(dl_vlan_enable=True,pktlen=108),
123 "simple tagged TCP packet"),
124 (simple_eth_packet(), "simple Ethernet packet"),
125 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
126
127 logging.info("PKT IN test with %s, port %s" % (pt, of_port))
128 for count in range(100):
129 out_count += 1
130 self.dataplane.send(of_port, str(pkt))
Dan Talaycod0832852012-10-10 09:49:53 -0700131 while True:
Ed Swierka9e12ab2013-01-16 07:35:25 -0800132 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Dan Talaycod0832852012-10-10 09:49:53 -0700133 if not response:
134 break
135 in_count += 1
136 logging.info("PacketInLoad Sent %d. Got %d." % (out_count, in_count))
137
138
139
140class PacketOutLoad(base_tests.SimpleDataPlane):
141 """
142 Generate lots of packet-out messages
143
144 Test packet-out function by sending lots of packet-out msgs
145 to the switch. This test tracks the number of packets received in
146 the dataplane, but does not enforce any requirements about the
147 number received.
148 """
149 def runTest(self):
150 # Construct packet to send to dataplane
151 # Send packet to dataplane
152 # Poll controller with expect message type packet in
153
Rich Lane32bf9482013-01-03 17:26:30 -0800154 delete_all_flows(self.controller)
Dan Talaycod0832852012-10-10 09:49:53 -0700155
156 # These will get put into function
157 of_ports = config["port_map"].keys()
158 of_ports.sort()
159 out_count = 0
160 in_count = 0
161 xid = 100
162 for dp_port in of_ports:
163 for outpkt, opt in [
164 (simple_tcp_packet(), "simple TCP packet"),
165 (simple_eth_packet(), "simple Ethernet packet"),
166 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
167
168 logging.info("PKT OUT test with %s, port %s" % (opt, dp_port))
Rich Lane28fa9272013-03-08 16:00:25 -0800169 msg = ofp.message.packet_out()
Rich Laneafcf4672012-11-14 13:19:27 -0800170 msg.in_port = ofp.OFPP_NONE
Dan Talaycod0832852012-10-10 09:49:53 -0700171 msg.data = str(outpkt)
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800172 act = ofp.action.output()
Dan Talaycod0832852012-10-10 09:49:53 -0700173 act.port = dp_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800174 msg.actions.append(act)
Rich Laneea8c4722013-04-04 15:30:20 -0700175 msg.buffer_id = 0xffffffff
Dan Talaycod0832852012-10-10 09:49:53 -0700176
177 logging.info("PacketOutLoad to: " + str(dp_port))
178 for count in range(100):
179 msg.xid = xid
180 xid += 1
Rich Lane5c3151c2013-01-03 17:15:41 -0800181 self.controller.message_send(msg)
Dan Talaycod0832852012-10-10 09:49:53 -0700182 out_count += 1
183
184 exp_pkt_arg = None
185 exp_port = None
Dan Talaycod0832852012-10-10 09:49:53 -0700186 while True:
Ed Swierka9e12ab2013-01-16 07:35:25 -0800187 (of_port, pkt, pkt_time) = self.dataplane.poll()
Dan Talaycod0832852012-10-10 09:49:53 -0700188 if pkt is None:
189 break
190 in_count += 1
191 logging.info("PacketOutLoad Sent %d. Got %d." % (out_count, in_count))
Ed Swierke6fca642012-11-30 12:00:54 -0800192
193class FlowModLoad(base_tests.SimpleProtocol):
194
195 def checkBarrier(self):
Rich Lane28fa9272013-03-08 16:00:25 -0800196 msg, pkt = self.controller.transact(ofp.message.barrier_request(), timeout=60)
Ed Swierke6fca642012-11-30 12:00:54 -0800197 self.assertNotEqual(msg, None, "Barrier failed")
198 while self.controller.packets:
199 msg = self.controller.packets.pop(0)[0]
Rich Lanef9f6b512013-03-11 22:35:28 -0700200 self.assertNotEqual(msg.type, ofp.OFPT_ERROR, "Error received")
Ed Swierke6fca642012-11-30 12:00:54 -0800201
202 def runTest(self):
Rich Lane28fa9272013-03-08 16:00:25 -0800203 msg, pkt = self.controller.transact(ofp.message.table_stats_request())
Rich Lane30ca70c2012-12-31 16:53:55 -0800204
205 # Some switches report an extremely high max_entries that would cause
206 # us to run out of memory attempting to create all the flow-mods.
Rich Lane5fd6faf2013-03-11 13:30:20 -0700207 num_flows = min(msg.entries[0].max_entries, 32678)
Rich Lane30ca70c2012-12-31 16:53:55 -0800208
209 logging.info("Creating %d flow-mods messages", num_flows)
Ed Swierke6fca642012-11-30 12:00:54 -0800210
211 requests = []
212 for i in range(num_flows):
Rich Lane0237baf2013-03-11 22:34:59 -0700213 match = ofp.match()
Ed Swierke6fca642012-11-30 12:00:54 -0800214 match.wildcards = ofp.OFPFW_ALL & ~ofp.OFPFW_DL_VLAN & ~ofp.OFPFW_DL_DST
Rich Laned0478ff2013-03-11 12:46:58 -0700215 match.vlan_vid = ofp.OFP_VLAN_NONE
216 match.eth_dst = [0, 1, 2, 3, i / 256, i % 256]
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800217 act = ofp.action.output()
Ed Swierke6fca642012-11-30 12:00:54 -0800218 act.port = ofp.OFPP_CONTROLLER
Rich Laneba3f0e22013-03-11 16:43:57 -0700219 request = ofp.message.flow_add()
Ed Swierke6fca642012-11-30 12:00:54 -0800220 request.buffer_id = 0xffffffff
221 request.priority = num_flows - i
222 request.out_port = ofp.OFPP_NONE
223 request.match = match
Rich Lanec495d9e2013-03-08 17:43:36 -0800224 request.actions.append(act)
Ed Swierke6fca642012-11-30 12:00:54 -0800225 requests.append(request)
226
Rich Lane82c35e82012-12-31 10:59:36 -0800227 for i in range(3):
Ed Swierke6fca642012-11-30 12:00:54 -0800228 logging.info("Iteration %d: delete all flows" % i)
Rich Lane32bf9482013-01-03 17:26:30 -0800229 delete_all_flows(self.controller)
Ed Swierke6fca642012-11-30 12:00:54 -0800230 self.checkBarrier()
231
232 logging.info("Iteration %d: add %s flows" % (i, num_flows))
Rich Laned9ef7c32012-12-31 11:00:30 -0800233 random.shuffle(requests)
Ed Swierke6fca642012-11-30 12:00:54 -0800234 for request in requests:
235 self.assertNotEqual(self.controller.message_send(request), -1,
236 "Error installing flow mod")
237 self.checkBarrier()
Rich Lane9c491602013-04-15 16:00:46 -0700238
239class FlowRemovedLoad(base_tests.SimpleDataPlane):
240 """
241 Generate lots of flow-removed messages
242
243 We keep track of the number of flow-removed messages we get but do not
244 assert on it. The goal of this test is just to make sure the controller
245 stays connected.
246 """
247
248 def checkBarrier(self):
249 msg, pkt = self.controller.transact(ofp.message.barrier_request(), timeout=60)
250 self.assertNotEqual(msg, None, "Barrier failed")
251 while self.controller.packets:
252 msg = self.controller.packets.pop(0)[0]
253 self.assertNotEqual(msg.type, ofp.OFPT_ERROR, "Error received")
254
255 def runTest(self):
256 delete_all_flows(self.controller)
257 self.checkBarrier()
258 msg, _ = self.controller.transact(ofp.message.table_stats_request())
259
260 # Some switches report an extremely high max_entries that would cause
261 # us to run out of memory attempting to create all the flow-mods.
262 num_flows = min(msg.entries[0].max_entries, 32678)
263
264 logging.info("Creating %d flow-mods messages", num_flows)
265
266 requests = []
267 for i in range(num_flows):
268 match = ofp.match()
269 match.wildcards = ofp.OFPFW_ALL & ~ofp.OFPFW_DL_VLAN & ~ofp.OFPFW_DL_DST
270 match.vlan_vid = ofp.OFP_VLAN_NONE
271 match.eth_dst = [0, 1, 2, 3, i / 256, i % 256]
272 act = ofp.action.output()
273 act.port = ofp.OFPP_CONTROLLER
274 request = ofp.message.flow_add()
275 request.buffer_id = 0xffffffff
276 request.priority = num_flows - i
277 request.out_port = ofp.OFPP_NONE
278 request.flags = ofp.OFPFF_SEND_FLOW_REM
279 request.match = match
280 request.actions.append(act)
281 requests.append(request)
282
283 logging.info("Adding %d flows", num_flows)
284 random.shuffle(requests)
285 for request in requests:
286 self.controller.message_send(request)
287 self.checkBarrier()
288
289 # Trigger a flood of flow-removed messages
290 delete_all_flows(self.controller)
291
292 count = 0
293 while True:
294 (response, raw) = self.controller.poll(ofp.OFPT_FLOW_REMOVED)
295 if not response:
296 break
297 count += 1
298
299 # Make sure the switch is still connected
300 self.checkBarrier()
301
302 logging.info("FlowRemovedLoad got %d/%d flow_removed messages." % (count, num_flows))