Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions io/zenoh-links/zenoh-link-udp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl LocatorInspector for UdpLocatorInspector {
pub mod config {
pub const UDP_MULTICAST_IFACE: &str = "iface";
pub const UDP_MULTICAST_JOIN: &str = "join";
pub const UDP_MULTICAST_TTL: &str = "ttl";
}

pub async fn get_udp_addrs(address: Address<'_>) -> ZResult<impl Iterator<Item = SocketAddr>> {
Expand Down
30 changes: 29 additions & 1 deletion io/zenoh-links/zenoh-link-udp/src/multicast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ impl LinkManagerMulticastUdp {
.map_err(|e| zerror!("{}: {}", mcast_addr, e))?;
}

// Bind the socket: let's bing to the unspecified address so we can join and read
// Bind the socket: let's bind to the unspecified address so we can join and read
// from multiple multicast groups.
let bind_mcast_addr = match mcast_addr.ip() {
IpAddr::V4(_) => IpAddr::V4(Ipv4Addr::UNSPECIFIED),
Expand Down Expand Up @@ -321,6 +321,34 @@ impl LinkManagerMulticastUdp {
// https://docs.rs/tokio/latest/tokio/net/struct.UdpSocket.html#notes
mcast_sock.set_nonblocking(true)?;

// If TTL is specified, add set the socket's TTL
if let Some(ttl_str) = config.get(UDP_MULTICAST_TTL) {
let ttl = match ttl_str.parse::<u32>() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IPv6 hop limit is not yet supported in the Rust library.
I've opened rust-lang/rust#138744 to address the issue.

In the meanwhile, I suggest to simply log a warning in the case of an IPv6 socket.

        // If TTL is specified, add set the socket's TTL
        if let Some(ttl_str) = config.get(UDP_MULTICAST_TTL) {
            match &local_addr {
                IpAddr::V4(_) => {
                    let ttl = match ttl_str.parse::<u32>() {
                        Ok(ttl) => ttl,
                        Err(e) => bail!("Can not parse TTL '{}' to a u32: {}", ttl_str, e),
                    };

                    ucast_sock.set_multicast_ttl_v4(ttl).map_err(|e| {
                        zerror!("Can not set multicast TTL {} on {}: {}", ttl, mcast_addr, e)
                    })?;
                }
                IpAddr::V6(_) => {
                    tracing::warn!(
                            "UDP multicast hop limit not supported for v6 socket: {}. See https://github.com/rust-lang/rust/pull/138744.",
                            mcast_addr
                        );
                }
            }
        }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't sure how tokio handled this under the hood, I just saw is said it "may not have any effect" and figured it was a shot in the dark to attempt to set the TTL.

Sounds great, I will make this change. Thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have taken your changes, feel free to re-review that they were taken correctly.
It passed a local build for me.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good, thanks!

Ok(ttl) => ttl,
Err(e) => bail!("Can not parse TTL '{}' to a u32: {}", ttl_str, e),
};

match &local_addr {
IpAddr::V4(_) => {
ucast_sock
.set_multicast_ttl_v4(ttl)
.map_err(|e| zerror!("{}: {}", mcast_addr, e))?;
}
IpAddr::V6(_) => match zenoh_util::net::get_index_of_interface(local_addr) {
Ok(_) => {
tracing::warn!(
"set_multicast_ttl_v4 on v6 socket (may have no effect): {}",
mcast_addr
);
ucast_sock
.set_multicast_ttl_v4(ttl)
.map_err(|e| zerror!("{}: {}", mcast_addr, e))?
}
Err(e) => bail!("{}: {}", mcast_addr, e),
},
}
}

// Build the tokio multicast UdpSocket
let mcast_sock = UdpSocket::from_std(mcast_sock.into())?;

Expand Down