Consolidate duplicate code.
Support "relax" option when sending and verifying dataplane packets.
Add OFPSF_REPLY_MORE support to TwoFlowStats test,
but this should ultimately be moved to controller.transact().
diff --git a/tests/flow_stats.py b/tests/flow_stats.py
index 91c67a6..e5976c3 100644
--- a/tests/flow_stats.py
+++ b/tests/flow_stats.py
@@ -58,6 +58,31 @@
fs_port_map = config["port_map"]
fs_config = config
+def sendPacket(obj, pkt, ingress_port, egress_port, test_timeout):
+
+ fs_logger.info("Sending packet to dp port " + str(ingress_port) +
+ ", expecting output on " + str(egress_port))
+ obj.dataplane.send(ingress_port, str(pkt))
+
+ exp_pkt_arg = None
+ exp_port = None
+ if fs_config["relax"]:
+ exp_pkt_arg = pkt
+ exp_port = egress_port
+
+ (rcv_port, rcv_pkt, pkt_time) = obj.dataplane.poll(timeout=1,
+ port_number=exp_port,
+ exp_pkt=exp_pkt_arg)
+ obj.assertTrue(rcv_pkt is not None,
+ "Packet not received on port " + str(egress_port))
+ fs_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
+ str(rcv_port))
+ obj.assertEqual(rcv_port, egress_port,
+ "Packet received on port " + str(rcv_port) +
+ ", expected port " + str(egress_port))
+ obj.assertEqual(str(pkt), str(rcv_pkt),
+ 'Response packet does not match send packet')
+
class SingleFlowStats(basic.SimpleDataPlane):
"""
Verify flow stats are properly retrieved.
@@ -151,21 +176,8 @@
num_sends = random.randint(10,20)
fs_logger.info("Sending " + str(num_sends) + " test packets")
for i in range(0,num_sends):
- fs_logger.info("Sending packet to dp port " +
- str(ingress_port))
- self.dataplane.send(ingress_port, str(pkt))
- (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=
- test_timeout)
- self.assertTrue(rcv_pkt is not None, "Did not receive packet")
- fs_logger.debug("Packet len " + str(len(pkt)) + " in on " +
- str(rcv_port))
- self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
- for j in range(0,test_timeout):
- if str(pkt) == str(rcv_pkt):
- break
- sleep(1)
- self.assertTrue(j < test_timeout,
- 'Timeout sending packets for flow stats test')
+ sendPacket(self, pkt, ingress_port, egress_port,
+ test_timeout)
self.verifyStats(match, ofp.OFPP_NONE, test_timeout, num_sends)
self.verifyStats(match, egress_port, test_timeout, num_sends)
@@ -209,22 +221,19 @@
return flow_mod_msg
- def sendPacket(self, pkt, ingress_port, egress_port, test_timeout):
- fs_logger.info("Sending packet to dp port " +
- str(ingress_port))
- self.dataplane.send(ingress_port, str(pkt))
- (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=
- test_timeout)
- self.assertTrue(rcv_pkt is not None, "Did not receive packet")
- fs_logger.debug("Packet len " + str(len(pkt)) + " in on " +
- str(rcv_port))
- self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
- for j in range(0,test_timeout):
- if str(pkt) == str(rcv_pkt):
- break
- sleep(1)
- self.assertTrue(j < test_timeout,
- 'Timeout sending packets for flow stats test')
+ def sumStatsReplyCounts(self, response):
+ total_packets = 0
+ for obj in response.stats:
+ # TODO: pad1 and pad2 fields may be nonzero, is this a bug?
+ # for now, just clear them so the assert is simpler
+ #obj.match.pad1 = 0
+ #obj.match.pad2 = [0, 0]
+ #self.assertEqual(match, obj.match,
+ # "Matches do not match")
+ fs_logger.info("Received " + str(obj.packet_count)
+ + " packets")
+ total_packets += obj.packet_count
+ return total_packets
def verifyStats(self, match, out_port, test_timeout, packet_count):
stat_req = message.flow_stats_request()
@@ -235,29 +244,27 @@
all_packets_received = 0
for i in range(0,test_timeout):
fs_logger.info("Sending stats request")
+ # TODO: move REPLY_MORE handling to controller.transact?
response, pkt = self.controller.transact(stat_req,
timeout=test_timeout)
self.assertTrue(response is not None,
"No response to stats request")
- self.assertTrue(len(response.stats) >= 1,
- "Did not receive flow stats reply")
- total_packets = 0
- for obj in response.stats:
- # TODO: pad1 and pad2 fields may be nonzero, is this a bug?
- # for now, just clear them so the assert is simpler
- #obj.match.pad1 = 0
- #obj.match.pad2 = [0, 0]
- #self.assertEqual(match, obj.match,
- # "Matches do not match")
- fs_logger.info("Received " + str(obj.packet_count) + " packets")
- total_packets += obj.packet_count
+ total_packets = self.sumStatsReplyCounts(response)
+
+ while response.flags == ofp.OFPSF_REPLY_MORE:
+ response, pkt = self.controller.poll(exp_msg=
+ ofp.OFPT_STATS_REPLY,
+ timeout=test_timeout)
+ total_packets += self.sumStatsReplyCounts(response)
+
if total_packets == packet_count:
all_packets_received = 1
break
sleep(1)
self.assertTrue(all_packets_received,
- "Packet count does not match number sent")
+ "Total stats packet count " + str(total_packets) +
+ " does not match number sent " + str(packet_count))
def runTest(self):
global fs_port_map
@@ -294,15 +301,18 @@
num_pkt2s = random.randint(10,30)
fs_logger.info("Sending " + str(num_pkt2s) + " pkt2s")
for i in range(0,num_pkt1s):
- self.sendPacket(pkt1, ingress_port, egress_port1, test_timeout)
+ sendPacket(self, pkt1, ingress_port, egress_port1, test_timeout)
for i in range(0,num_pkt2s):
- self.sendPacket(pkt2, ingress_port, egress_port2, test_timeout)
+ sendPacket(self, pkt2, ingress_port, egress_port2, test_timeout)
match1 = parse.packet_to_flow_match(pkt1)
+ fs_logger.info("Verifying flow1's " + str(num_pkt1s) + " packets")
self.verifyStats(match1, ofp.OFPP_NONE, test_timeout, num_pkt1s)
match2 = parse.packet_to_flow_match(pkt2)
+ fs_logger.info("Verifying flow2's " + str(num_pkt2s) + " packets")
self.verifyStats(match2, ofp.OFPP_NONE, test_timeout, num_pkt2s)
match1.wildcards |= ofp.OFPFW_DL_SRC
+ fs_logger.info("Verifying combined " + str(num_pkt1s+num_pkt2s) + " packets")
self.verifyStats(match1, ofp.OFPP_NONE, test_timeout,
num_pkt1s+num_pkt2s)
# TODO: sweep through the wildcards to verify matching?
@@ -341,23 +351,6 @@
return flow_mod_msg
- def sendPacket(self, pkt, ingress_port, egress_port, test_timeout):
- fs_logger.info("Sending packet to dp port " +
- str(ingress_port))
- self.dataplane.send(ingress_port, str(pkt))
- (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=
- test_timeout)
- self.assertTrue(rcv_pkt is not None, "Did not receive packet")
- fs_logger.debug("Packet len " + str(len(pkt)) + " in on " +
- str(rcv_port))
- self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
- for j in range(0,test_timeout):
- if str(pkt) == str(rcv_pkt):
- break
- sleep(1)
- self.assertTrue(j < test_timeout,
- 'Timeout sending packets for flow stats test')
-
def verifyAggFlowStats(self, match, out_port, test_timeout,
flow_count, packet_count):
stat_req = message.aggregate_stats_request()
@@ -424,9 +417,9 @@
num_pkt2s = random.randint(10,30)
fs_logger.info("Sending " + str(num_pkt2s) + " pkt2s")
for i in range(0,num_pkt1s):
- self.sendPacket(pkt1, ingress_port, egress_port1, test_timeout)
+ sendPacket(self, pkt1, ingress_port, egress_port1, test_timeout)
for i in range(0,num_pkt2s):
- self.sendPacket(pkt2, ingress_port, egress_port2, test_timeout)
+ sendPacket(self, pkt2, ingress_port, egress_port2, test_timeout)
# loop on flow stats request until timeout
match = parse.packet_to_flow_match(pkt1)