Skip to content

feat(enhancement): resolve the problem of udp asymmetric routing#2570

Open
Micbetter wants to merge 1 commit into
eclipse-zenoh:mainfrom
Micbetter:feat/udp_asymmetric_routing
Open

feat(enhancement): resolve the problem of udp asymmetric routing#2570
Micbetter wants to merge 1 commit into
eclipse-zenoh:mainfrom
Micbetter:feat/udp_asymmetric_routing

Conversation

@Micbetter
Copy link
Copy Markdown

@Micbetter Micbetter commented Apr 15, 2026

Description

This PR adds the sender-side support for IP_PKTINFO (and IPV6_PKTINFO) in the zenoh-link-udp module on Unix platforms.

What does this PR do?

  1. Adds send_with_src_inner to pktinfo_unix.rs, utilizing libc::sendmsg to inject IP_PKTINFO (or IPV6_PKTINFO) into the ancillary data (cmsg) of outgoing UDP packets.
  2. Ensures the cmsg buffer is efficiently stack-allocated using a compile-time computed CMSG_BUF_SIZE to avoid heap allocations in the hot path.
  3. Exposes a new send_to(buffer, dst_addr, src_addr) API in PktInfoUdpSocket and gracefully falls back to the standard send_to on non-Unix platforms.
  4. Updates LinkUnicastUdpUnconnected in unicast.rs to leverage this new API, ensuring that unconnected UDP sockets (e.g., those listening on 0.0.0.0 or [::]) reply using the exact local IP address on which the incoming packet was received.

Why is this change needed?

Prior to this PR, Zenoh's UDP link successfully utilized IP_PKTINFO via recvmsg to determine the specific local IP address a packet arrived on. However, when replying, Zenoh fell back to the standard UdpSocket::send_to(), ignoring the captured local IP.

This created a severe issue known as udp asymmetric routing in multi-homed environments (e.g., a node with both eth0 and wlan0 listening on 0.0.0.0).
When a client connected to the server's wlan0 IP, the server would often reply via eth0 due to OS routing table defaults, causing the reply packet to bear the eth0 source IP. Because the client's socket was connect()ed to the wlan0 IP, the client's OS kernel would strictly drop the mismatching reply packet.


🏷️ Label-Based Checklist

Based on the labels applied to this PR, please complete these additional requirements:

Labels: bug

🐛 Bug Fix Requirements

Since this PR is labeled as a bug fix, please ensure:

  • Root cause documented - Explain what caused the bug in the PR description
  • Reproduction test added - Test that fails on main branch without the fix
  • Test passes with fix - The reproduction test passes with your changes
  • Regression prevention - Test will catch if this bug reoccurs in the future
  • Fix is minimal - Changes are focused only on fixing the bug
  • Related bugs checked - Verified no similar bugs exist in related code

Why this matters: Bugs without tests often reoccur.

Instructions:

  1. Check off items as you complete them (change - [ ] to - [x])
  2. The PR checklist CI will verify these are completed

This checklist updates automatically when labels change, but preserves your checked boxes.

@oteffahi oteffahi added enhancement Existing things could work better bug Something isn't working and removed enhancement Existing things could work better labels Apr 15, 2026
@Micbetter
Copy link
Copy Markdown
Author

Hi @oteffahi, Adding tests to reproduce this bug is not easily in a standard CI environment, because we require a multi-IP host. Do you have any suggestions on how to approach the reproduction test for this?

@oteffahi
Copy link
Copy Markdown
Contributor

oteffahi commented Apr 21, 2026

Hi @oteffahi, Adding tests to reproduce this bug is not easily in a standard CI environment, because we require a multi-IP host. Do you have any suggestions on how to approach the reproduction test for this?

Correct me if I'm wrong, I believe the requirements are the same as for binding tests, which use zenoh_util::net::get_ipv4_ipaddrs(None) to get IP addresses of non-loopback interfaces of the runner.

@DenisBiryukov91 DenisBiryukov91 requested a review from Copilot April 28, 2026 16:16
@mdyring
Copy link
Copy Markdown

mdyring commented May 8, 2026

Just dropping a note there that IP_PKTINFO will need to be handled differently for Linux and FreeBSD similar to PR #2087.

Specifically this commit: 678c864

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants