Files
Pavel Punsky 3294c714aa Add Linux-only recvmmsg receive path for DTLS/UDP listener (#1852)
## Summary

This change lets the listener batch incoming UDP datagrams when
`--udp-recvmmsg` is enabled, reducing per-packet overhead on busy
listeners while preserving the existing behavior as the default and
fallback path.

## What changed

- add a new `--udp-recvmmsg` runtime flag
- implement a batched UDP receive path in the DTLS listener using
`recvmmsg()`
- reuse packet classification and datagram processing logic across
batched and non-batched receive paths
- reduce buffer/metadata churn by reusing listener-side scratch state
and network buffers
- keep compatibility safeguards by falling back when `recvmmsg()` is
unavailable or unsupported
- expose the setting in admin/CLI configuration output
- update the example test runner to enable the flag on Linux

## Why

The current listener processes UDP datagrams one at a time. On Linux,
`recvmmsg()` allows the server to receive multiple packets per syscall,
which should improve throughput and lower CPU overhead under load for
UDP-heavy traffic.

## Notes

- the feature is opt-in and defaults to disabled
- the implementation is Linux-specific and leaves the existing path
unchanged on other platforms
- the listener still falls back to the legacy receive path if batched
receive is unavailable at runtime

## Testing

- updated `examples/run_tests.sh` to pass `--udp-recvmmsg` on Linux
- validated behavior through the existing listener flow and fallback
handling
2026-04-10 08:56:28 -07:00

66 lines
1.8 KiB
Bash
Executable File

#!/bin/bash
cleanup() {
kill "$turnserver_pid" "$peer_pid" 2>/dev/null
}
trap cleanup EXIT
# Detect cmake build and adjust path
BINDIR="../bin"
if [ ! -f $BINDIR/turnserver ]; then
BINDIR="../build/bin"
fi
TURNSERVER_EXTRA_ARGS=""
if [ "$(uname -s)" = "Linux" ]; then
TURNSERVER_EXTRA_ARGS="--udp-recvmmsg"
echo 'Using TURNSERVER_EXTRA_ARGS="--udp-recvmmsg"'
fi
echo 'Running turnserver'
$BINDIR/turnserver --use-auth-secret --sock-buf-size=1048576 --static-auth-secret=secret --realm=north.gov --allow-loopback-peers $TURNSERVER_EXTRA_ARGS --cert ../examples/ca/turn_server_cert.pem --pkey ../examples/ca/turn_server_pkey.pem > /dev/null &
turnserver_pid="$!"
echo 'Running peer client'
$BINDIR/turnutils_peer -L 127.0.0.1 -L ::1 -L 0.0.0.0 > /dev/null &
peer_pid="$!"
sleep 2
echo 'Running turn client TCP'
$BINDIR/turnutils_uclient -t -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
echo FAIL
exit $?
fi
echo 'Running turn client TLS'
$BINDIR/turnutils_uclient -t -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
echo FAIL
exit $?
fi
echo 'Running turn client UDP'
$BINDIR/turnutils_uclient -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
echo FAIL
exit $?
fi
echo 'Running turn client DTLS'
$BINDIR/turnutils_uclient -S -e 127.0.0.1 -X -g -u user -W secret 127.0.0.1 | grep "start_mclient: tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000" > /dev/null
if [ $? -eq 0 ]; then
echo OK
else
echo FAIL
exit $?
fi
sleep 2