302 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03 4# ShellCheck incorrectly believes that most of the code here is unreachable5# because it's invoked by variable name following ALL_TESTS.6#7# shellcheck disable=SC23178 9ALL_TESTS="check_accounting check_limit"10NUM_NETIFS=611source lib.sh12 13TEST_MAC_BASE=de:ad:be:ef:42:14 15NUM_PKTS=1616FDB_LIMIT=817 18FDB_TYPES=(19 # name is counted? overrides learned?20 'learned 1 0'21 'static 0 1'22 'user 0 1'23 'extern_learn 0 1'24 'local 0 1'25)26 27mac()28{29 printf "${TEST_MAC_BASE}%02x" "$1"30}31 32H1_DEFAULT_MAC=$(mac 42)33 34switch_create()35{36 ip link add dev br0 type bridge37 38 ip link set dev "$swp1" master br039 ip link set dev "$swp2" master br040 # swp3 is used to add local MACs, so do not add it to the bridge yet.41 42 # swp2 is only used for replying when learning on swp1, its MAC should not be learned.43 ip link set dev "$swp2" type bridge_slave learning off44 45 ip link set dev br0 up46 47 ip link set dev "$swp1" up48 ip link set dev "$swp2" up49 ip link set dev "$swp3" up50}51 52switch_destroy()53{54 ip link set dev "$swp3" down55 ip link set dev "$swp2" down56 ip link set dev "$swp1" down57 58 ip link del dev br059}60 61h_create()62{63 ip link set "$h1" addr "$H1_DEFAULT_MAC"64 65 simple_if_init "$h1" 192.0.2.1/2466 simple_if_init "$h2" 192.0.2.2/2467}68 69h_destroy()70{71 simple_if_fini "$h1" 192.0.2.1/2472 simple_if_fini "$h2" 192.0.2.2/2473}74 75setup_prepare()76{77 h1=${NETIFS[p1]}78 swp1=${NETIFS[p2]}79 80 h2=${NETIFS[p3]}81 swp2=${NETIFS[p4]}82 83 swp3=${NETIFS[p6]}84 85 vrf_prepare86 87 h_create88 89 switch_create90}91 92cleanup()93{94 pre_cleanup95 96 switch_destroy97 98 h_destroy99 100 vrf_cleanup101}102 103fdb_get_n_learned()104{105 ip -d -j link show dev br0 type bridge | \106 jq '.[]["linkinfo"]["info_data"]["fdb_n_learned"]'107}108 109fdb_get_n_mac()110{111 local mac=${1}112 113 bridge -j fdb show br br0 | \114 jq "map(select(.mac == \"${mac}\" and (has(\"vlan\") | not))) | length"115}116 117fdb_fill_learned()118{119 local i120 121 for i in $(seq 1 "$NUM_PKTS"); do122 fdb_add learned "$(mac "$i")"123 done124}125 126fdb_reset()127{128 bridge fdb flush dev br0129 130 # Keep the default MAC address of h1 in the table. We set it to a different one when131 # testing dynamic learning.132 bridge fdb add "$H1_DEFAULT_MAC" dev "$swp1" master static use133}134 135fdb_add()136{137 local type=$1 mac=$2138 139 case "$type" in140 learned)141 ip link set "$h1" addr "$mac"142 # Wait for a reply so we implicitly wait until after the forwarding143 # code finished and the FDB entry was created.144 PING_COUNT=1 ping_do "$h1" 192.0.2.2145 check_err $? "Failed to ping another bridge port"146 ip link set "$h1" addr "$H1_DEFAULT_MAC"147 ;;148 local)149 ip link set dev "$swp3" addr "$mac" && ip link set "$swp3" master br0150 ;;151 static)152 bridge fdb replace "$mac" dev "$swp1" master static153 ;;154 user)155 bridge fdb replace "$mac" dev "$swp1" master static use156 ;;157 extern_learn)158 bridge fdb replace "$mac" dev "$swp1" master extern_learn159 ;;160 esac161 162 check_err $? "Failed to add a FDB entry of type ${type}"163}164 165fdb_del()166{167 local type=$1 mac=$2168 169 case "$type" in170 local)171 ip link set "$swp3" nomaster172 ;;173 *)174 bridge fdb del "$mac" dev "$swp1" master175 ;;176 esac177 178 check_err $? "Failed to remove a FDB entry of type ${type}"179}180 181check_fdb_n_learned_support()182{183 if ! ip link help bridge 2>&1 | grep -q "fdb_max_learned"; then184 echo "SKIP: iproute2 too old, missing bridge max learned support"185 exit $ksft_skip186 fi187 188 ip link add dev br0 type bridge189 local learned=$(fdb_get_n_learned)190 ip link del dev br0191 if [ "$learned" == "null" ]; then192 echo "SKIP: kernel too old; bridge fdb_n_learned feature not supported."193 exit $ksft_skip194 fi195}196 197check_accounting_one_type()198{199 local type=$1 is_counted=$2 overrides_learned=$3200 shift 3201 RET=0202 203 fdb_reset204 fdb_add "$type" "$(mac 0)"205 learned=$(fdb_get_n_learned)206 [ "$learned" -ne "$is_counted" ]207 check_fail $? "Inserted FDB type ${type}: Expected the count ${is_counted}, but got ${learned}"208 209 fdb_del "$type" "$(mac 0)"210 learned=$(fdb_get_n_learned)211 [ "$learned" -ne 0 ]212 check_fail $? "Removed FDB type ${type}: Expected the count 0, but got ${learned}"213 214 if [ "$overrides_learned" -eq 1 ]; then215 fdb_reset216 fdb_add learned "$(mac 0)"217 fdb_add "$type" "$(mac 0)"218 learned=$(fdb_get_n_learned)219 [ "$learned" -ne "$is_counted" ]220 check_fail $? "Set a learned entry to FDB type ${type}: Expected the count ${is_counted}, but got ${learned}"221 fdb_del "$type" "$(mac 0)"222 fi223 224 log_test "FDB accounting interacting with FDB type ${type}"225}226 227check_accounting()228{229 local type_args learned230 RET=0231 232 fdb_reset233 learned=$(fdb_get_n_learned)234 [ "$learned" -ne 0 ]235 check_fail $? "Flushed the FDB table: Expected the count 0, but got ${learned}"236 237 fdb_fill_learned238 sleep 1239 240 learned=$(fdb_get_n_learned)241 [ "$learned" -ne "$NUM_PKTS" ]242 check_fail $? "Filled the FDB table: Expected the count ${NUM_PKTS}, but got ${learned}"243 244 log_test "FDB accounting"245 246 for type_args in "${FDB_TYPES[@]}"; do247 # This is intentional use of word splitting.248 # shellcheck disable=SC2086249 check_accounting_one_type $type_args250 done251}252 253check_limit_one_type()254{255 local type=$1 is_counted=$2256 local n_mac expected=$((1 - is_counted))257 RET=0258 259 fdb_reset260 fdb_fill_learned261 262 fdb_add "$type" "$(mac 0)"263 n_mac=$(fdb_get_n_mac "$(mac 0)")264 [ "$n_mac" -ne "$expected" ]265 check_fail $? "Inserted FDB type ${type} at limit: Expected the count ${expected}, but got ${n_mac}"266 267 log_test "FDB limits interacting with FDB type ${type}"268}269 270check_limit()271{272 local learned273 RET=0274 275 ip link set br0 type bridge fdb_max_learned "$FDB_LIMIT"276 277 fdb_reset278 fdb_fill_learned279 280 learned=$(fdb_get_n_learned)281 [ "$learned" -ne "$FDB_LIMIT" ]282 check_fail $? "Filled the limited FDB table: Expected the count ${FDB_LIMIT}, but got ${learned}"283 284 log_test "FDB limits"285 286 for type_args in "${FDB_TYPES[@]}"; do287 # This is intentional use of word splitting.288 # shellcheck disable=SC2086289 check_limit_one_type $type_args290 done291}292 293check_fdb_n_learned_support294 295trap cleanup EXIT296 297setup_prepare298 299tests_run300 301exit $EXIT_STATUS302