Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: fib_rule_tests: Test UDP and TCP connections with DSCP rules.

Add the fib_rule6_send and fib_rule4_send tests to verify that DSCP
values are properly taken into account when UDP or TCP sockets try to
connect().

Tests are done with nettest, which needs a new option to specify
the DS Field value of the socket being tested. This new option is
named '-Q', in reference to the similar option used by ping.

Signed-off-by: Guillaume Nault <gnault@redhat.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Guillaume Nault and committed by
Jakub Kicinski
c21a20d9 8230680f

+177 -2
+127 -1
tools/testing/selftests/net/fib_rule_tests.sh
··· 10 10 11 11 PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no} 12 12 IP="ip -netns testns" 13 + IP_PEER="ip -netns peerns" 13 14 14 15 RTABLE=100 16 + RTABLE_PEER=101 15 17 GW_IP4=192.51.100.2 16 18 SRC_IP=192.51.100.3 17 19 GW_IP6=2001:db8:1::2 ··· 22 20 DEV_ADDR=192.51.100.1 23 21 DEV_ADDR6=2001:db8:1::1 24 22 DEV=dummy0 25 - TESTS="fib_rule6 fib_rule4" 23 + TESTS="fib_rule6 fib_rule4 fib_rule6_connect fib_rule4_connect" 24 + 25 + SELFTEST_PATH="" 26 26 27 27 log_test() 28 28 { ··· 56 52 echo "######################################################################" 57 53 } 58 54 55 + check_nettest() 56 + { 57 + if which nettest > /dev/null 2>&1; then 58 + return 0 59 + fi 60 + 61 + # Add the selftest directory to PATH if not already done 62 + if [ "${SELFTEST_PATH}" = "" ]; then 63 + SELFTEST_PATH="$(dirname $0)" 64 + PATH="${PATH}:${SELFTEST_PATH}" 65 + 66 + # Now retry with the new path 67 + if which nettest > /dev/null 2>&1; then 68 + return 0 69 + fi 70 + 71 + if [ "${ret}" -eq 0 ]; then 72 + ret="${ksft_skip}" 73 + fi 74 + echo "nettest not found (try 'make -C ${SELFTEST_PATH} nettest')" 75 + fi 76 + 77 + return 1 78 + } 79 + 59 80 setup() 60 81 { 61 82 set -e ··· 99 70 { 100 71 $IP link del dev dummy0 &> /dev/null 101 72 ip netns del testns 73 + } 74 + 75 + setup_peer() 76 + { 77 + set -e 78 + 79 + ip netns add peerns 80 + $IP_PEER link set dev lo up 81 + 82 + ip link add name veth0 netns testns type veth \ 83 + peer name veth1 netns peerns 84 + $IP link set dev veth0 up 85 + $IP_PEER link set dev veth1 up 86 + 87 + $IP address add 192.0.2.10 peer 192.0.2.11/32 dev veth0 88 + $IP_PEER address add 192.0.2.11 peer 192.0.2.10/32 dev veth1 89 + 90 + $IP address add 2001:db8::10 peer 2001:db8::11/128 dev veth0 nodad 91 + $IP_PEER address add 2001:db8::11 peer 2001:db8::10/128 dev veth1 nodad 92 + 93 + $IP_PEER address add 198.51.100.11/32 dev lo 94 + $IP route add table $RTABLE_PEER 198.51.100.11/32 via 192.0.2.11 95 + 96 + $IP_PEER address add 2001:db8::1:11/128 dev lo 97 + $IP route add table $RTABLE_PEER 2001:db8::1:11/128 via 2001:db8::11 98 + 99 + set +e 100 + } 101 + 102 + cleanup_peer() 103 + { 104 + $IP link del dev veth0 105 + ip netns del peerns 102 106 } 103 107 104 108 fib_check_iproute_support() ··· 252 190 fi 253 191 } 254 192 193 + # Verify that the IPV6_TCLASS option of UDPv6 and TCPv6 sockets is properly 194 + # taken into account when connecting the socket and when sending packets. 195 + fib_rule6_connect_test() 196 + { 197 + local dsfield 198 + 199 + if ! check_nettest; then 200 + echo "SKIP: Could not run test without nettest tool" 201 + return 202 + fi 203 + 204 + setup_peer 205 + $IP -6 rule add dsfield 0x04 table $RTABLE_PEER 206 + 207 + # Combine the base DS Field value (0x04) with all possible ECN values 208 + # (Not-ECT: 0, ECT(1): 1, ECT(0): 2, CE: 3). 209 + # The ECN bits shouldn't influence the result of the test. 210 + for dsfield in 0x04 0x05 0x06 0x07; do 211 + nettest -q -6 -B -t 5 -N testns -O peerns -U -D \ 212 + -Q "${dsfield}" -l 2001:db8::1:11 -r 2001:db8::1:11 213 + log_test $? 0 "rule6 dsfield udp connect (dsfield ${dsfield})" 214 + 215 + nettest -q -6 -B -t 5 -N testns -O peerns -Q "${dsfield}" \ 216 + -l 2001:db8::1:11 -r 2001:db8::1:11 217 + log_test $? 0 "rule6 dsfield tcp connect (dsfield ${dsfield})" 218 + done 219 + 220 + $IP -6 rule del dsfield 0x04 table $RTABLE_PEER 221 + cleanup_peer 222 + } 223 + 255 224 fib_rule4_del() 256 225 { 257 226 $IP rule del $1 ··· 389 296 fi 390 297 } 391 298 299 + # Verify that the IP_TOS option of UDPv4 and TCPv4 sockets is properly taken 300 + # into account when connecting the socket and when sending packets. 301 + fib_rule4_connect_test() 302 + { 303 + local dsfield 304 + 305 + if ! check_nettest; then 306 + echo "SKIP: Could not run test without nettest tool" 307 + return 308 + fi 309 + 310 + setup_peer 311 + $IP -4 rule add dsfield 0x04 table $RTABLE_PEER 312 + 313 + # Combine the base DS Field value (0x04) with all possible ECN values 314 + # (Not-ECT: 0, ECT(1): 1, ECT(0): 2, CE: 3). 315 + # The ECN bits shouldn't influence the result of the test. 316 + for dsfield in 0x04 0x05 0x06 0x07; do 317 + nettest -q -B -t 5 -N testns -O peerns -D -U -Q "${dsfield}" \ 318 + -l 198.51.100.11 -r 198.51.100.11 319 + log_test $? 0 "rule4 dsfield udp connect (dsfield ${dsfield})" 320 + 321 + nettest -q -B -t 5 -N testns -O peerns -Q "${dsfield}" \ 322 + -l 198.51.100.11 -r 198.51.100.11 323 + log_test $? 0 "rule4 dsfield tcp connect (dsfield ${dsfield})" 324 + done 325 + 326 + $IP -4 rule del dsfield 0x04 table $RTABLE_PEER 327 + cleanup_peer 328 + } 329 + 392 330 run_fibrule_tests() 393 331 { 394 332 log_section "IPv4 fib rule" ··· 469 345 case $t in 470 346 fib_rule6_test|fib_rule6) fib_rule6_test;; 471 347 fib_rule4_test|fib_rule4) fib_rule4_test;; 348 + fib_rule6_connect_test|fib_rule6_connect) fib_rule6_connect_test;; 349 + fib_rule4_connect_test|fib_rule4_connect) fib_rule4_connect_test;; 472 350 473 351 help) echo "Test names: $TESTS"; exit 0;; 474 352
+50 -1
tools/testing/selftests/net/nettest.c
··· 87 87 int use_setsockopt; 88 88 int use_freebind; 89 89 int use_cmsg; 90 + uint8_t dsfield; 90 91 const char *dev; 91 92 const char *server_dev; 92 93 int ifindex; ··· 579 578 } 580 579 581 580 return rc; 581 + } 582 + 583 + static int set_dsfield(int sd, int version, int dsfield) 584 + { 585 + if (!dsfield) 586 + return 0; 587 + 588 + switch (version) { 589 + case AF_INET: 590 + if (setsockopt(sd, SOL_IP, IP_TOS, &dsfield, 591 + sizeof(dsfield)) < 0) { 592 + log_err_errno("setsockopt(IP_TOS)"); 593 + return -1; 594 + } 595 + break; 596 + 597 + case AF_INET6: 598 + if (setsockopt(sd, SOL_IPV6, IPV6_TCLASS, &dsfield, 599 + sizeof(dsfield)) < 0) { 600 + log_err_errno("setsockopt(IPV6_TCLASS)"); 601 + return -1; 602 + } 603 + break; 604 + 605 + default: 606 + log_error("Invalid address family\n"); 607 + return -1; 608 + } 609 + 610 + return 0; 582 611 } 583 612 584 613 static int str_to_uint(const char *str, int min, int max, unsigned int *value) ··· 1348 1317 (char *)&one, sizeof(one)) < 0) 1349 1318 log_err_errno("Setting SO_BROADCAST error"); 1350 1319 1320 + if (set_dsfield(sd, AF_INET, args->dsfield) != 0) 1321 + goto out_err; 1322 + 1351 1323 if (args->dev && bind_to_device(sd, args->dev) != 0) 1352 1324 goto out_err; 1353 1325 else if (args->use_setsockopt && ··· 1477 1443 goto err; 1478 1444 1479 1445 if (set_reuseport(sd) != 0) 1446 + goto err; 1447 + 1448 + if (set_dsfield(sd, args->version, args->dsfield) != 0) 1480 1449 goto err; 1481 1450 1482 1451 if (args->dev && bind_to_device(sd, args->dev) != 0) ··· 1695 1658 if (set_reuseport(sd) != 0) 1696 1659 goto err; 1697 1660 1661 + if (set_dsfield(sd, args->version, args->dsfield) != 0) 1662 + goto err; 1663 + 1698 1664 if (args->dev && bind_to_device(sd, args->dev) != 0) 1699 1665 goto err; 1700 1666 else if (args->use_setsockopt && ··· 1902 1862 return client_status; 1903 1863 } 1904 1864 1905 - #define GETOPT_STR "sr:l:c:p:t:g:P:DRn:M:X:m:d:I:BN:O:SUCi6xL:0:1:2:3:Fbqf" 1865 + #define GETOPT_STR "sr:l:c:Q:p:t:g:P:DRn:M:X:m:d:I:BN:O:SUCi6xL:0:1:2:3:Fbqf" 1906 1866 #define OPT_FORCE_BIND_KEY_IFINDEX 1001 1907 1867 #define OPT_NO_BIND_KEY_IFINDEX 1002 1908 1868 ··· 1933 1893 " -D|R datagram (D) / raw (R) socket (default stream)\n" 1934 1894 " -l addr local address to bind to in server mode\n" 1935 1895 " -c addr local address to bind to in client mode\n" 1896 + " -Q dsfield DS Field value of the socket (the IP_TOS or\n" 1897 + " IPV6_TCLASS socket option)\n" 1936 1898 " -x configure XFRM policy on socket\n" 1937 1899 "\n" 1938 1900 " -d dev bind socket to given device name\n" ··· 2012 1970 case 'c': 2013 1971 args.has_local_ip = 1; 2014 1972 args.client_local_addr_str = optarg; 1973 + break; 1974 + case 'Q': 1975 + if (str_to_uint(optarg, 0, 255, &tmp) != 0) { 1976 + fprintf(stderr, "Invalid DS Field\n"); 1977 + return 1; 1978 + } 1979 + args.dsfield = tmp; 2015 1980 break; 2016 1981 case 'p': 2017 1982 if (str_to_uint(optarg, 1, 65535, &tmp) != 0) {