blob: 4b3c8e16bfdd78e7d4a870084ce28f21d37c6bfa [file] [log] [blame]
Dan Talayco89d57342010-06-07 16:24:59 -07001"""
2Flow stats test case.
3Similar to Flow stats test case in the perl test harness.
4
5"""
6
7import logging
8
9import unittest
10import random
11
Rich Lane477f4812012-10-04 22:49:00 -070012from oftest import config
Dan Talayco89d57342010-06-07 16:24:59 -070013import oftest.controller as controller
14import oftest.cstruct as ofp
15import oftest.message as message
16import oftest.dataplane as dataplane
17import oftest.action as action
18import oftest.parse as parse
19import basic
20
Rich Laneda3b5ad2012-10-03 09:05:32 -070021from oftest.testutils import *
Dan Talayco89d57342010-06-07 16:24:59 -070022from time import sleep
23
Ken Chiang620bdcc2012-03-23 12:52:07 -070024# TODO: ovs has problems with VLAN id?
25WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070026 # (ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP),
Ken Chiang620bdcc2012-03-23 12:52:07 -070027 ofp.OFPFW_DL_SRC,
28 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070029 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
30 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
31 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
32 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Ken Chiang620bdcc2012-03-23 12:52:07 -070033 ofp.OFPFW_TP_SRC,
34 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070035 ofp.OFPFW_NW_SRC_MASK,
36 ofp.OFPFW_NW_DST_MASK,
Ken Chiang620bdcc2012-03-23 12:52:07 -070037 ofp.OFPFW_DL_VLAN_PCP,
38 ofp.OFPFW_NW_TOS]
39
Ken Chiangaa5bc062012-03-31 14:03:28 -070040def sendPacket(obj, pkt, ingress_port, egress_port, test_timeout):
41
Rich Lane9a003812012-10-04 17:17:59 -070042 logging.info("Sending packet to dp port " + str(ingress_port) +
Ken Chiangaa5bc062012-03-31 14:03:28 -070043 ", expecting output on " + str(egress_port))
44 obj.dataplane.send(ingress_port, str(pkt))
45
46 exp_pkt_arg = None
47 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -070048 if config["relax"]:
Ken Chiangaa5bc062012-03-31 14:03:28 -070049 exp_pkt_arg = pkt
50 exp_port = egress_port
51
Rich Lanec8aaa3e2012-07-26 19:28:02 -070052 (rcv_port, rcv_pkt, pkt_time) = obj.dataplane.poll(port_number=exp_port,
Ken Chiangaa5bc062012-03-31 14:03:28 -070053 exp_pkt=exp_pkt_arg)
54 obj.assertTrue(rcv_pkt is not None,
55 "Packet not received on port " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -070056 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Ken Chiangaa5bc062012-03-31 14:03:28 -070057 str(rcv_port))
58 obj.assertEqual(rcv_port, egress_port,
59 "Packet received on port " + str(rcv_port) +
60 ", expected port " + str(egress_port))
61 obj.assertEqual(str(pkt), str(rcv_pkt),
62 'Response packet does not match send packet')
63
Ken Chiang620bdcc2012-03-23 12:52:07 -070064class SingleFlowStats(basic.SimpleDataPlane):
Dan Talayco89d57342010-06-07 16:24:59 -070065 """
66 Verify flow stats are properly retrieved.
67
68 Generate a packet
Ken Chiang620bdcc2012-03-23 12:52:07 -070069 Generate and install a matching flow
70 Send the packet
71 Send a flow stats request to match the flow and retrieve stats
72 Verify that the packet counter has incremented
Dan Talayco89d57342010-06-07 16:24:59 -070073 """
Ken Chiang620bdcc2012-03-23 12:52:07 -070074
75 def verifyStats(self, match, out_port, test_timeout, packet_count):
76 stat_req = message.flow_stats_request()
77 stat_req.match = match
78 stat_req.table_id = 0xff
79 stat_req.out_port = out_port
80
81 all_packets_received = 0
82 for i in range(0,test_timeout):
Rich Lane9a003812012-10-04 17:17:59 -070083 logging.info("Sending stats request")
Ken Chiangfb593e72012-03-28 17:19:13 -070084 response, pkt = self.controller.transact(stat_req,
85 timeout=test_timeout)
86 self.assertTrue(response is not None,
87 "No response to stats request")
88 self.assertTrue(len(response.stats) == 1,
89 "Did not receive flow stats reply")
Ken Chiang620bdcc2012-03-23 12:52:07 -070090 for obj in response.stats:
91 # TODO: pad1 and pad2 fields may be nonzero, is this a bug?
92 # for now, just clear them so the assert is simpler
93 #obj.match.pad1 = 0
94 #obj.match.pad2 = [0, 0]
95 #self.assertEqual(match, obj.match,
96 # "Matches do not match")
Rich Lane9a003812012-10-04 17:17:59 -070097 logging.info("Received " + str(obj.packet_count) + " packets")
Ken Chiang620bdcc2012-03-23 12:52:07 -070098 if obj.packet_count == packet_count:
99 all_packets_received = 1
100
101 if all_packets_received:
102 break
103 sleep(1)
104
105 self.assertTrue(all_packets_received,
106 "Packet count does not match number sent")
107
Dan Talayco89d57342010-06-07 16:24:59 -0700108 def runTest(self):
Ken Chiang620bdcc2012-03-23 12:52:07 -0700109 # TODO: set from command-line parameter
110 test_timeout = 60
111
Rich Lane477f4812012-10-04 22:49:00 -0700112 of_ports = config["port_map"].keys()
Dan Talayco89d57342010-06-07 16:24:59 -0700113 of_ports.sort()
114 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
115
Rich Lane9a003812012-10-04 17:17:59 -0700116 rc = delete_all_flows(self.controller)
Dan Talayco89d57342010-06-07 16:24:59 -0700117 self.assertEqual(rc, 0, "Failed to delete all flows")
118
Ken Chiang620bdcc2012-03-23 12:52:07 -0700119 # build packet
Dan Talayco89d57342010-06-07 16:24:59 -0700120 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700121 match = packet_to_flow_match(self, pkt)
Dan Talayco89d57342010-06-07 16:24:59 -0700122 match.wildcards &= ~ofp.OFPFW_IN_PORT
123 self.assertTrue(match is not None,
124 "Could not generate flow match from pkt")
125 act = action.action_output()
126
Ken Chiang620bdcc2012-03-23 12:52:07 -0700127 # build flow
Dan Talayco39bf6912010-07-08 14:17:52 -0700128 ingress_port = of_ports[0];
129 egress_port = of_ports[1];
Rich Lane9a003812012-10-04 17:17:59 -0700130 logging.info("Ingress " + str(ingress_port) +
Dan Talayco89d57342010-06-07 16:24:59 -0700131 " to egress " + str(egress_port))
Ken Chiang620bdcc2012-03-23 12:52:07 -0700132 match.in_port = ingress_port
133 flow_mod_msg = message.flow_mod()
134 flow_mod_msg.match = match
135 flow_mod_msg.cookie = random.randint(0,9007199254740992)
136 flow_mod_msg.buffer_id = 0xffffffff
137 flow_mod_msg.idle_timeout = 0
138 flow_mod_msg.hard_timeout = 0
139 act.port = egress_port
140 self.assertTrue(flow_mod_msg.actions.add(act), "Could not add action")
141
142 # send flow
Rich Lane9a003812012-10-04 17:17:59 -0700143 logging.info("Inserting flow")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700144 rv = self.controller.message_send(flow_mod_msg)
145 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700146 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700147
148 # no packets sent, so zero packet count
149 self.verifyStats(match, ofp.OFPP_NONE, test_timeout, 0)
150
151 # send packet N times
152 num_sends = random.randint(10,20)
Rich Lane9a003812012-10-04 17:17:59 -0700153 logging.info("Sending " + str(num_sends) + " test packets")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700154 for i in range(0,num_sends):
Ken Chiangaa5bc062012-03-31 14:03:28 -0700155 sendPacket(self, pkt, ingress_port, egress_port,
156 test_timeout)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700157
158 self.verifyStats(match, ofp.OFPP_NONE, test_timeout, num_sends)
159 self.verifyStats(match, egress_port, test_timeout, num_sends)
160 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -0700161 match.wildcards = required_wildcards(self) | wc
Ken Chiang620bdcc2012-03-23 12:52:07 -0700162 self.verifyStats(match, egress_port, test_timeout, num_sends)
163
164
165class TwoFlowStats(basic.SimpleDataPlane):
166 """
167 Verify flow stats are properly retrieved.
168
169 Generate two packets and install two matching flows
170 Send some number of packets
171 Send a flow stats request to match the flows and retrieve stats
172 Verify that the packet counter has incremented
173
174 TODO: add a third flow, and then configure the match to exclude
175 that flow?
176 """
177
178 def buildFlowModMsg(self, pkt, ingress_port, egress_port):
Ed Swierk99a74de2012-08-22 06:40:54 -0700179 match = packet_to_flow_match(self, pkt)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700180 match.wildcards &= ~ofp.OFPFW_IN_PORT
181 self.assertTrue(match is not None,
182 "Could not generate flow match from pkt")
Dan Talayco89d57342010-06-07 16:24:59 -0700183 match.in_port = ingress_port
184
185 flow_mod_msg = message.flow_mod()
186 flow_mod_msg.match = match
187 flow_mod_msg.cookie = random.randint(0,9007199254740992)
188 flow_mod_msg.buffer_id = 0xffffffff
Ken Chiang620bdcc2012-03-23 12:52:07 -0700189 flow_mod_msg.idle_timeout = 0
190 flow_mod_msg.hard_timeout = 0
191 act = action.action_output()
Dan Talayco89d57342010-06-07 16:24:59 -0700192 act.port = egress_port
193 self.assertTrue(flow_mod_msg.actions.add(act), "Could not add action")
Dan Talayco89d57342010-06-07 16:24:59 -0700194
Rich Lane9a003812012-10-04 17:17:59 -0700195 logging.info("Ingress " + str(ingress_port) +
Ken Chiang620bdcc2012-03-23 12:52:07 -0700196 " to egress " + str(egress_port))
Dan Talayco89d57342010-06-07 16:24:59 -0700197
Ken Chiang620bdcc2012-03-23 12:52:07 -0700198 return flow_mod_msg
Dan Talayco89d57342010-06-07 16:24:59 -0700199
Ken Chiangaa5bc062012-03-31 14:03:28 -0700200 def sumStatsReplyCounts(self, response):
201 total_packets = 0
202 for obj in response.stats:
203 # TODO: pad1 and pad2 fields may be nonzero, is this a bug?
204 # for now, just clear them so the assert is simpler
205 #obj.match.pad1 = 0
206 #obj.match.pad2 = [0, 0]
207 #self.assertEqual(match, obj.match,
208 # "Matches do not match")
Rich Lane9a003812012-10-04 17:17:59 -0700209 logging.info("Received " + str(obj.packet_count)
Ken Chiangaa5bc062012-03-31 14:03:28 -0700210 + " packets")
211 total_packets += obj.packet_count
212 return total_packets
Ken Chiang620bdcc2012-03-23 12:52:07 -0700213
214 def verifyStats(self, match, out_port, test_timeout, packet_count):
215 stat_req = message.flow_stats_request()
216 stat_req.match = match
217 stat_req.table_id = 0xff
218 stat_req.out_port = out_port
219
220 all_packets_received = 0
221 for i in range(0,test_timeout):
Rich Lane9a003812012-10-04 17:17:59 -0700222 logging.info("Sending stats request")
Ken Chiangaa5bc062012-03-31 14:03:28 -0700223 # TODO: move REPLY_MORE handling to controller.transact?
Ken Chiangfb593e72012-03-28 17:19:13 -0700224 response, pkt = self.controller.transact(stat_req,
225 timeout=test_timeout)
226 self.assertTrue(response is not None,
227 "No response to stats request")
Ken Chiangaa5bc062012-03-31 14:03:28 -0700228 total_packets = self.sumStatsReplyCounts(response)
229
230 while response.flags == ofp.OFPSF_REPLY_MORE:
231 response, pkt = self.controller.poll(exp_msg=
232 ofp.OFPT_STATS_REPLY,
233 timeout=test_timeout)
234 total_packets += self.sumStatsReplyCounts(response)
235
Ken Chiang620bdcc2012-03-23 12:52:07 -0700236 if total_packets == packet_count:
237 all_packets_received = 1
238 break
239 sleep(1)
240
241 self.assertTrue(all_packets_received,
Ken Chiangaa5bc062012-03-31 14:03:28 -0700242 "Total stats packet count " + str(total_packets) +
243 " does not match number sent " + str(packet_count))
Ken Chiang620bdcc2012-03-23 12:52:07 -0700244
245 def runTest(self):
Ken Chiang620bdcc2012-03-23 12:52:07 -0700246 # TODO: set from command-line parameter
247 test_timeout = 60
248
Rich Lane477f4812012-10-04 22:49:00 -0700249 of_ports = config["port_map"].keys()
Ken Chiang620bdcc2012-03-23 12:52:07 -0700250 of_ports.sort()
251 self.assertTrue(len(of_ports) >= 3, "Not enough ports for test")
252 ingress_port = of_ports[0];
253 egress_port1 = of_ports[1];
254 egress_port2 = of_ports[2];
255
Rich Lane9a003812012-10-04 17:17:59 -0700256 rc = delete_all_flows(self.controller)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700257 self.assertEqual(rc, 0, "Failed to delete all flows")
258
259 pkt1 = simple_tcp_packet()
260 flow_mod_msg1 = self.buildFlowModMsg(pkt1, ingress_port, egress_port1)
261
262 pkt2 = simple_tcp_packet(dl_src='0:7:7:7:7:7')
263 flow_mod_msg2 = self.buildFlowModMsg(pkt2, ingress_port, egress_port2)
264
Rich Lane9a003812012-10-04 17:17:59 -0700265 logging.info("Inserting flow1")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700266 rv = self.controller.message_send(flow_mod_msg1)
267 self.assertTrue(rv != -1, "Error installing flow mod")
Rich Lane9a003812012-10-04 17:17:59 -0700268 logging.info("Inserting flow2")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700269 rv = self.controller.message_send(flow_mod_msg2)
270 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700271 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco89d57342010-06-07 16:24:59 -0700272
Ken Chiang620bdcc2012-03-23 12:52:07 -0700273 num_pkt1s = random.randint(10,30)
Rich Lane9a003812012-10-04 17:17:59 -0700274 logging.info("Sending " + str(num_pkt1s) + " pkt1s")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700275 num_pkt2s = random.randint(10,30)
Rich Lane9a003812012-10-04 17:17:59 -0700276 logging.info("Sending " + str(num_pkt2s) + " pkt2s")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700277 for i in range(0,num_pkt1s):
Ken Chiangaa5bc062012-03-31 14:03:28 -0700278 sendPacket(self, pkt1, ingress_port, egress_port1, test_timeout)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700279 for i in range(0,num_pkt2s):
Ken Chiangaa5bc062012-03-31 14:03:28 -0700280 sendPacket(self, pkt2, ingress_port, egress_port2, test_timeout)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700281
Ed Swierk99a74de2012-08-22 06:40:54 -0700282 match1 = packet_to_flow_match(self, pkt1)
Rich Lane9a003812012-10-04 17:17:59 -0700283 logging.info("Verifying flow1's " + str(num_pkt1s) + " packets")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700284 self.verifyStats(match1, ofp.OFPP_NONE, test_timeout, num_pkt1s)
Ed Swierk99a74de2012-08-22 06:40:54 -0700285 match2 = packet_to_flow_match(self, pkt2)
Rich Lane9a003812012-10-04 17:17:59 -0700286 logging.info("Verifying flow2's " + str(num_pkt2s) + " packets")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700287 self.verifyStats(match2, ofp.OFPP_NONE, test_timeout, num_pkt2s)
288 match1.wildcards |= ofp.OFPFW_DL_SRC
Rich Lane9a003812012-10-04 17:17:59 -0700289 logging.info("Verifying combined " + str(num_pkt1s+num_pkt2s) + " packets")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700290 self.verifyStats(match1, ofp.OFPP_NONE, test_timeout,
291 num_pkt1s+num_pkt2s)
292 # TODO: sweep through the wildcards to verify matching?
293
294
295class AggregateStats(basic.SimpleDataPlane):
296 """
297 Verify aggregate flow stats are properly retrieved.
298
299 Generate two packets
300 Generate and install two matching flows
301 Send an aggregate stats request
302 Verify that aggregate stats are correct
303 Also verify out_port filtering
304 """
305
306 def buildFlowModMsg(self, pkt, ingress_port, egress_port):
Ed Swierk99a74de2012-08-22 06:40:54 -0700307 match = packet_to_flow_match(self, pkt)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700308 match.wildcards &= ~ofp.OFPFW_IN_PORT
309 self.assertTrue(match is not None,
310 "Could not generate flow match from pkt")
311 match.in_port = ingress_port
312
313 flow_mod_msg = message.flow_mod()
314 flow_mod_msg.match = match
315 flow_mod_msg.cookie = random.randint(0,9007199254740992)
316 flow_mod_msg.buffer_id = 0xffffffff
317 flow_mod_msg.idle_timeout = 0
318 flow_mod_msg.hard_timeout = 0
319 act = action.action_output()
320 act.port = egress_port
321 self.assertTrue(flow_mod_msg.actions.add(act), "Could not add action")
322
Rich Lane9a003812012-10-04 17:17:59 -0700323 logging.info("Ingress " + str(ingress_port) +
Ken Chiang620bdcc2012-03-23 12:52:07 -0700324 " to egress " + str(egress_port))
325
326 return flow_mod_msg
327
Ken Chiang620bdcc2012-03-23 12:52:07 -0700328 def verifyAggFlowStats(self, match, out_port, test_timeout,
329 flow_count, packet_count):
330 stat_req = message.aggregate_stats_request()
331 stat_req.match = match
332 stat_req.table_id = 0xff
333 stat_req.out_port = out_port
334
335 all_packets_received = 0
336 for i in range(0,test_timeout):
Rich Lane9a003812012-10-04 17:17:59 -0700337 logging.info("Sending stats request")
Ken Chiangfb593e72012-03-28 17:19:13 -0700338 response, pkt = self.controller.transact(stat_req,
339 timeout=test_timeout)
340 self.assertTrue(response is not None,
341 "No response to stats request")
Dan Talaycoaff26c82012-03-25 15:06:26 -0700342 self.assertTrue(len(response.stats) == 1,
343 "Did not receive flow stats reply")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700344 for obj in response.stats:
345 self.assertTrue(obj.flow_count == flow_count,
346 "Flow count " + str(obj.flow_count) +
347 " does not match expected " + str(flow_count))
Rich Lane9a003812012-10-04 17:17:59 -0700348 logging.info("Received " + str(obj.packet_count) + " packets")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700349 if obj.packet_count == packet_count:
350 all_packets_received = 1
351
352 if all_packets_received:
353 break
354 sleep(1)
355
356 self.assertTrue(all_packets_received,
357 "Packet count does not match number sent")
358
359 def runTest(self):
Ken Chiang620bdcc2012-03-23 12:52:07 -0700360 # TODO: set from command-line parameter
361 test_timeout = 60
362
Rich Lane477f4812012-10-04 22:49:00 -0700363 of_ports = config["port_map"].keys()
Ken Chiang620bdcc2012-03-23 12:52:07 -0700364 of_ports.sort()
365 self.assertTrue(len(of_ports) >= 3, "Not enough ports for test")
366 ingress_port = of_ports[0];
367 egress_port1 = of_ports[1];
368 egress_port2 = of_ports[2];
369
Rich Lane9a003812012-10-04 17:17:59 -0700370 rc = delete_all_flows(self.controller)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700371 self.assertEqual(rc, 0, "Failed to delete all flows")
372
373 pkt1 = simple_tcp_packet()
374 flow_mod_msg1 = self.buildFlowModMsg(pkt1, ingress_port, egress_port1)
375
376 pkt2 = simple_tcp_packet(dl_src='0:7:7:7:7:7')
377 flow_mod_msg2 = self.buildFlowModMsg(pkt2, ingress_port, egress_port2)
378
Rich Lane9a003812012-10-04 17:17:59 -0700379 logging.info("Inserting flow1")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700380 rv = self.controller.message_send(flow_mod_msg1)
381 self.assertTrue(rv != -1, "Error installing flow mod")
Rich Lane9a003812012-10-04 17:17:59 -0700382 logging.info("Inserting flow2")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700383 rv = self.controller.message_send(flow_mod_msg2)
384 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700385 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700386
387 num_pkt1s = random.randint(10,30)
Rich Lane9a003812012-10-04 17:17:59 -0700388 logging.info("Sending " + str(num_pkt1s) + " pkt1s")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700389 num_pkt2s = random.randint(10,30)
Rich Lane9a003812012-10-04 17:17:59 -0700390 logging.info("Sending " + str(num_pkt2s) + " pkt2s")
Ken Chiang620bdcc2012-03-23 12:52:07 -0700391 for i in range(0,num_pkt1s):
Ken Chiangaa5bc062012-03-31 14:03:28 -0700392 sendPacket(self, pkt1, ingress_port, egress_port1, test_timeout)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700393 for i in range(0,num_pkt2s):
Ken Chiangaa5bc062012-03-31 14:03:28 -0700394 sendPacket(self, pkt2, ingress_port, egress_port2, test_timeout)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700395
396 # loop on flow stats request until timeout
Ed Swierk99a74de2012-08-22 06:40:54 -0700397 match = packet_to_flow_match(self, pkt1)
Ken Chiang620bdcc2012-03-23 12:52:07 -0700398 match.wildcards |= ofp.OFPFW_DL_SRC
399 self.verifyAggFlowStats(match, ofp.OFPP_NONE, test_timeout,
400 2, num_pkt1s+num_pkt2s)
401
402 # out_port filter for egress_port1
403 self.verifyAggFlowStats(match, egress_port1, test_timeout,
404 1, num_pkt1s)
405
406 # out_port filter for egress_port1
407 self.verifyAggFlowStats(match, egress_port2, test_timeout,
408 1, num_pkt2s)