selftests: bonding: add fail_over_mac testing
authorHangbin Liu <liuhangbin@gmail.com>
Wed, 10 Sep 2025 02:43:35 +0000 (02:43 +0000)
committerJakub Kicinski <kuba@kernel.org>
Tue, 16 Sep 2025 00:48:42 +0000 (17:48 -0700)
Add a test to check each value of bond fail_over_mac option.

Also fix a minor garp_test print issue.

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Link: https://patch.msgid.link/20250910024336.400253-2-liuhangbin@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
tools/testing/selftests/drivers/net/bonding/bond_options.sh
tools/testing/selftests/drivers/net/bonding/bond_topo_2d1c.sh
tools/testing/selftests/drivers/net/bonding/bond_topo_3d1c.sh

index 7bc148889ca729ed82f915ae0f701a84419a06b8..e3f3cc803b562c3e39591bae5660dadae206270e 100755 (executable)
@@ -7,6 +7,7 @@ ALL_TESTS="
        prio
        arp_validate
        num_grat_arp
+       fail_over_mac
 "
 
 lib_dir=$(dirname "$0")
@@ -352,8 +353,8 @@ garp_test()
 
        exp_num=$(echo "${param}" | cut -f6 -d ' ')
        active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
-       slowwait_for_counter $((exp_num + 5)) $exp_num \
-               tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}"
+       slowwait_for_counter $((exp_num + 5)) $exp_num tc_rule_handle_stats_get \
+               "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}" &> /dev/null
 
        # check result
        real_num=$(tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}")
@@ -376,6 +377,140 @@ num_grat_arp()
        done
 }
 
