This patch adds two system tests for bonding failover with multicast snooping with a best effort attempt to simulate real multicast activity without adding any dependancies to the testsuite.
Both tests feature the creation of a linux bridge, and an ad-hoc python program that joins a multicast group. The linux bridge doesn't use linux kernel bonding as otherwise bridge mdb show attributes group membership to the bond instead of the member interface. Assisted-by: Claude Opus 4.8, Cursor Signed-off-by: Mike Pattrick <[email protected]> --- note: These tests can be slow. I am unsure if we want to include them, so I removed them from the previous patch. --- tests/system-traffic.at | 130 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/tests/system-traffic.at b/tests/system-traffic.at index a1794ceca..b63b1ae9b 100644 --- a/tests/system-traffic.at +++ b/tests/system-traffic.at @@ -295,6 +295,136 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -W 2 10.1.1.2 | FORMAT_PING OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([IGMP - send reports on bond failover]) +OVS_TRAFFIC_VSWITCHD_START() +AT_CHECK([ovs-vsctl set bridge br0 mcast_snooping_enable=true -- \ + set bridge br0 other-config:mcast-snooping-disable-flood-unregistered=true]) +AT_CHECK([ovs-ofctl add-flow br0 "actions=NORMAL"]) +ADD_NAMESPACES(at_ns0, at_ns1) +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") +AT_CHECK([ip link add p1 type veth peer name ovs-p1 || return 77]) +on_exit 'ip link del ovs-p1' +CONFIGURE_VETH_OFFLOADS([p1]) +AT_CHECK([ip link set p1 netns at_ns1]) +AT_CHECK([ip link set dev ovs-p1 up]) +AT_CHECK([ip link add p2 type veth peer name ovs-p2 || return 77]) +on_exit 'ip link del ovs-p2' +CONFIGURE_VETH_OFFLOADS([p2]) +AT_CHECK([ip link set p2 netns at_ns1]) +AT_CHECK([ip link set dev ovs-p2 up]) +NS_CHECK_EXEC([at_ns1], [ip link add br1 type bridge]) +NS_CHECK_EXEC([at_ns1], [ip link set p1 master br1]) +NS_CHECK_EXEC([at_ns1], [ip link set p2 master br1]) +NS_CHECK_EXEC([at_ns1], [ip link set dev p1 up]) +NS_CHECK_EXEC([at_ns1], [ip link set dev p2 up]) +NS_CHECK_EXEC([at_ns1], [ip link set br1 up]) +NS_CHECK_EXEC([at_ns1], [ip addr add 10.1.1.2/24 dev br1]) +NS_CHECK_EXEC([at_ns1], [sh -c "echo 1 > /sys/class/net/br1/bridge/multicast_snooping"]) +NS_CHECK_EXEC([at_ns1], [sh -c "echo 0 > /sys/class/net/br1/bridge/multicast_querier"]) +AT_CHECK([ovs-vsctl add-bond br0 bond0 ovs-p1 ovs-p2 \ + bond_mode=active-backup]) + +AT_CHECK([ip link set dev ovs-p1 down]) +AT_CHECK([ip link set dev ovs-p2 down]) +AT_CHECK([ip link set dev ovs-p1 up]) +sleep 1 +AT_CHECK([ovs-appctl bond/set-active-member bond0 ovs-p1], [0], [ignore]) +OVS_WAIT_UNTIL([ovs-appctl bond/show bond0 | grep -q "active member.*ovs-p1"]) +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 -i 0.3 -W 2 10.1.1.2]) +AT_CHECK([ip link set dev ovs-p2 up]) + +sleep 1 +NETNS_DAEMONIZE([at_ns0], + [$PYTHON3 -c " +import socket, struct, time +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +s.bind(('10.1.1.1', 5000)) +mreq = struct.pack('4s4s', + socket.inet_aton('239.1.1.1'), + socket.inet_aton('10.1.1.1')) +s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) +time.sleep(300) +"], [mcast_join.pid]) +OVS_WAIT_UNTIL([ovs-appctl mdb/show br0 | grep -q "239.1.1.1"]) +AT_CHECK([ip link set dev ovs-p1 down]) +OVS_WAIT_UNTIL([ovs-appctl bond/show bond0 | grep -q "active member.*ovs-p2"]) +OVS_WAIT_UNTIL([NS_EXEC([at_ns1], + [bridge mdb show dev br1 | grep "239.1.1.1" | grep -q p2])]) +OVS_TRAFFIC_VSWITCHD_STOP(["/Network is down/d +/No such device/d"]) +AT_CLEANUP + +AT_SETUP([MLD - send reports on bond failover]) +OVS_TRAFFIC_VSWITCHD_START() +AT_CHECK([ovs-vsctl set bridge br0 mcast_snooping_enable=true -- \ + set bridge br0 other-config:mcast-snooping-disable-flood-unregistered=true]) +AT_CHECK([ovs-ofctl add-flow br0 "actions=NORMAL"]) +ADD_NAMESPACES(at_ns0, at_ns1) +ADD_VETH(p0, at_ns0, br0, "fc00::1/96") + +dnl Create veth pairs for bond members. +AT_CHECK([ip link add p1 type veth peer name ovs-p1 || return 77]) +on_exit 'ip link del ovs-p1' +CONFIGURE_VETH_OFFLOADS([p1]) +AT_CHECK([ip link set p1 netns at_ns1]) +AT_CHECK([ip link set dev ovs-p1 up]) +AT_CHECK([ip link add p2 type veth peer name ovs-p2 || return 77]) +on_exit 'ip link del ovs-p2' +CONFIGURE_VETH_OFFLOADS([p2]) +AT_CHECK([ip link set p2 netns at_ns1]) +AT_CHECK([ip link set dev ovs-p2 up]) + +dnl Linux bridge in at_ns1 with p1 and p2 as individual ports. +dnl This lets us verify exactly which port the replayed MLD arrives on. +NS_CHECK_EXEC([at_ns1], [ip link add br1 type bridge]) +NS_CHECK_EXEC([at_ns1], [ip link set p1 master br1]) +NS_CHECK_EXEC([at_ns1], [ip link set p2 master br1]) +NS_CHECK_EXEC([at_ns1], [ip link set dev p1 up]) +NS_CHECK_EXEC([at_ns1], [ip link set dev p2 up]) +NS_CHECK_EXEC([at_ns1], [ip link set br1 up]) +NS_CHECK_EXEC([at_ns1], [ip -6 addr add fc00::2/96 dev br1 nodad]) +NS_CHECK_EXEC([at_ns1], [sh -c "echo 1 > /sys/class/net/br1/bridge/multicast_snooping"]) +NS_CHECK_EXEC([at_ns1], [sh -c "echo 0 > /sys/class/net/br1/bridge/multicast_querier"]) + +dnl OVS active-backup bond. +AT_CHECK([ovs-vsctl add-bond br0 bond0 ovs-p1 ovs-p2 \ + bond_mode=active-backup]) +AT_CHECK([ip link set dev ovs-p1 down]) +AT_CHECK([ip link set dev ovs-p2 down]) +AT_CHECK([ip link set dev ovs-p1 up]) +sleep 1 +AT_CHECK([ovs-appctl bond/set-active-member bond0 ovs-p1], [0], [ignore]) +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 1 fc00::2]) +AT_CHECK([ip link set dev ovs-p2 up]) + +dnl Join IPv6 multicast group from at_ns0 using a real socket. +NETNS_DAEMONIZE([at_ns0], + [$PYTHON3 -c " +import socket, struct, time +s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +s.bind(('::', 5000)) +ifindex = socket.if_nametoindex('p0') +mreq = struct.pack('16sI', + socket.inet_pton(socket.AF_INET6, 'ff35::db8:1'), + ifindex) +s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq) +time.sleep(300) +"], [mcast_join.pid]) +OVS_WAIT_UNTIL([ovs-appctl mdb/show br0 | grep -q "ff35::db8:1"]) + +dnl Trigger failover. +AT_CHECK([ip link set dev ovs-p1 down]) +OVS_WAIT_UNTIL([ovs-appctl bond/show bond0 | grep -q "active member.*ovs-p2"]) + +dnl The replayed MLD must arrive on p2, the new active member's peer. +OVS_WAIT_UNTIL([NS_EXEC([at_ns1], + [bridge mdb show dev br1 | grep "ff35::db8:1" | grep -q p2])]) +OVS_TRAFFIC_VSWITCHD_STOP(["/Network is down/d +/No such device/d"]) +AT_CLEANUP + AT_SETUP([datapath - ping over vxlan tunnel]) AT_SKIP_IF([test $HAVE_NC = no]) OVS_CHECK_VXLAN() -- 2.56.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
