blob: d3d3ca62e26640e097a957f47c042c4df1abd790 [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
Rich Lanee30455b2013-01-03 16:24:44 -080072 request.actions.add(act)
Dan Talayco942f5302012-04-12 22:32:34 -070073
74 act = action.action_output()
75 act.port = ofp.OFPP_CONTROLLER
Rich Lanee30455b2013-01-03 16:24:44 -080076 request.actions.add(act)
Dan Talayco942f5302012-04-12 22:32:34 -070077
Rich Lane5c3151c2013-01-03 17:15:41 -080078 self.controller.message_send(request)
Dan Talayco942f5302012-04-12 22:32:34 -070079 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
Rich Lanee30455b2013-01-03 16:24:44 -080087 msg.actions.add(act)
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))
Rich Lane5c3151c2013-01-03 17:15:41 -080091 self.controller.message_send(msg)
Dan Talayco942f5302012-04-12 22:32:34 -070092
93 for idx in range(0, barrier_count):
94 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
95 # To do: Add some interesting functionality here
Rich Lane9a003812012-10-04 17:17:59 -070096 logging.info("Barrier %d completed" % idx)
Dan Talayco942f5302012-04-12 22:32:34 -070097
98 # Clear the flow table when done
Rich Lane9a003812012-10-04 17:17:59 -070099 logging.debug("Deleting all flows from switch")
100 rc = delete_all_flows(self.controller)
Dan Talayco942f5302012-04-12 22:32:34 -0700101 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talaycod0832852012-10-10 09:49:53 -0700102
103class PacketInLoad(base_tests.SimpleDataPlane):
104 """
105 Generate lots of packet-in messages
106
107 Test packet-in function by sending lots of packets to the dataplane.
108 This test tracks the number of pkt-ins received but does not enforce
109 any requirements about the number received.
110 """
111 def runTest(self):
112 # Construct packet to send to dataplane
113 # Send packet to dataplane, once to each port
114 # Poll controller with expect message type packet in
115
116 rc = delete_all_flows(self.controller)
117 self.assertEqual(rc, 0, "Failed to delete all flows")
118 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
119 out_count = 0
120 in_count = 0
121
122 of_ports = config["port_map"].keys()
123 for of_port in of_ports:
124 for pkt, pt in [
125 (simple_tcp_packet(), "simple TCP packet"),
126 (simple_tcp_packet(dl_vlan_enable=True,pktlen=108),
127 "simple tagged TCP packet"),
128 (simple_eth_packet(), "simple Ethernet packet"),
129 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
130
131 logging.info("PKT IN test with %s, port %s" % (pt, of_port))
132 for count in range(100):
133 out_count += 1
134 self.dataplane.send(of_port, str(pkt))
135 time.sleep(2)
136 while True:
137 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,
138 timeout=0)
139 if not response:
140 break
141 in_count += 1
142 logging.info("PacketInLoad Sent %d. Got %d." % (out_count, in_count))
143
144
145
146class PacketOutLoad(base_tests.SimpleDataPlane):
147 """
148 Generate lots of packet-out messages
149
150 Test packet-out function by sending lots of packet-out msgs
151 to the switch. This test tracks the number of packets received in
152 the dataplane, but does not enforce any requirements about the
153 number received.
154 """
155 def runTest(self):
156 # Construct packet to send to dataplane
157 # Send packet to dataplane
158 # Poll controller with expect message type packet in
159
160 rc = delete_all_flows(self.controller)
161 self.assertEqual(rc, 0, "Failed to delete all flows")
162
163 # These will get put into function
164 of_ports = config["port_map"].keys()
165 of_ports.sort()
166 out_count = 0
167 in_count = 0
168 xid = 100
169 for dp_port in of_ports:
170 for outpkt, opt in [
171 (simple_tcp_packet(), "simple TCP packet"),
172 (simple_eth_packet(), "simple Ethernet packet"),
173 (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
174
175 logging.info("PKT OUT test with %s, port %s" % (opt, dp_port))
176 msg = message.packet_out()
Rich Laneafcf4672012-11-14 13:19:27 -0800177 msg.in_port = ofp.OFPP_NONE
Dan Talaycod0832852012-10-10 09:49:53 -0700178 msg.data = str(outpkt)
179 act = action.action_output()
180 act.port = dp_port
Rich Lanee30455b2013-01-03 16:24:44 -0800181 msg.actions.add(act)
Dan Talaycod0832852012-10-10 09:49:53 -0700182
183 logging.info("PacketOutLoad to: " + str(dp_port))
184 for count in range(100):
185 msg.xid = xid
186 xid += 1
Rich Lane5c3151c2013-01-03 17:15:41 -0800187 self.controller.message_send(msg)
Dan Talaycod0832852012-10-10 09:49:53 -0700188 out_count += 1
189
190 exp_pkt_arg = None
191 exp_port = None
192 time.sleep(2)
193 while True:
194 (of_port, pkt, pkt_time) = self.dataplane.poll(timeout=0)
195 if pkt is None:
196 break
197 in_count += 1
198 logging.info("PacketOutLoad Sent %d. Got %d." % (out_count, in_count))
Ed Swierke6fca642012-11-30 12:00:54 -0800199
200class FlowModLoad(base_tests.SimpleProtocol):
201
202 def checkBarrier(self):
203 msg, pkt = self.controller.transact(message.barrier_request(), timeout=60)
204 self.assertNotEqual(msg, None, "Barrier failed")
205 while self.controller.packets:
206 msg = self.controller.packets.pop(0)[0]
207 self.assertNotEqual(msg.header.type, message.OFPT_ERROR,
208 "Error received")
209
210 def runTest(self):
211 msg, pkt = self.controller.transact(message.table_stats_request())
Rich Lane30ca70c2012-12-31 16:53:55 -0800212
213 # Some switches report an extremely high max_entries that would cause
214 # us to run out of memory attempting to create all the flow-mods.
215 num_flows = min(msg.stats[0].max_entries, 32678)
216
217 logging.info("Creating %d flow-mods messages", num_flows)
Ed Swierke6fca642012-11-30 12:00:54 -0800218
219 requests = []
220 for i in range(num_flows):
221 match = ofp.ofp_match()
222 match.wildcards = ofp.OFPFW_ALL & ~ofp.OFPFW_DL_VLAN & ~ofp.OFPFW_DL_DST
223 match.dl_vlan = ofp.OFP_VLAN_NONE
224 match.dl_dst = [0, 1, 2, 3, i / 256, i % 256]
225 act = action.action_output()
226 act.port = ofp.OFPP_CONTROLLER
227 request = message.flow_mod()
228 request.command = ofp.OFPFC_ADD
229 request.buffer_id = 0xffffffff
230 request.priority = num_flows - i
231 request.out_port = ofp.OFPP_NONE
232 request.match = match
233 request.actions.add(act)
234 requests.append(request)
235
Rich Lane82c35e82012-12-31 10:59:36 -0800236 for i in range(3):
Ed Swierke6fca642012-11-30 12:00:54 -0800237 logging.info("Iteration %d: delete all flows" % i)
238 self.assertEqual(delete_all_flows(self.controller), 0,
239 "Failed to delete all flows")
240 self.checkBarrier()
241
242 logging.info("Iteration %d: add %s flows" % (i, num_flows))
Rich Laned9ef7c32012-12-31 11:00:30 -0800243 random.shuffle(requests)
Ed Swierke6fca642012-11-30 12:00:54 -0800244 for request in requests:
245 self.assertNotEqual(self.controller.message_send(request), -1,
246 "Error installing flow mod")
247 self.checkBarrier()