+check_all_mac_same()
+{
+       RET=0
+       # all slaves should have same mac address (with the first port's mac)
+       local bond_mac=$(ip -n "$s_ns" -j link show bond0 | jq -r '.[]["address"]')
+       local eth0_mac=$(ip -n "$s_ns" -j link show eth0 | jq -r '.[]["address"]')
+       local eth1_mac=$(ip -n "$s_ns" -j link show eth1 | jq -r '.[]["address"]')
+       local eth2_mac=$(ip -n "$s_ns" -j link show eth2 | jq -r '.[]["address"]')
+       if [ "$bond_mac" != "${mac[0]}" ] || [ "$eth0_mac" != "$bond_mac" ] || \
+               [ "$eth1_mac" != "$bond_mac" ] || [ "$eth2_mac" != "$bond_mac" ]; then
+               RET=1
+       fi
+}
+
+check_bond_mac_same_with_first()
+{
+       RET=0
+       # bond mac address should be same with the first added slave
+       local bond_mac=$(ip -n "$s_ns" -j link show bond0 | jq -r '.[]["address"]')
+       if [ "$bond_mac" != "${mac[0]}" ]; then
+               RET=1
+       fi
+}
+
+check_bond_mac_same_with_active()
+{
+       RET=0
+       # bond mac address should be same with active slave
+       local bond_mac=$(ip -n "$s_ns" -j link show bond0 | jq -r '.[]["address"]')
+       local active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
+       local active_slave_mac=$(ip -n "$s_ns" -j link show "$active_slave" | jq -r '.[]["address"]')
+       if [ "$bond_mac" != "$active_slave_mac" ]; then
+               RET=1
+       fi
+}
+
+check_backup_slave_mac_not_change()
+{
+       RET=0
+       # backup slave's mac address is not changed
+       if ip -n "$s_ns" -d -j link show type bond_slave | jq -e '.[]
+               | select(.linkinfo.info_slave_data.state=="BACKUP")
+               | select(.address != .linkinfo.info_slave_data.perm_hwaddr)' &> /dev/null; then
+               RET=1
+       fi
+}
+
+check_backup_slave_mac_inherit()
+{
+       local backup_mac
+       RET=0
+
+       # backup slaves should use mac[1] or mac[2]
+       local backup_macs=$(ip -n "$s_ns" -d -j link show type bond_slave | \
+               jq -r '.[] | select(.linkinfo.info_slave_data.state=="BACKUP") | .address')
+       for backup_mac in $backup_macs; do
+               if [ "$backup_mac" != "${mac[1]}" ] && [ "$backup_mac" != "${mac[2]}" ]; then
+                       RET=1
+               fi
+       done
+}
+
+check_first_slave_random_mac()
+{
+       RET=0
+       # remove the first added slave and added it back
+       ip -n "$s_ns" link set eth0 nomaster
+       ip -n "$s_ns" link set eth0 master bond0
+
+       # the first slave should use random mac address
+       eth0_mac=$(ip -n "$s_ns" -j link show eth0 | jq -r '.[]["address"]')
+       [ "$eth0_mac" = "${mac[0]}" ] && RET=1
+       log_test "bond fail_over_mac follow" "random first slave mac"
+
+       # remove the first slave, the permanent MAC address should be restored back
+       ip -n "$s_ns" link set eth0 nomaster
+       eth0_mac=$(ip -n "$s_ns" -j link show eth0 | jq -r '.[]["address"]')
+       [ "$eth0_mac" != "${mac[0]}" ] && RET=1
+}
+
+do_active_backup_failover()
+{
+       local active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
+       ip -n ${s_ns} link set ${active_slave} down
+       slowwait 2 active_slave_changed $active_slave
+       ip -n ${s_ns} link set ${active_slave} up
+}
+
+fail_over_mac()
+{
+       # Bring down the first interface on the switch to force the bond to
+       # select another active interface instead of the first one that joined.
+       ip -n "$g_ns" link set s0 down
+
+       # fail_over_mac none
+       bond_reset "mode active-backup miimon 100 fail_over_mac 0"
+       check_all_mac_same
+       log_test "fail_over_mac 0" "all slaves have same mac"
+       do_active_backup_failover
+       check_all_mac_same
+       log_test "fail_over_mac 0" "failover: all slaves have same mac"
+
+       # fail_over_mac active
+       bond_reset "mode active-backup miimon 100 fail_over_mac 1"
+       check_bond_mac_same_with_active
+       log_test "fail_over_mac 1" "bond mac is same with active slave mac"
+       check_backup_slave_mac_not_change
+       log_test "fail_over_mac 1" "backup slave mac is not changed"
+       do_active_backup_failover
+       check_bond_mac_same_with_active
+       log_test "fail_over_mac 1" "failover: bond mac is same with active slave mac"
+       check_backup_slave_mac_not_change
+       log_test "fail_over_mac 1" "failover: backup slave mac is not changed"
+
+       # fail_over_mac follow
+       bond_reset "mode active-backup miimon 100 fail_over_mac 2"
+       check_bond_mac_same_with_first
+       log_test "fail_over_mac 2" "bond mac is same with first slave mac"
+       check_bond_mac_same_with_active
+       log_test "fail_over_mac 2" "bond mac is same with active slave mac"
+       check_backup_slave_mac_inherit
+       log_test "fail_over_mac 2" "backup slave mac inherit"
+       do_active_backup_failover
+       check_bond_mac_same_with_first
+       log_test "fail_over_mac 2" "failover: bond mac is same with first slave mac"
+       check_bond_mac_same_with_active
+       log_test "fail_over_mac 2" "failover: bond mac is same with active slave mac"
+       check_backup_slave_mac_inherit
+       log_test "fail_over_mac 2" "failover: backup slave mac inherit"
+       check_first_slave_random_mac
+       log_test "fail_over_mac 2" "first slave mac random"
+
+}
+
 trap cleanup EXIT
 
 setup_prepare
index 195ef83cfbf167297b925e9b4f9b76b4d839a284..167aa4a4a12a42290bc184f8847dd82a7dfe3432 100644 (file)
@@ -39,6 +39,8 @@ g_ip4="192.0.2.254"
 s_ip6="2001:db8::1"
 c_ip6="2001:db8::10"
 g_ip6="2001:db8::254"
+mac[0]="00:0a:0b:0c:0d:01"
+mac[1]="00:0a:0b:0c:0d:02"
 
 gateway_create()
 {
@@ -62,6 +64,7 @@ server_create()
 
        for i in $(seq 0 1); do
                ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns}
+               ip -n "${s_ns}" link set "eth${i}" addr "${mac[$i]}"
 
                ip -n ${g_ns} link set s${i} up
                ip -n ${g_ns} link set s${i} master br0
index 3a1333d9a85b3661a6a4632f7c82df4dd708d7b7..23a2932301cc0d7f0cc2e422831a5a68ffe725c8 100644 (file)
@@ -26,6 +26,7 @@
 #  +-------------------------------------+
 
 source bond_topo_2d1c.sh
+mac[2]="00:0a:0b:0c:0d:03"
 
 setup_prepare()
 {
@@ -36,6 +37,7 @@ setup_prepare()
        # Add the extra device as we use 3 down links for bond0
        local i=2
        ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns}
+       ip -n "${s_ns}" link set "eth${i}" addr "${mac[$i]}"
        ip -n ${g_ns} link set s${i} up
        ip -n ${g_ns} link set s${i} master br0
        ip -n ${s_ns} link set eth${i} master bond0