groups-1.3: add tests for SELECT group forwarding
Tests empty, single-buckets, and multiple-bucket groups.
Does not test port-down or unequal-weight scenarios. Doesn't use any bucket
actions other than a single output.
diff --git a/tests-1.3/groups.py b/tests-1.3/groups.py
index 64bd656..d1bc83a 100644
--- a/tests-1.3/groups.py
+++ b/tests-1.3/groups.py
@@ -8,6 +8,7 @@
"""
import logging
+import random
from oftest import config
import oftest
@@ -780,3 +781,127 @@
self.assertEqual(response.flow_count, 2,
'Did not match expected flow count')
+
+
+class SelectFwdEmpty(GroupTest):
+ """
+ A SELECT group with no buckets should not alter the action set of the packet
+ """
+
+ def runTest(self):
+ port1, port2 = openflow_ports(2)
+
+ msg = ofp.message.group_mod(
+ command=ofp.OFPGC_ADD,
+ group_type=ofp.OFPGT_SELECT,
+ group_id=1,
+ buckets=[])
+
+ self.controller.message_send(msg)
+ do_barrier(self.controller)
+
+ msg = ofp.message.flow_add(
+ buffer_id=ofp.OFP_NO_BUFFER,
+ instructions=[
+ ofp.instruction.apply_actions(
+ [ofp.action.output(2), ofp.action.group(1)])])
+
+ self.controller.message_send(msg)
+ do_barrier(self.controller)
+
+ verify_no_errors(self.controller)
+
+ pkt = simple_tcp_packet()
+ self.dataplane.send(port1, str(pkt))
+ verify_packets(self, pkt, [port2])
+
+
+class SelectFwdSingle(GroupTest):
+ """
+ A SELECT group with a single bucket should use that bucket's actions
+ """
+
+ def runTest(self):
+ port1, port2 = openflow_ports(2)
+
+ msg = ofp.message.group_mod(
+ command=ofp.OFPGC_ADD,
+ group_type=ofp.OFPGT_SELECT,
+ group_id=1,
+ buckets=[
+ ofp.bucket(weight=1, actions=[ofp.action.output(port2)])])
+
+ self.controller.message_send(msg)
+ do_barrier(self.controller)
+
+ msg = ofp.message.flow_add(
+ buffer_id=ofp.OFP_NO_BUFFER,
+ instructions=[ofp.instruction.apply_actions([ofp.action.group(1)])])
+
+ self.controller.message_send(msg)
+ do_barrier(self.controller)
+
+ verify_no_errors(self.controller)
+
+ pkt = simple_tcp_packet()
+ self.dataplane.send(port1, str(pkt))
+ verify_packets(self, pkt, [port2])
+
+
+class SelectFwdSpread(GroupTest):
+ """
+ A SELECT group with several buckets should spead different flows between them
+ """
+
+ def runTest(self):
+ num_out_ports = 3
+ num_pkts = 1000
+
+ port1, port2, port3, port4 = openflow_ports(num_out_ports + 1)
+ out_ports = [port2, port3, port4]
+
+ msg = ofp.message.group_mod(
+ command=ofp.OFPGC_ADD,
+ group_type=ofp.OFPGT_SELECT,
+ group_id=1,
+ buckets=[
+ ofp.bucket(weight=1, actions=[ofp.action.output(port)])
+ for port in out_ports])
+
+ self.controller.message_send(msg)
+ do_barrier(self.controller)
+
+ msg = ofp.message.flow_add(
+ buffer_id=ofp.OFP_NO_BUFFER,
+ instructions=[ofp.instruction.apply_actions([ofp.action.group(1)])])
+
+ self.controller.message_send(msg)
+ do_barrier(self.controller)
+
+ verify_no_errors(self.controller)
+
+ counters = { x: 0 for x in out_ports }
+
+ for i in xrange(0, num_pkts):
+ pkt = simple_tcp_packet(tcp_sport=i, tcp_dport=random.randint(0, 65535))
+ self.dataplane.send(port1, str(pkt))
+ (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=str(pkt))
+ self.assertIsNotNone(rcv_pkt)
+ if rcv_port not in counters:
+ raise AssertionError("unexpected packet on port %d" % rcv_port)
+ counters[rcv_port] += 1
+
+ # Verify the same flow is mapped to the same output port
+ self.dataplane.send(port1, str(pkt))
+ (rcv_port2, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=str(pkt))
+ self.assertIsNotNone(rcv_pkt)
+ self.assertEquals(rcv_port, rcv_port2)
+
+ logging.debug("Distribution: %r" ,counters)
+
+ self.assertEquals(sum(counters.values()), num_pkts)
+ expected = num_pkts/num_out_ports
+ for port, count in counters.iteritems():
+ # Check that count is within 20% of expected
+ self.assertTrue(expected * 0.8 < count < expected * 1.2,
+ "port %d count was %d, expected %d" % (port, count, expected))