Skip to content

Increase UDP socket receive buffer to prevent large message loss#402

Open
alvgaona wants to merge 1 commit intoAtostek:masterfrom
alvgaona:fix/recv-buf
Open

Increase UDP socket receive buffer to prevent large message loss#402
alvgaona wants to merge 1 commit intoAtostek:masterfrom
alvgaona:fix/recv-buf

Conversation

@alvgaona
Copy link
Contributor

Problem

RustDDS silently drops large DDS messages (e.g., sensor_msgs/Image at ~1200p or above) because the OS-default UDP receive buffer is too small to absorb fragment bursts. When a publisher (e.g., CycloneDDS) sends a large message, it gets fragmented into thousands of small UDP packets (~1 KB each). These arrive in a burst that overflows the default receive buffer (~786 KB on macOS, ~208 KB on Linux). With BestEffort QoS — standard for image topics — lost fragments are never retransmitted, so the message is silently lost.

Fix

Set SO_RCVBUF to 8 MB on all UDP listener sockets. The buffer size is configurable via DomainParticipantBuilder::socket_receive_buffer_size().

On macOS, the per-socket buffer is capped at kern.ipc.maxsockbuf (8 MB by default), which limits reliable reception to ~8 MB payloads. On Linux, users can raise net.core.rmem_max for larger payloads (e.g., 4K uncompressed images).

Testing

Tested with a ROS 2 camera node publishing sensor_msgs/Image over CycloneDDS:

Resolution Payload Before After
320×240 230 KB
640×480 920 KB
1100×540 1.8 MB
1200×540 1.9 MB
1920×1080 6.2 MB
3840×2160 24.9 MB ✗ (macOS buffer cap)

For high-resolution images those must be compressed. Apparently in Linux the max_buf_size is more generous than macOS and would allow raw 4K streams.

@alvgaona alvgaona force-pushed the fix/recv-buf branch 2 times, most recently from 4252ddd to 317e0dd Compare March 11, 2026 00:50
RustDDS used OS-default UDP receive buffers (~786 KB on macOS, ~208 KB
on Linux), which caused silent packet loss when receiving large
fragmented DDS messages (e.g., 1080p images at ~6 MB). The buffer
overflowed during fragment bursts, and with BestEffort QoS, lost
fragments are never retransmitted.

Set SO_RCVBUF to 8 MB by default (configurable via
DomainParticipantBuilder::socket_receive_buffer_size). On Linux,
users may need to raise net.core.rmem_max for larger payloads.
This matches the approach used by CycloneDDS and FastDDS.
@alvgaona
Copy link
Contributor Author

@jhelovuo more enhancements. Let me know what you think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant