Expand description
UDP through the worker’s ring: batched receive, GSO send.
Receive is one multishot recvmsg per socket feeding from a registered
provided-buffer ring: each completion consumes one whole buffer, so every
buffer is sized for the worst case (a full UDP_GRO coalesce plus the
recvmsg header). Incremental consumption (IOU_PBUF_RING_INC) looked like
a better fit for GRO’s 100-byte-to-64KB completion variance, but it cannot
back a multishot recvmsg: the kernel releases an incremental buffer only
at exactly zero bytes left, and io_recvmsg_prep_multishot fails with
EFAULT the moment a leftover tail is smaller than the recvmsg header.
A completed buffer is handed out as a Packet and returns to the kernel
once every packet borrowing it drops.
Send stages datagrams in a pool of buffers owned by id and released
explicitly on completion, the shape SENDMSG_ZC’s deferred-reclaim NOTIF
model needs later. Every GSO sendmsg carries its UDP_SEGMENT control
message explicitly; the socket default is never relied on. The ECN mark
rides beside it as IP_TOS or IPV6_TCLASS, and receives read the mark
back through IP_RECVTOS and IPV6_RECVTCLASS, so a QUIC stack’s ECN
validation sees what the network did to its packets.
Both pools are queues of concurrent operations, not byte budgets: one send
buffer holds one GSO train and one receive buffer holds one completion,
however little either carries. So the depth a socket needs is set by how
many of its connections want the socket at once, which no caller can
predict. Both start small and grow on demand when they starve, bounded by
the ceilings in Config; a pool never shrinks, so it settles at the
socket’s high-water concurrency and the memory comes back when it drops.
The gro/gso/multishot toggles in Config exist for the ablation
benchmarks; production callers keep the defaults (all on).
Structs§
- Config
- How a socket uses the ring. The defaults are the production path; the toggles exist so the benchmarks can ablate one mechanism at a time.
- Packet
- One receive: a possibly GRO-coalesced run of datagrams from one source.
- Socket
- A UDP socket driven by a
crate::Worker. - Transmit
- What one
TxBuf::sendputs on the wire. - TxBuf
- A checked-out send-staging buffer: fill it, then
sendit.