1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
//
// Copyright (c) 2023 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
// ZettaScale Zenoh Team, <zenoh@zettascale.tech>
//
//! ⚠️ WARNING ⚠️
//!
//! This crate is intended for Zenoh's internal use.
//!
//! [Click here for Zenoh's documentation](../zenoh/index.html)
mod multicast;
mod unicast;
use async_std::net::ToSocketAddrs;
use async_trait::async_trait;
pub use multicast::*;
use std::net::SocketAddr;
pub use unicast::*;
use zenoh_core::zconfigurable;
use zenoh_link_commons::LocatorInspector;
use zenoh_protocol::core::{endpoint::Address, Locator};
use zenoh_result::{zerror, ZResult};
// NOTE: In case of using UDP in high-throughput scenarios, it is recommended to set the
// UDP buffer size on the host to a reasonable size. Usually, default values for UDP buffers
// size are undersized. Setting UDP buffers on the host to a size of 4M can be considered
// as a safe choice.
// Usually, on Linux systems this could be achieved by executing:
// $ sysctl -w net.core.rmem_max=4194304
// $ sysctl -w net.core.rmem_default=4194304
// Maximum MTU (UDP PDU) in bytes.
// NOTE: The UDP field size sets a theoretical limit of 65,535 bytes (8 byte header + 65,527 bytes of
// data) for a UDP datagram. However the actual limit for the data length, which is imposed by
// the underlying IPv4 protocol, is 65,507 bytes (65,535 − 8 byte UDP header − 20 byte IP header).
// Although in IPv6 it is possible to have UDP datagrams of size greater than 65,535 bytes via
// IPv6 Jumbograms, its usage in Zenoh is discouraged unless the consequences are very well
// understood.
const UDP_MAX_MTU: u16 = 65_507;
pub const UDP_LOCATOR_PREFIX: &str = "udp";
#[cfg(any(target_os = "linux", target_os = "windows"))]
// Linux default value of a maximum datagram size is set to UDP MAX MTU.
const UDP_MTU_LIMIT: u16 = UDP_MAX_MTU;
#[cfg(target_os = "macos")]
// Mac OS X default value of a maximum datagram size is set to 9216 bytes.
const UDP_MTU_LIMIT: u16 = 9_216;
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
const UDP_MTU_LIMIT: u16 = 8_192;
zconfigurable! {
// Default MTU (UDP PDU) in bytes.
static ref UDP_DEFAULT_MTU: u16 = UDP_MTU_LIMIT;
// Amount of time in microseconds to throttle the accept loop upon an error.
// Default set to 100 ms.
static ref UDP_ACCEPT_THROTTLE_TIME: u64 = 100_000;
}
#[derive(Default, Clone, Copy)]
pub struct UdpLocatorInspector;
#[async_trait]
impl LocatorInspector for UdpLocatorInspector {
fn protocol(&self) -> &str {
UDP_LOCATOR_PREFIX
}
async fn is_multicast(&self, locator: &Locator) -> ZResult<bool> {
let is_multicast = get_udp_addrs(locator.address())
.await?
.any(|x| x.ip().is_multicast());
Ok(is_multicast)
}
}
pub mod config {
pub const UDP_MULTICAST_SRC_IFACE: &str = "src_iface";
}
pub async fn get_udp_addrs(address: Address<'_>) -> ZResult<impl Iterator<Item = SocketAddr>> {
let iter = address
.as_str()
.to_socket_addrs()
.await
.map_err(|e| zerror!("{}", e))?;
Ok(iter)
}
pub(crate) fn socket_addr_to_udp_locator(addr: &SocketAddr) -> Locator {
Locator::new(UDP_LOCATOR_PREFIX, addr.to_string(), "").unwrap()
}