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

selftests: net: test SO_PRIORITY ancillary data with cmsg_sender

Extend cmsg_sender.c with a new option '-Q' to send SO_PRIORITY
ancillary data.

cmsg_so_priority.sh script added to validate SO_PRIORITY behavior
by creating VLAN device with egress QoS mapping and testing packet
priorities using flower filters. Verify that packets with different
priorities are correctly matched and counted by filters for multiple
protocols and IP versions.

Reviewed-by: Willem de Bruijn <willemb@google.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Tested-by: Ido Schimmel <idosch@nvidia.com>
Suggested-by: Ido Schimmel <idosch@idosch.org>
Signed-off-by: Anna Emese Nyiri <annaemesenyiri@gmail.com>
Link: https://patch.msgid.link/20241213084457.45120-4-annaemesenyiri@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Anna Emese Nyiri and committed by
Jakub Kicinski
cda7d5ab a32f3e9d

+162 -1
+1
tools/testing/selftests/net/Makefile
··· 32 32 TEST_PROGS += gro.sh 33 33 TEST_PROGS += gre_gso.sh 34 34 TEST_PROGS += cmsg_so_mark.sh 35 + TEST_PROGS += cmsg_so_priority.sh 35 36 TEST_PROGS += cmsg_time.sh cmsg_ipv6.sh 36 37 TEST_PROGS += netns-name.sh 37 38 TEST_PROGS += nl_netdev.py
+10 -1
tools/testing/selftests/net/cmsg_sender.c
··· 59 59 unsigned int proto; 60 60 } sock; 61 61 struct option_cmsg_u32 mark; 62 + struct option_cmsg_u32 priority; 62 63 struct { 63 64 bool ena; 64 65 unsigned int delay; ··· 98 97 "\n" 99 98 "\t\t-m val Set SO_MARK with given value\n" 100 99 "\t\t-M val Set SO_MARK via setsockopt\n" 100 + "\t\t-P val Set SO_PRIORITY via setsockopt\n" 101 + "\t\t-Q val Set SO_PRIORITY via cmsg\n" 101 102 "\t\t-d val Set SO_TXTIME with given delay (usec)\n" 102 103 "\t\t-t Enable time stamp reporting\n" 103 104 "\t\t-f val Set don't fragment via cmsg\n" ··· 118 115 { 119 116 int o; 120 117 121 - while ((o = getopt(argc, argv, "46sS:p:P:m:M:n:d:tf:F:c:C:l:L:H:")) != -1) { 118 + while ((o = getopt(argc, argv, "46sS:p:P:m:M:n:d:tf:F:c:C:l:L:H:Q:")) != -1) { 122 119 switch (o) { 123 120 case 's': 124 121 opt.silent_send = true; ··· 150 147 case 'm': 151 148 opt.mark.ena = true; 152 149 opt.mark.val = atoi(optarg); 150 + break; 151 + case 'Q': 152 + opt.priority.ena = true; 153 + opt.priority.val = atoi(optarg); 153 154 break; 154 155 case 'M': 155 156 opt.sockopt.mark = atoi(optarg); ··· 259 252 260 253 ca_write_cmsg_u32(cbuf, cbuf_sz, &cmsg_len, 261 254 SOL_SOCKET, SO_MARK, &opt.mark); 255 + ca_write_cmsg_u32(cbuf, cbuf_sz, &cmsg_len, 256 + SOL_SOCKET, SO_PRIORITY, &opt.priority); 262 257 ca_write_cmsg_u32(cbuf, cbuf_sz, &cmsg_len, 263 258 SOL_IPV6, IPV6_DONTFRAG, &opt.v6.dontfrag); 264 259 ca_write_cmsg_u32(cbuf, cbuf_sz, &cmsg_len,
+151
tools/testing/selftests/net/cmsg_so_priority.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + source lib.sh 5 + 6 + readonly KSFT_SKIP=4 7 + 8 + IP4=192.0.2.1/24 9 + TGT4=192.0.2.2 10 + TGT4_RAW=192.0.2.3 11 + IP6=2001:db8::1/64 12 + TGT6=2001:db8::2 13 + TGT6_RAW=2001:db8::3 14 + PORT=1234 15 + TOTAL_TESTS=0 16 + FAILED_TESTS=0 17 + 18 + if ! command -v jq &> /dev/null; then 19 + echo "SKIP cmsg_so_priroity.sh test: jq is not installed." >&2 20 + exit "$KSFT_SKIP" 21 + fi 22 + 23 + check_result() { 24 + ((TOTAL_TESTS++)) 25 + if [ "$1" -ne 0 ]; then 26 + ((FAILED_TESTS++)) 27 + fi 28 + } 29 + 30 + cleanup() 31 + { 32 + cleanup_ns $NS 33 + } 34 + 35 + trap cleanup EXIT 36 + 37 + setup_ns NS 38 + 39 + create_filter() { 40 + local handle=$1 41 + local vlan_prio=$2 42 + local ip_type=$3 43 + local proto=$4 44 + local dst_ip=$5 45 + local ip_proto 46 + 47 + if [[ "$proto" == "u" ]]; then 48 + ip_proto="udp" 49 + elif [[ "$ip_type" == "ipv4" && "$proto" == "i" ]]; then 50 + ip_proto="icmp" 51 + elif [[ "$ip_type" == "ipv6" && "$proto" == "i" ]]; then 52 + ip_proto="icmpv6" 53 + fi 54 + 55 + tc -n $NS filter add dev dummy1 \ 56 + egress pref 1 handle "$handle" proto 802.1q \ 57 + flower vlan_prio "$vlan_prio" vlan_ethtype "$ip_type" \ 58 + dst_ip "$dst_ip" ${ip_proto:+ip_proto $ip_proto} \ 59 + action pass 60 + } 61 + 62 + ip -n $NS link set dev lo up 63 + ip -n $NS link add name dummy1 up type dummy 64 + 65 + ip -n $NS link add link dummy1 name dummy1.10 up type vlan id 10 \ 66 + egress-qos-map 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 67 + 68 + ip -n $NS address add $IP4 dev dummy1.10 69 + ip -n $NS address add $IP6 dev dummy1.10 nodad 70 + 71 + ip netns exec $NS sysctl -wq net.ipv4.ping_group_range='0 2147483647' 72 + 73 + ip -n $NS neigh add $TGT4 lladdr 00:11:22:33:44:55 nud permanent \ 74 + dev dummy1.10 75 + ip -n $NS neigh add $TGT6 lladdr 00:11:22:33:44:55 nud permanent \ 76 + dev dummy1.10 77 + ip -n $NS neigh add $TGT4_RAW lladdr 00:11:22:33:44:66 nud permanent \ 78 + dev dummy1.10 79 + ip -n $NS neigh add $TGT6_RAW lladdr 00:11:22:33:44:66 nud permanent \ 80 + dev dummy1.10 81 + 82 + tc -n $NS qdisc add dev dummy1 clsact 83 + 84 + FILTER_COUNTER=10 85 + 86 + for i in 4 6; do 87 + for proto in u i r; do 88 + echo "Test IPV$i, prot: $proto" 89 + for priority in {0..7}; do 90 + if [[ $i == 4 && $proto == "r" ]]; then 91 + TGT=$TGT4_RAW 92 + elif [[ $i == 6 && $proto == "r" ]]; then 93 + TGT=$TGT6_RAW 94 + elif [ $i == 4 ]; then 95 + TGT=$TGT4 96 + else 97 + TGT=$TGT6 98 + fi 99 + 100 + handle="${FILTER_COUNTER}${priority}" 101 + 102 + create_filter $handle $priority ipv$i $proto $TGT 103 + 104 + pkts=$(tc -n $NS -j -s filter show dev dummy1 egress \ 105 + | jq ".[] | select(.options.handle == ${handle}) | \ 106 + .options.actions[0].stats.packets") 107 + 108 + if [[ $pkts == 0 ]]; then 109 + check_result 0 110 + else 111 + echo "prio $priority: expected 0, got $pkts" 112 + check_result 1 113 + fi 114 + 115 + ip netns exec $NS ./cmsg_sender -$i -Q $priority \ 116 + -p $proto $TGT $PORT 117 + 118 + pkts=$(tc -n $NS -j -s filter show dev dummy1 egress \ 119 + | jq ".[] | select(.options.handle == ${handle}) | \ 120 + .options.actions[0].stats.packets") 121 + if [[ $pkts == 1 ]]; then 122 + check_result 0 123 + else 124 + echo "prio $priority -Q: expected 1, got $pkts" 125 + check_result 1 126 + fi 127 + 128 + ip netns exec $NS ./cmsg_sender -$i -P $priority \ 129 + -p $proto $TGT $PORT 130 + 131 + pkts=$(tc -n $NS -j -s filter show dev dummy1 egress \ 132 + | jq ".[] | select(.options.handle == ${handle}) | \ 133 + .options.actions[0].stats.packets") 134 + if [[ $pkts == 2 ]]; then 135 + check_result 0 136 + else 137 + echo "prio $priority -P: expected 2, got $pkts" 138 + check_result 1 139 + fi 140 + done 141 + FILTER_COUNTER=$((FILTER_COUNTER + 10)) 142 + done 143 + done 144 + 145 + if [ $FAILED_TESTS -ne 0 ]; then 146 + echo "FAIL - $FAILED_TESTS/$TOTAL_TESTS tests failed" 147 + exit 1 148 + else 149 + echo "OK - All $TOTAL_TESTS tests passed" 150 + exit 0 151 + fi