mirror of https://github.com/coturn/coturn
Tag:
Branch:
Tree:
master
copilot/fix-1649
debian/buster
debian/buster-backports
debian/master
debian/stretch
debian/stretch-backports
dh2066
fix-oauth
fix_msvc_analyzer
input-validation
libevent.rpm
macos_upgrade
master
move_to_verbose
pristine-tar
sparc64
sparc64-rebase
sparc64-rebase-slim
try-fix-docker
turnbis
upstream/latest
wferi/callback
4.10.0
4.11.0
4.12.0
4.4.5.3
4.4.5.4
4.5.0.1
4.5.0.2
4.5.0.3
4.5.0.4
4.5.0.5
4.5.0.6
4.5.0.7
4.5.0.8
4.5.1.0
4.5.1.1
4.5.1.2
4.5.1.3
4.5.2
4.6.0
4.6.1
4.6.2
4.6.3
4.7.0
4.8.0
4.9.0
debian/4.5.0.2-3
debian/4.5.0.2-3_bpo8+1
debian/4.5.0.3-1
debian/4.5.0.4-1
debian/4.5.0.4-4
debian/4.5.0.5-1
debian/4.5.0.5-1+deb9u1
debian/4.5.0.5-1+deb9u2
debian/4.5.0.5-1+deb9u3
debian/4.5.0.6-1
debian/4.5.0.7-1
debian/4.5.0.8-1
debian/4.5.1.0-1
debian/4.5.1.0-1_bpo9+1
debian/4.5.1.1-1
debian/4.5.1.1-1.1
debian/4.5.1.1-1.1+deb10u1
debian/4.5.1.1-1.1+deb10u2
debian/4.5.1.1-1.2
debian/4.5.1.3-1
debian/4.5.2-1
debian/4.5.2-1_bpo10+1
debian/4.5.2-2
debian/4.5.2-3
docker/4.10.0-r0
docker/4.10.0-r1
docker/4.11.0-r0
docker/4.12.0-r0
docker/4.5.2-r0
docker/4.5.2-r1
docker/4.5.2-r10
docker/4.5.2-r11
docker/4.5.2-r12
docker/4.5.2-r13
docker/4.5.2-r14
docker/4.5.2-r2
docker/4.5.2-r3
docker/4.5.2-r4
docker/4.5.2-r5
docker/4.5.2-r6
docker/4.5.2-r7
docker/4.5.2-r8
docker/4.5.2-r9
docker/4.6.0-r0
docker/4.6.0-r1
docker/4.6.1-r0
docker/4.6.1-r1
docker/4.6.1-r2
docker/4.6.1-r3
docker/4.6.2-r0
docker/4.6.2-r1
docker/4.6.2-r10
docker/4.6.2-r11
docker/4.6.2-r12
docker/4.6.2-r13
docker/4.6.2-r2
docker/4.6.2-r3
docker/4.6.2-r4
docker/4.6.2-r5
docker/4.6.2-r6
docker/4.6.2-r7
docker/4.6.2-r8
docker/4.6.2-r9
docker/4.6.3-r0
docker/4.6.3-r1
docker/4.6.3-r2
docker/4.6.3-r3
docker/4.7.0-r0
docker/4.7.0-r1
docker/4.7.0-r2
docker/4.7.0-r3
docker/4.7.0-r4
docker/4.8.0-r0
docker/4.8.0-r1
docker/4.9.0-r0
upstream/4.0.0.0
upstream/4.0.0.1
upstream/4.0.0.2
upstream/4.0.1.2
upstream/4.0.1.3
upstream/4.1.0.1
upstream/4.1.0.2
upstream/4.1.1.1
upstream/4.1.2.1
upstream/4.2.1.2
upstream/4.2.2.2
upstream/4.2.3.1
upstream/4.3.1.1
upstream/4.3.1.2
upstream/4.3.1.3
upstream/4.3.2.1
upstream/4.3.2.2
upstream/4.3.3.1
upstream/4.4.1.1
upstream/4.4.1.2
upstream/4.4.2.1
upstream/4.4.2.2
upstream/4.4.2.3
upstream/4.4.4.1
upstream/4.4.4.2
upstream/4.4.5.1
upstream/4.4.5.2
upstream/4.4.5.3
upstream/4.4.5.4
upstream/4.5.0.1
upstream/4.5.0.2
upstream/4.5.0.3
upstream/4.5.0.4
upstream/4.5.0.5
upstream/4.5.0.6
upstream/4.5.0.7
upstream/4.5.0.8
upstream/4.5.1.0
upstream/4.5.1.1
upstream/4.5.1.3
upstream/4.5.2
${ noResults }
2 Commits (master)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
b17f5c482f
|
Add --udp-sendmmsg-log to observe egress sendmmsg/UDP-GSO batching (#1927)
## Summary Adds a Linux-only `--udp-sendmmsg-log` flag (mirroring `--udp-recvmmsg-log`) that logs per-relay-thread **egress** batch statistics every 10 s: flush count, total datagrams, average batch occupancy, UDP-GSO engagement (`gso_flushes`/`gso_datagrams`/`gso_frac`), and a per-flush occupancy histogram. ## Motivation `--multiplex-peer` enables `sendmmsg`/UDP-GSO coalescing on the egress path, but there was no way to see whether it actually coalesces anything. While investigating this I confirmed a non-obvious property worth documenting: - Per-session UDP **client** sockets are children of the listener (`parent_s`), and `udp_send_fd()` returns the shared **listener fd** for all of them. Combined with the `recvmmsg`-driven batch window, relay→client **downlink** sends to *different clients* already coalesce into one `sendmmsg` on the listener fd — the listener fd is effectively a shared client-facing send socket. (In non-multiplex mode each allocation has its own relay socket, so a `recvmmsg` drain spans only one session and the downlink batch is a singleton — cross-client batching genuinely requires `--multiplex-peer`.) - UDP-GSO only engages when destination **and** segment size match across a batch, so at low per-flow packet rates (VoIP-style, tens of pps per flow) it rarely fires. This flag makes both effects measurable instead of assumed. ## Example Captured under a `--multiplex-peer --udp-gso` load: ``` udp-sendmmsg stats: flushes=21 datagrams=27 avg_batch=1.29 gso_flushes=0 \ gso_datagrams=0 gso_frac=0.000 hist_1=17 hist_2=2 hist_3_4=2 hist_5_8=0 hist_9_16=0 hist_17_32=0 ``` - `avg_batch` — mean datagrams per flush (1.0 = no coalescing) - `gso_frac` — fraction of datagrams sent via UDP-GSO (~0 = GSO not earning its keep) - `hist_*` — per-flush occupancy histogram Both rise with aggregate pps and sit near the floor on lightly loaded servers. ## Implementation - Counters on `ioa_engine` (behind `#if defined(__linux__)`), bumped once per flush in `udp_sendmmsg_flush()` and once per `recvmmsg` call — no per-datagram cost. - New `--udp-sendmmsg-log` CLI flag + 10 s periodic logger in the engine timer, mirroring the existing recvmmsg stats path. - Docs: a new "Egress Batching (sendmmsg / UDP-GSO) and Observability" section in `docs/multiplex-peer.md`. ## Testing - macOS: build + `ctest` (6/6) + `run_tests.sh` pass (instrumentation is `#if __linux__`, validating flag plumbing + the non-Linux stub path). - Linux (clean Ubuntu 24.04 Docker): build + `ctest` (4/4) + `run_tests.sh` / `run_tests_conf.sh` / `run_tests_multiplex_peer.sh` pass, and a `--multiplex-peer --udp-gso --udp-sendmmsg-log` load run emitted the stats line above. |
22 hours ago |
|
|
e0c37a3aa0
|
Multiplexpeer (#1916)
## Summary Adds **`--multiplex-peer`**, a non-standard relay mode that replaces the per-allocation peer-side port bind with **one shared IPv4+IPv6 UDP socket pair per relay thread**. Sessions are demultiplexed by exact peer IP:port in a per-thread `mp_table`. This lifts the ~16 k allocation cap that the default 49152-65535 relay port range imposes, and dramatically reduces kernel-level UDP receive-buffer drops under high pps. Design and trade-offs: [docs/multiplex-peer.md](docs/multiplex-peer.md). ## What changes ### Server (turnserver) - **`--multiplex-peer`** (cross-platform) — enable the shared per-thread relay sockets. Replaces the per-session port bind. Implies sendmmsg batching on Linux and default-enables `--udp-recvmmsg` (override with `--udp-recvmmsg=0`). Incompatible with EVEN-PORT — those Allocates are rejected with 400. - **`--multiplex-peer-port <port>`** (cross-platform, default 3480) — base port; thread `i` binds `<base>+2i` (IPv4) and `<base>+2i+1` (IPv6). A 4-thread server consumes 8 ports. - **`--udp-gso`** (Linux-only CLI) — UDP-GSO (`UDP_SEGMENT` cmsg) on the relay send path. Requires `--multiplex-peer` (which is what enables the sendmmsg batching GSO piggybacks on); passing `--udp-gso` alone is a silent no-op. - **CLI surface tightened**: `--udp-recvmmsg`, `--udp-recvmmsg-log`, `--udp-gso` and their fields are now `#if defined(__linux__)` — absent from `--help`, rejected with `unrecognized option`, and the code paths compile out on macOS/Windows. - **Windows portability**: `SO_REUSEPORT` in `mp_open_socket` wrapped in `#ifdef` (MSVC's Winsock doesn't define it; REUSEPORT was defensive anyway because the per-thread port layout is unique by construction). - **`--sock-buf-size` honoured at startup**: the shared multiplex-peer relay socket now calls `set_ioa_socket_buf_size` in `mp_open_socket` so the configured rcvbuf is in effect from the moment the socket exists, not deferred to the first Allocate. ### turnutils_uclient (loadgen) - **`--no-even-port`** — force `ep = -1` on Allocate. The default path randomly attaches EVEN-PORT (with no-R bit) even under `-c`, which `--multiplex-peer` strictly rejects with 400; this flag makes alloc-flood runs against multiplex-peer deterministic. - **Legacy `timer_handler` now wraps the per-tick send batch with `uclient_send_batch_begin/_end`** — without this, runs with `--sender-threads 0` (the default for `-m < 4`) silently fell through every send to plain `send(2)`. strace A/B: 205 k `sendto` → 61 k `sendmsg` (GSO) + 4 k `sendmmsg` + small `sendto` residual for control. ## Measured impact (3-droplet DigitalOcean, c-4 / 4 vCPU, 8 concurrent UDP streams, 45 s) | | baseline | `--udp-recvmmsg` | `--multiplex-peer` | `--multiplex-peer --udp-gso` | |---|---:|---:|---:|---:| | Server NIC rx pps (UDP relay both legs) | 350 k | 334 k | 326 k | 294 k | | Server `UdpInDatagrams` pps | 279 k | 292 k | 300 k | 294 k | | **Server `UdpRcvbufErrors` pps** | **71 k** | 42 k | 26 k | **0.3 k (−99.6 %)** | | **`turnserver` process CPU** | **387 %** | 205 % | 283 % | **133 % (−65 %)** | | Server host idle | 22 % | 49 % | 41 % | **68 %** | Same loadgen-side packet rate (~2 M pps reported by uclient `send_pps` after the legacy-path batching fix). Iteration log: [docs/PerformanceIterationLog.md](docs/PerformanceIterationLog.md). ## Test plan - [x] `ctest --test-dir build` — 3/3 pass (test_ioaddr, test_stun_msg, test_http_server) on macOS + Linux. - [x] `examples/run_tests.sh` — 4 protocols + 4 threaded + load-gen smoke on Linux; 4 protocols on macOS. - [x] `examples/run_tests_conf.sh` — same coverage, conf-driven. - [x] `examples/run_tests_multiplex_peer.sh` — UDP/TCP/TLS/DTLS via `--multiplex-peer --multiplex-peer-port=35000` on macOS + Linux. - [x] Flag matrix smoke on macOS: `--multiplex-peer`, `--multiplex-peer-port=42000`, `--multiplex-peer --udp-gso` (no-op), `uclient --no-even-port`, `uclient --listener-threads N --sender-threads M` — all pass; `--udp-recvmmsg` / `--udp-gso` correctly rejected with `unrecognized option`. - [x] Flag matrix smoke on Linux (Docker): same + `--udp-recvmmsg` accepted, `--multiplex-peer` auto-enables `--udp-recvmmsg`, `--udp-recvmmsg=0` overrides the auto-enable. - [x] Windows compile fix verified — `SO_REUSEPORT` no longer referenced unconditionally. - [x] 3-droplet perf matrix completed; per-hop UDP counters captured. ## Docs updated - New: [docs/multiplex-peer.md](docs/multiplex-peer.md) - [README.turnserver](README.turnserver): full entries for `--multiplex-peer`, `--multiplex-peer-port`, `--udp-gso`; clarified `--udp-recvmmsg` auto-enable semantics. - [README.turnutils](README.turnutils): added `--no-even-port`, plus previously-undocumented `--listener-threads` / `--sender-threads` loadgen pool flags. - [examples/etc/turnserver.conf](examples/etc/turnserver.conf): commented `udp-recvmmsg`, `udp-recvmmsg-log`, `udp-gso`, `multiplex-peer`, `multiplex-peer-port` keys with one-paragraph descriptions and pointer to `docs/multiplex-peer.md`. - Man pages regenerated via `./make-man.sh`. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
2 weeks ago |