Skip to content

Commit 59ecffa

Browse files
author
Florian Westphal
committed
selftests: netfilter: nft_queue.sh: add udp fraglist gro test case
Without the preceding patch, this fails with: FAIL: test_udp_gro_ct: Expected udp conntrack entry FAIL: test_udp_gro_ct: Expected software segmentation to occur, had 10 and 0 Signed-off-by: Florian Westphal <fw@strlen.de>
1 parent 207b3eb commit 59ecffa

1 file changed

Lines changed: 136 additions & 6 deletions

File tree

tools/testing/selftests/net/netfilter/nft_queue.sh

Lines changed: 136 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -510,15 +510,15 @@ EOF
510510

511511
udp_listener_ready()
512512
{
513-
ss -S -N "$1" -uln -o "sport = :12345" | grep -q 12345
513+
ss -S -N "$1" -uln -o "sport = :$2" | grep -q "$2"
514514
}
515515

516516
output_files_written()
517517
{
518518
test -s "$1" && test -s "$2"
519519
}
520520

521-
test_udp_ct_race()
521+
test_udp_nat_race()
522522
{
523523
ip netns exec "$nsrouter" nft -f /dev/stdin <<EOF
524524
flush ruleset
@@ -545,8 +545,8 @@ EOF
545545
ip netns exec "$nsrouter" ./nf_queue -q 12 -d 1000 &
546546
local nfqpid=$!
547547

548-
busywait "$BUSYWAIT_TIMEOUT" udp_listener_ready "$ns2"
549-
busywait "$BUSYWAIT_TIMEOUT" udp_listener_ready "$ns3"
548+
busywait "$BUSYWAIT_TIMEOUT" udp_listener_ready "$ns2" 12345
549+
busywait "$BUSYWAIT_TIMEOUT" udp_listener_ready "$ns3" 12345
550550
busywait "$BUSYWAIT_TIMEOUT" nf_queue_wait "$nsrouter" 12
551551

552552
# Send two packets, one should end up in ns1, other in ns2.
@@ -557,7 +557,7 @@ EOF
557557

558558
busywait 10000 output_files_written "$TMPFILE1" "$TMPFILE2"
559559

560-
kill "$nfqpid"
560+
kill "$nfqpid" "$rpid1" "$rpid2"
561561

562562
if ! ip netns exec "$nsrouter" bash -c 'conntrack -L -p udp --dport 12345 2>/dev/null | wc -l | grep -q "^1"'; then
563563
echo "FAIL: Expected One udp conntrack entry"
@@ -585,6 +585,135 @@ EOF
585585
echo "PASS: both udp receivers got one packet each"
586586
}
587587

