#!/bin/bash # SPDX-License-Identifier: GPL-2.0 NAMESPACES="" # Test that a link aggregation device (bonding, team) removes the hardware # addresses that it adds on its underlying devices. test_LAG_cleanup() { local driver=$1 local mode=$2 local ucaddr="02:00:00:12:34:56" local addr6="fe80::78:9abc/64" local mcaddr="33:33:ff:78:9a:bc" local name ip link add dummy1 type dummy ip link add dummy2 type dummy if [ "$driver" = "bonding" ]; then name="bond1" ip link add "$name" up type bond mode "$mode" ip link set dev dummy1 master "$name" ip link set dev dummy2 master "$name" elif [ "$driver" = "team" ]; then name="team0" teamd -d -c ' { "device": "'"$name"'", "runner": { "name": "'"$mode"'" }, "ports": { "dummy1": {}, "dummy2": {} } } ' ip link set dev "$name" up else check_err 1 log_test test_LAG_cleanup ": unknown driver \"$driver\"" return fi # Used to test dev->uc handling ip link add mv0 link "$name" up address "$ucaddr" type macvlan # Used to test dev->mc handling ip address add "$addr6" dev "$name" # Check that addresses were added as expected (grep_bridge_fdb "$ucaddr" bridge fdb show dev dummy1 || grep_bridge_fdb "$ucaddr" bridge fdb show dev dummy2) >/dev/null check_err $? "macvlan unicast address not found on a slave" # mcaddr is added asynchronously by addrconf_dad_work(), use busywait (busywait 10000 grep_bridge_fdb "$mcaddr" bridge fdb show dev dummy1 || grep_bridge_fdb "$mcaddr" bridge fdb show dev dummy2) >/dev/null check_err $? "IPv6 solicited-node multicast mac address not found on a slave" ip link set dev "$name" down ip link del "$name" not grep_bridge_fdb "$ucaddr" bridge fdb show >/dev/null check_err $? "macvlan unicast address still present on a slave" not grep_bridge_fdb "$mcaddr" bridge fdb show >/dev/null check_err $? "IPv6 solicited-node multicast mac address still present on a slave" cleanup log_test "$driver cleanup mode $mode" } # Build a generic 2 node net namespace with 2 connections # between the namespaces # # +-----------+ +-----------+ # | node1 | | node2 | # | | | | # | | | | # | eth0 +-------+ eth0 | # | | | | # | eth1 +-------+ eth1 | # | | | | # +-----------+ +-----------+ lag_setup2x2() { local state=${1:-down} local namespaces="lag_node1 lag_node2" # create namespaces for n in ${namespaces}; do ip netns add ${n} done # wire up namespaces ip link add name lag1 type veth peer name lag1-end ip link set dev lag1 netns lag_node1 $state name eth0 ip link set dev lag1-end netns lag_node2 $state name eth0 ip link add name lag1 type veth peer name lag1-end ip link set dev lag1 netns lag_node1 $state name eth1 ip link set dev lag1-end netns lag_node2 $state name eth1 NAMESPACES="${namespaces}" } # cleanup all lag related namespaces lag_cleanup() { for n in ${NAMESPACES}; do ip netns delete ${n} >/dev/null 2>&1 || true done } SWITCH="lag_node1" CLIENT="lag_node2" CLIENTIP="172.20.2.1" SWITCHIP="172.20.2.2" lag_setup_network() { lag_setup2x2 "down" # create switch ip netns exec ${SWITCH} ip link add br0 up type bridge ip netns exec ${SWITCH} ip link set eth0 master br0 up ip netns exec ${SWITCH} ip link set eth1 master br0 up ip netns exec ${SWITCH} ip addr add ${SWITCHIP}/24 dev br0 } lag_reset_network() { ip netns exec ${CLIENT} ip link del bond0 ip netns exec ${SWITCH} ip link set eth0 up ip netns exec ${SWITCH} ip link set eth1 up } create_bond() { # create client ip netns exec ${CLIENT} ip link set eth0 down ip netns exec ${CLIENT} ip link set eth1 down ip netns exec ${CLIENT} ip link add bond0 type bond $@ ip netns exec ${CLIENT} ip link set eth0 master bond0 ip netns exec ${CLIENT} ip link set eth1 master bond0 ip netns exec ${CLIENT} ip link set bond0 up ip netns exec ${CLIENT} ip addr add ${CLIENTIP}/24 dev bond0 } test_bond_recovery() { RET=0 create_bond $@ # verify connectivity slowwait 2 ip netns exec ${CLIENT} ping ${SWITCHIP} -c 2 -W 0.1 &> /dev/null check_err $? "No connectivity" # force the links of the bond down ip netns exec ${SWITCH} ip link set eth0 down sleep 2 ip netns exec ${SWITCH} ip link set eth0 up ip netns exec ${SWITCH} ip link set eth1 down # re-verify connectivity slowwait 2 ip netns exec ${CLIENT} ping ${SWITCHIP} -c 2 -W 0.1 &> /dev/null local rc=$? check_err $rc "Bond failed to recover" log_test "$1 ($2) bond recovery" lag_reset_network }