1 #!/bin/bash 2 # SPDX-License-Identifier: GPL-2.0 3 4 # +-------------------------+ +-------------------------+ 5 # | H1 | | H2 | 6 # | $h1 + | | + $h2 | 7 # | 192.0.2.1/28 | | | | 192.0.2.34/28 | 8 # | 2001:db8:1::1/64 | | | | 2001:db8:3::2/64 | 9 # +-------------------|-----+ +-|-----------------------+ 10 # | | 11 # +-------------------|-----+ +-|-----------------------+ 12 # | R1 | | | | R2 | 13 # | $rp11 + | | + $rp21 | 14 # | 192.0.2.2/28 | | 192.0.2.33/28 | 15 # | 2001:db8:1::2/64 | | 2001:db8:3::1/64 | 16 # | | | | 17 # | $rp12 + | | + $rp22 | 18 # | 192.0.2.17/28 | | | | 192.0.2.18..27/28 | 19 # | 2001:db8:2::17/64 | | | | 2001:db8:2::18..27/64 | 20 # +-------------------|-----+ +-|-----------------------+ 21 # | | 22 # `----------' 23 24 ALL_TESTS=" 25 ping_ipv4 26 ping_ipv6 27 test_mpath_seed_stability_ipv4 28 test_mpath_seed_stability_ipv6 29 test_mpath_seed_get 30 test_mpath_seed_ipv4 31 test_mpath_seed_ipv6 32 " 33 NUM_NETIFS=6 34 source lib.sh 35 36 h1_create() 37 { 38 simple_if_init $h1 192.0.2.1/28 2001:db8:1::1/64 39 ip -4 route add 192.0.2.32/28 vrf v$h1 nexthop via 192.0.2.2 40 ip -6 route add 2001:db8:3::/64 vrf v$h1 nexthop via 2001:db8:1::2 41 } 42 43 h1_destroy() 44 { 45 ip -6 route del 2001:db8:3::/64 vrf v$h1 nexthop via 2001:db8:1::2 46 ip -4 route del 192.0.2.32/28 vrf v$h1 nexthop via 192.0.2.2 47 simple_if_fini $h1 192.0.2.1/28 2001:db8:1::1/64 48 } 49 50 h2_create() 51 { 52 simple_if_init $h2 192.0.2.34/28 2001:db8:3::2/64 53 ip -4 route add 192.0.2.0/28 vrf v$h2 nexthop via 192.0.2.33 54 ip -6 route add 2001:db8:1::/64 vrf v$h2 nexthop via 2001:db8:3::1 55 } 56 57 h2_destroy() 58 { 59 ip -6 route del 2001:db8:1::/64 vrf v$h2 nexthop via 2001:db8:3::1 60 ip -4 route del 192.0.2.0/28 vrf v$h2 nexthop via 192.0.2.33 61 simple_if_fini $h2 192.0.2.34/28 2001:db8:3::2/64 62 } 63 64 router1_create() 65 { 66 simple_if_init $rp11 192.0.2.2/28 2001:db8:1::2/64 67 __simple_if_init $rp12 v$rp11 192.0.2.17/28 2001:db8:2::17/64 68 } 69 70 router1_destroy() 71 { 72 __simple_if_fini $rp12 192.0.2.17/28 2001:db8:2::17/64 73 simple_if_fini $rp11 192.0.2.2/28 2001:db8:1::2/64 74 } 75 76 router2_create() 77 { 78 simple_if_init $rp21 192.0.2.33/28 2001:db8:3::1/64 79 __simple_if_init $rp22 v$rp21 192.0.2.18/28 2001:db8:2::18/64 80 ip -4 route add 192.0.2.0/28 vrf v$rp21 nexthop via 192.0.2.17 81 ip -6 route add 2001:db8:1::/64 vrf v$rp21 nexthop via 2001:db8:2::17 82 } 83 84 router2_destroy() 85 { 86 ip -6 route del 2001:db8:1::/64 vrf v$rp21 nexthop via 2001:db8:2::17 87 ip -4 route del 192.0.2.0/28 vrf v$rp21 nexthop via 192.0.2.17 88 __simple_if_fini $rp22 192.0.2.18/28 2001:db8:2::18/64 89 simple_if_fini $rp21 192.0.2.33/28 2001:db8:3::1/64 90 } 91 92 nexthops_create() 93 { 94 local i 95 for i in $(seq 10); do 96 ip nexthop add id $((1000 + i)) via 192.0.2.18 dev $rp12 97 ip nexthop add id $((2000 + i)) via 2001:db8:2::18 dev $rp12 98 done 99 100 ip nexthop add id 1000 group $(seq -s / 1001 1010) hw_stats on 101 ip nexthop add id 2000 group $(seq -s / 2001 2010) hw_stats on 102 ip -4 route add 192.0.2.32/28 vrf v$rp11 nhid 1000 103 ip -6 route add 2001:db8:3::/64 vrf v$rp11 nhid 2000 104 } 105 106 nexthops_destroy() 107 { 108 local i 109 110 ip -6 route del 2001:db8:3::/64 vrf v$rp11 nhid 2000 111 ip -4 route del 192.0.2.32/28 vrf v$rp11 nhid 1000 112 ip nexthop del id 2000 113 ip nexthop del id 1000 114 115 for i in $(seq 10 -1 1); do 116 ip nexthop del id $((2000 + i)) 117 ip nexthop del id $((1000 + i)) 118 done 119 } 120 121 setup_prepare() 122 { 123 h1=${NETIFS[p1]} 124 rp11=${NETIFS[p2]} 125 126 rp12=${NETIFS[p3]} 127 rp22=${NETIFS[p4]} 128 129 rp21=${NETIFS[p5]} 130 h2=${NETIFS[p6]} 131 132 sysctl_save net.ipv4.fib_multipath_hash_seed 133 134 vrf_prepare 135 136 h1_create 137 h2_create 138 router1_create 139 router2_create 140 141 forwarding_enable 142 } 143 144 cleanup() 145 { 146 pre_cleanup 147 148 forwarding_restore 149 150 nexthops_destroy 151 router2_destroy 152 router1_destroy 153 h2_destroy 154 h1_destroy 155 156 vrf_cleanup 157 158 sysctl_restore net.ipv4.fib_multipath_hash_seed 159 } 160 161 ping_ipv4() 162 { 163 ping_test $h1 192.0.2.34 164 } 165 166 ping_ipv6() 167 { 168 ping6_test $h1 2001:db8:3::2 169 } 170 171 test_mpath_seed_get() 172 { 173 RET=0 174 175 local i 176 for ((i = 0; i < 100; i++)); do 177 local seed_w=$((999331 * i)) 178 sysctl -qw net.ipv4.fib_multipath_hash_seed=$seed_w 179 local seed_r=$(sysctl -n net.ipv4.fib_multipath_hash_seed) 180 ((seed_r == seed_w)) 181 check_err $? "mpath seed written as $seed_w, but read as $seed_r" 182 done 183 184 log_test "mpath seed set/get" 185 } 186 187 nh_stats_snapshot() 188 { 189 local group_id=$1; shift 190 191 ip -j -s -s nexthop show id $group_id | 192 jq -c '[.[].group_stats | sort_by(.id) | .[].packets]' 193 } 194 195 get_active_nh() 196 { 197 local s0=$1; shift 198 local s1=$1; shift 199 200 jq -n --argjson s0 "$s0" --argjson s1 "$s1" -f /dev/stdin <<-"EOF" 201 [range($s0 | length)] | 202 map($s1[.] - $s0[.]) | 203 map(if . > 8 then 1 else 0 end) | 204 index(1) 205 EOF 206 } 207 208 probe_nh() 209 { 210 local group_id=$1; shift 211 local -a mz=("$@") 212 213 local s0=$(nh_stats_snapshot $group_id) 214 "${mz[@]}" 215 local s1=$(nh_stats_snapshot $group_id) 216 217 get_active_nh "$s0" "$s1" 218 } 219 220 probe_seed() 221 { 222 local group_id=$1; shift 223 local seed=$1; shift 224 local -a mz=("$@") 225 226 sysctl -qw net.ipv4.fib_multipath_hash_seed=$seed 227 probe_nh "$group_id" "${mz[@]}" 228 } 229 230 test_mpath_seed() 231 { 232 local group_id=$1; shift 233 local what=$1; shift 234 local -a mz=("$@") 235 local ii 236 237 RET=0 238 239 local -a tally=(0 0 0 0 0 0 0 0 0 0) 240 for ((ii = 0; ii < 100; ii++)); do 241 local act=$(probe_seed $group_id $((999331 * ii)) "${mz[@]}") 242 ((tally[act]++)) 243 done 244 245 local tally_str="${tally[@]}" 246 for ((ii = 0; ii < ${#tally[@]}; ii++)); do 247 ((tally[ii] > 0)) 248 check_err $? "NH #$ii not hit, tally='$tally_str'" 249 done 250 251 log_test "mpath seed $what" 252 sysctl -qw net.ipv4.fib_multipath_hash_seed=0 253 } 254 255 test_mpath_seed_ipv4() 256 { 257 test_mpath_seed 1000 IPv4 \ 258 $MZ $h1 -A 192.0.2.1 -B 192.0.2.34 -q \ 259 -p 64 -d 0 -c 10 -t udp 260 } 261 262 test_mpath_seed_ipv6() 263 { 264 test_mpath_seed 2000 IPv6 \ 265 $MZ -6 $h1 -A 2001:db8:1::1 -B 2001:db8:3::2 -q \ 266 -p 64 -d 0 -c 10 -t udp 267 } 268 269 check_mpath_seed_stability() 270 { 271 local seed=$1; shift 272 local act_0=$1; shift 273 local act_1=$1; shift 274 275 ((act_0 == act_1)) 276 check_err $? "seed $seed: active NH moved from $act_0 to $act_1 after seed change" 277 } 278 279 test_mpath_seed_stability() 280 { 281 local group_id=$1; shift 282 local what=$1; shift 283 local -a mz=("$@") 284 285 RET=0 286 287 local seed_0=0 288 local seed_1=3221338814 289 local seed_2=3735928559 290 291 # Initial active NH before touching the seed at all. 292 local act_ini=$(probe_nh $group_id "${mz[@]}") 293 294 local act_0_0=$(probe_seed $group_id $seed_0 "${mz[@]}") 295 local act_1_0=$(probe_seed $group_id $seed_1 "${mz[@]}") 296 local act_2_0=$(probe_seed $group_id $seed_2 "${mz[@]}") 297 298 local act_0_1=$(probe_seed $group_id $seed_0 "${mz[@]}") 299 local act_1_1=$(probe_seed $group_id $seed_1 "${mz[@]}") 300 local act_2_1=$(probe_seed $group_id $seed_2 "${mz[@]}") 301 302 check_mpath_seed_stability initial $act_ini $act_0_0 303 check_mpath_seed_stability $seed_0 $act_0_0 $act_0_1 304 check_mpath_seed_stability $seed_1 $act_1_0 $act_1_1 305 check_mpath_seed_stability $seed_2 $act_2_0 $act_2_1 306 307 log_test "mpath seed stability $what" 308 sysctl -qw net.ipv4.fib_multipath_hash_seed=0 309 } 310 311 test_mpath_seed_stability_ipv4() 312 { 313 test_mpath_seed_stability 1000 IPv4 \ 314 $MZ $h1 -A 192.0.2.1 -B 192.0.2.34 -q \ 315 -p 64 -d 0 -c 10 -t udp 316 } 317 318 test_mpath_seed_stability_ipv6() 319 { 320 test_mpath_seed_stability 2000 IPv6 \ 321 $MZ -6 $h1 -A 2001:db8:1::1 -B 2001:db8:3::2 -q \ 322 -p 64 -d 0 -c 10 -t udp 323 } 324 325 trap cleanup EXIT 326 327 setup_prepare 328 setup_wait 329 nexthops_create 330 331 tests_run 332 333 exit $EXIT_STATUS
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.