From 2559bb7d67bc9b8dbf8fe192efc927e84ffdbd09 Mon Sep 17 00:00:00 2001 From: Wesley Rosenblum <55108558+WesleyRosenblum@users.noreply.github.com> Date: Fri, 28 Jul 2023 16:45:39 -0400 Subject: [PATCH] fix(s2n-quic-transport): handle MaxMtu smaller than Base PLPMTU (#1893) --- quic/s2n-quic-core/src/path/mod.rs | 14 +++++++++----- quic/s2n-quic-transport/src/path/mtu.rs | 15 +++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/quic/s2n-quic-core/src/path/mod.rs b/quic/s2n-quic-core/src/path/mod.rs index ca0b109ed5..94b91bc894 100644 --- a/quic/s2n-quic-core/src/path/mod.rs +++ b/quic/s2n-quic-core/src/path/mod.rs @@ -36,14 +36,18 @@ pub const UDP_HEADER_LEN: u16 = 8; pub const IPV4_MIN_HEADER_LEN: u16 = 20; // IPv6 header is always 40 bytes, plus extensions pub const IPV6_MIN_HEADER_LEN: u16 = 40; -#[cfg(feature = "ipv6")] -const IP_MIN_HEADER_LEN: u16 = IPV6_MIN_HEADER_LEN; -#[cfg(not(feature = "ipv6"))] -const IP_MIN_HEADER_LEN: u16 = IPV4_MIN_HEADER_LEN; // The minimum allowed Max MTU is the minimum UDP datagram size of 1200 bytes plus // the UDP header length and minimal IP header length -const MIN_ALLOWED_MAX_MTU: u16 = MINIMUM_MTU + UDP_HEADER_LEN + IP_MIN_HEADER_LEN; +const fn const_min(a: u16, b: u16) -> u16 { + if a < b { + a + } else { + b + } +} +const MIN_ALLOWED_MAX_MTU: u16 = + MINIMUM_MTU + UDP_HEADER_LEN + const_min(IPV4_MIN_HEADER_LEN, IPV6_MIN_HEADER_LEN); // Initial PTO backoff multiplier is 1 indicating no additional increase to the backoff. pub const INITIAL_PTO_BACKOFF: u32 = 1; diff --git a/quic/s2n-quic-transport/src/path/mtu.rs b/quic/s2n-quic-transport/src/path/mtu.rs index 54f22103b4..790290b821 100644 --- a/quic/s2n-quic-transport/src/path/mtu.rs +++ b/quic/s2n-quic-transport/src/path/mtu.rs @@ -135,11 +135,8 @@ impl Controller { SocketAddress::IpV4(_) => IPV4_MIN_HEADER_LEN, SocketAddress::IpV6(_) => IPV6_MIN_HEADER_LEN, }; - let max_udp_payload = u16::from(max_mtu) - UDP_HEADER_LEN - min_ip_header_len; - debug_assert!( - max_udp_payload >= BASE_PLPMTU, - "max_udp_payload must be at least {BASE_PLPMTU}" - ); + let max_udp_payload = + (u16::from(max_mtu) - UDP_HEADER_LEN - min_ip_header_len).max(BASE_PLPMTU); // The UDP payload size for the most likely MTU is based on standard Ethernet MTU minus // the minimum length IP headers (without IPv4 options or IPv6 extensions) and UPD header @@ -499,9 +496,11 @@ mod test { } #[test] - #[should_panic] - fn new_max_mtu_too_small() { - new_controller(BASE_PLPMTU + UDP_HEADER_LEN + IPV4_MIN_HEADER_LEN - 1); + fn min_max_mtu() { + // Use an IPv6 address to force a smaller `max_udp_payload` + let addr: SocketAddr = "[::1]:123".parse().unwrap(); + let controller = Controller::new(MaxMtu::MIN, &addr.into()); + assert_eq!(BASE_PLPMTU, controller.plpmtu); } #[test]