588+
# Make sure UDPGRO aggregated packets don't lose
589+
# their skb->nfct entry when nfqueue passes the
590+
# skb to userspace with software gso segmentation on.
591+
test_udp_gro_ct()
592+
{
593+
local errprefix="FAIL: test_udp_gro_ct:"
594+
595+
ip netns exec "$nsrouter" conntrack -F 2>/dev/null
596+
597+
ip netns exec "$nsrouter" nft -f /dev/stdin <<EOF
598+
flush ruleset
599+
table inet udpq {
600+
# Number of packets/bytes queued to userspace
601+
counter toqueue { }
602+
# Number of packets/bytes reinjected from userspace with 'ct new' intact
603+
counter fromqueue { }
604+
# These two counters should be identical and not 0.
605+
606+
chain prerouting {
607+
type filter hook prerouting priority -300; policy accept;
608+
609+
# userspace sends small packets, if < 1000, UDPGRO did
610+
# not kick in, but test needs a 'new' conntrack with udpgro skb.
611+
meta iifname veth0 meta l4proto udp meta length > 1000 accept
612+
613+
# don't pick up non-gso packets and don't queue them to
614+
# userspace.
615+
notrack
616+
}
617+
618+
chain postrouting {
619+
type filter hook postrouting priority 0; policy accept;
620+
621+
# Only queue unconfirmed fraglist gro skbs to userspace.
622+
udp dport 12346 ct status ! confirmed counter name "toqueue" mark set 1 queue num 1
623+
}
624+
625+
chain validate {
626+
type filter hook postrouting priority 1; policy accept;
627+
# ... and only count those that were reinjected with the
628+
# skb->nfct intact.
629+
mark 1 counter name "fromqueue"
630+
}
631+
}
632+
EOF
633+
timeout 10 ip netns exec "$ns2" socat UDP-LISTEN:12346,fork,pf=ipv4 OPEN:"$TMPFILE1",trunc &
634+
local rpid=$!
635+
636+
ip netns exec "$nsrouter" ./nf_queue -G -c -q 1 -t 2 > "$TMPFILE2" &
637+
local nfqpid=$!
638+
639+
ip netns exec "$nsrouter" ethtool -K "veth0" rx-udp-gro-forwarding on rx-gro-list on generic-receive-offload on
640+
641+
busywait "$BUSYWAIT_TIMEOUT" udp_listener_ready "$ns2" 12346
642+
busywait "$BUSYWAIT_TIMEOUT" nf_queue_wait "$nsrouter" 1
643+
644+
local bs=512
645+
local count=$(((32 * 1024 * 1024) / bs))
646+
dd if=/dev/zero bs="$bs" count="$count" 2>/dev/null | for i in $(seq 1 16); do
647+
timeout 5 ip netns exec "$ns1" \
648+
socat -u -b 512 STDIN UDP-DATAGRAM:10.0.2.99:12346,reuseport,bind=0.0.0.0:55221 &
649+
done
650+
651+
busywait 10000 test -s "$TMPFILE1"
652+
653+
kill "$rpid"
654+
655+
wait
656+
657+
local p
658+
local b
659+
local pqueued
660+
local bqueued
661+
662+
c=$(ip netns exec "$nsrouter" nft list counter inet udpq "toqueue" | grep packets)
663+
read p pqueued b bqueued <<EOF
664+
$c
665+
EOF
666+
local preinject
667+
local breinject
668+
c=$(ip netns exec "$nsrouter" nft list counter inet udpq "fromqueue" | grep packets)
669+
read p preinject b breinject <<EOF
670+
$c
671+
EOF
672+
ip netns exec "$nsrouter" ethtool -K "veth0" rx-udp-gro-forwarding off
673+
ip netns exec "$nsrouter" ethtool -K "veth1" rx-udp-gro-forwarding off
674+
675+
if [ "$pqueued" -eq 0 ];then
676+
# happens when gro did not build at least on aggregate
677+
echo "SKIP: No packets were queued"
678+
return
679+
fi
680+
681+
local saw_ct_entry=0
682+
if ip netns exec "$nsrouter" bash -c 'conntrack -L -p udp --dport 12346 2>/dev/null | wc -l | grep -q "^1"'; then
683+
saw_ct_entry=1
684+
else
685+
echo "$errprefix Expected udp conntrack entry"
686+
ip netns exec "$nsrouter" conntrack -L
687+
ret=1
688+
fi
689+
690+
if [ "$pqueued" -ge "$preinject" ] ;then
691+
echo "$errprefix Expected software segmentation to occur, had $pqueued and $preinject"
692+
ret=1
693+
return
694+
fi
695+
696+
# sw segmentation adds extra udp and ip headers.
697+
local breinject_expect=$((preinject * (512 + 20 + 8)))
698+
699+
if [ "$breinject" -eq "$breinject_expect" ]; then
700+
if [ "$saw_ct_entry" -eq 1 ];then
701+
echo "PASS: fraglist gro skb passed with conntrack entry"
702+
else
703+
echo "$errprefix fraglist gro skb passed without conntrack entry"
704+
ret=1
705+
fi
706+
else
707+
echo "$errprefix Counter mismatch, conntrack entry dropped by nfqueue? Queued: $pqueued, $bqueued. Post-queue: $preinject, $breinject. Expected $breinject_expect"
708+
ret=1
709+
fi
710+
711+
if ! ip netns exec "$nsrouter" nft delete table inet udpq; then
712+
echo "$errprefix: Could not delete udpq table"
713+
ret=1
714+
fi
715+
}
716+
588717
test_queue_removal()
589718
{
590719
read tainted_then < /proc/sys/kernel/tainted
@@ -663,7 +792,8 @@ test_tcp_localhost_connectclose
663792
test_tcp_localhost_requeue
664793
test_sctp_forward
665794
test_sctp_output
666-
test_udp_ct_race
795+
test_udp_nat_race
796+
test_udp_gro_ct
667797

668798
# should be last, adds vrf device in ns1 and changes routes
669799
test_icmp_vrf

0 commit comments

Comments
 (0)