@@ -31,7 +31,7 @@ modprobe -q sctp
3131
3232trap cleanup EXIT
3333
34- setup_ns ns1 ns2 nsrouter
34+ setup_ns ns1 ns2 ns3 nsrouter
3535
3636TMPFILE0=$( mktemp)
3737TMPFILE1=$( mktemp)
@@ -48,6 +48,7 @@ if ! ip link add veth0 netns "$nsrouter" type veth peer name eth0 netns "$ns1" >
4848 exit $ksft_skip
4949fi
5050ip link add veth1 netns " $nsrouter " type veth peer name eth0 netns " $ns2 "
51+ ip link add veth2 netns " $nsrouter " type veth peer name eth0 netns " $ns3 "
5152
5253ip -net " $nsrouter " link set veth0 up
5354ip -net " $nsrouter " addr add 10.0.1.1/24 dev veth0
@@ -57,8 +58,13 @@ ip -net "$nsrouter" link set veth1 up
5758ip -net " $nsrouter " addr add 10.0.2.1/24 dev veth1
5859ip -net " $nsrouter " addr add dead:2::1/64 dev veth1 nodad
5960
61+ ip -net " $nsrouter " link set veth2 up
62+ ip -net " $nsrouter " addr add 10.0.3.1/24 dev veth2
63+ ip -net " $nsrouter " addr add dead:3::1/64 dev veth2 nodad
64+
6065ip -net " $ns1 " link set eth0 up
6166ip -net " $ns2 " link set eth0 up
67+ ip -net " $ns3 " link set eth0 up
6268
6369ip -net " $ns1 " addr add 10.0.1.99/24 dev eth0
6470ip -net " $ns1 " addr add dead:1::99/64 dev eth0 nodad
@@ -70,6 +76,11 @@ ip -net "$ns2" addr add dead:2::99/64 dev eth0 nodad
7076ip -net " $ns2 " route add default via 10.0.2.1
7177ip -net " $ns2 " route add default via dead:2::1
7278
79+ ip -net " $ns3 " addr add 10.0.3.99/24 dev eth0
80+ ip -net " $ns3 " addr add dead:3::99/64 dev eth0 nodad
81+ ip -net " $ns3 " route add default via 10.0.3.1
82+ ip -net " $ns3 " route add default via dead:3::1
83+
7384load_ruleset () {
7485 local name=$1
7586 local prio=$2
473484 check_output_files " $TMPINPUT " " $TMPFILE1 " " sctp output"
474485}
475486
487+ udp_listener_ready ()
488+ {
489+ ss -S -N " $1 " -uln -o " sport = :12345" | grep -q 12345
490+ }
491+
492+ output_files_written ()
493+ {
494+ test -s " $1 " && test -s " $2 "
495+ }
496+
497+ test_udp_ct_race ()
498+ {
499+ ip netns exec " $nsrouter " nft -f /dev/stdin << EOF
500+ flush ruleset
501+ table inet udpq {
502+ chain prerouting {
503+ type nat hook prerouting priority dstnat - 5; policy accept;
504+ ip daddr 10.6.6.6 udp dport 12345 counter dnat to numgen inc mod 2 map { 0 : 10.0.2.99, 1 : 10.0.3.99 }
505+ }
506+ chain postrouting {
507+ type filter hook postrouting priority srcnat - 5; policy accept;
508+ udp dport 12345 counter queue num 12
509+ }
510+ }
511+ EOF
512+ :> " $TMPFILE1 "
513+ :> " $TMPFILE2 "
514+
515+ timeout 10 ip netns exec " $ns2 " socat UDP-LISTEN:12345,fork OPEN:" $TMPFILE1 " ,trunc &
516+ local rpid1=$!
517+
518+ timeout 10 ip netns exec " $ns3 " socat UDP-LISTEN:12345,fork OPEN:" $TMPFILE2 " ,trunc &
519+ local rpid2=$!
520+
521+ ip netns exec " $nsrouter " ./nf_queue -q 12 -d 1000 &
522+ local nfqpid=$!
523+
524+ busywait " $BUSYWAIT_TIMEOUT " udp_listener_ready " $ns2 "
525+ busywait " $BUSYWAIT_TIMEOUT " udp_listener_ready " $ns3 "
526+ busywait " $BUSYWAIT_TIMEOUT " nf_queue_wait " $nsrouter " 12
527+
528+ # Send two packets, one should end up in ns1, other in ns2.
529+ # This is because nfqueue will delay packet for long enough so that
530+ # second packet will not find existing conntrack entry.
531+ echo " Packet 1" | ip netns exec " $ns1 " socat STDIN UDP-DATAGRAM:10.6.6.6:12345,bind=0.0.0.0:55221
532+ echo " Packet 2" | ip netns exec " $ns1 " socat STDIN UDP-DATAGRAM:10.6.6.6:12345,bind=0.0.0.0:55221
533+
534+ busywait 10000 output_files_written " $TMPFILE1 " " $TMPFILE2 "
535+
536+ kill " $nfqpid "
537+
538+ if ! ip netns exec " $nsrouter " bash -c ' conntrack -L -p udp --dport 12345 2>/dev/null | wc -l | grep -q "^1"' ; then
539+ echo " FAIL: Expected One udp conntrack entry"
540+ ip netns exec " $nsrouter " conntrack -L -p udp --dport 12345
541+ ret=1
542+ fi
543+
544+ if ! ip netns exec " $nsrouter " nft delete table inet udpq; then
545+ echo " FAIL: Could not delete udpq table"
546+ ret=1
547+ return
548+ fi
549+
550+ NUMLINES1=$( wc -l < " $TMPFILE1 " )
551+ NUMLINES2=$( wc -l < " $TMPFILE2 " )
552+
553+ if [ " $NUMLINES1 " -ne 1 ] || [ " $NUMLINES2 " -ne 1 ]; then
554+ ret=1
555+ echo " FAIL: uneven udp packet distribution: $NUMLINES1 $NUMLINES2 "
556+ echo -n " $TMPFILE1 : " ; cat " $TMPFILE1 "
557+ echo -n " $TMPFILE2 : " ; cat " $TMPFILE2 "
558+ return
559+ fi
560+
561+ echo " PASS: both udp receivers got one packet each"
562+ }
563+
476564test_queue_removal ()
477565{
478566 read tainted_then < /proc/sys/kernel/tainted
512600ip netns exec " $nsrouter " sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
513601ip netns exec " $nsrouter " sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
514602ip netns exec " $nsrouter " sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
603+ ip netns exec " $nsrouter " sysctl net.ipv4.conf.veth2.forwarding=1 > /dev/null
515604
516605load_ruleset " filter" 0
517606
@@ -549,6 +638,7 @@ test_tcp_localhost_connectclose
549638test_tcp_localhost_requeue
550639test_sctp_forward
551640test_sctp_output
641+ test_udp_ct_race
552642
553643# should be last, adds vrf device in ns1 and changes routes
554644test_icmp_vrf
0 commit comments