From b4afd0bffbd44767cf99d0a02d01cea3fc4607c3 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Sat, 19 Apr 2025 21:46:58 +1000 Subject: [PATCH] refactor(eBPF): reduce size of maps (#8849) Whilst developing the eBPF module for the relay, I needed to manually add padding within the key and value structs used in the maps in order for the kernel to be able to correctly retrieve the data. For some reason, this seems no longer necessary as the integration test now passes without this as well. Being able to remove the padding drastically reduces the size of these maps for the current number of entries that we allow. This brings the overall memory usage of the relay down. Resolves: #8682 --- rust/relay/ebpf-shared/src/lib.rs | 76 ------------------------- rust/relay/ebpf-turn-router/src/main.rs | 7 ++- 2 files changed, 5 insertions(+), 78 deletions(-) diff --git a/rust/relay/ebpf-shared/src/lib.rs b/rust/relay/ebpf-shared/src/lib.rs index 2f3da6486..d6a802f23 100644 --- a/rust/relay/ebpf-shared/src/lib.rs +++ b/rust/relay/ebpf-shared/src/lib.rs @@ -1,6 +1,5 @@ //! Shared data structures between the kernel and userspace. //! -//! To learn more about the layout requirements of these structs, read . //! In order to make sure endianness is correct, we store everything in byte-arrays in _big-endian_ order. //! This makes it easier to directly take the values from the network buffer and use them in these structs (and vice-versa). @@ -13,15 +12,8 @@ use core::net::{Ipv4Addr, Ipv6Addr}; #[cfg_attr(feature = "std", derive(Debug))] pub struct ClientAndChannelV4 { ipv4_address: [u8; 4], - _padding_ipv4_address: [u8; 4], - port: [u8; 2], - _padding_port: [u8; 6], - channel: [u8; 2], - _padding_channel: [u8; 6], - - _padding_struct: [u8; 40], } #[repr(C)] @@ -29,29 +21,16 @@ pub struct ClientAndChannelV4 { #[cfg_attr(feature = "std", derive(Debug))] pub struct ClientAndChannelV6 { ipv6_address: [u8; 16], - port: [u8; 2], - _padding_port: [u8; 6], - channel: [u8; 2], - _padding_channel: [u8; 6], - - _padding_struct: [u8; 32], } impl ClientAndChannelV4 { pub fn new(ipv4_address: Ipv4Addr, port: u16, channel: u16) -> Self { Self { ipv4_address: ipv4_address.octets(), - _padding_ipv4_address: [0u8; 4], - port: port.to_be_bytes(), - _padding_port: [0u8; 6], - channel: channel.to_be_bytes(), - _padding_channel: [0u8; 6], - - _padding_struct: [0u8; 40], } } @@ -76,14 +55,8 @@ impl ClientAndChannelV6 { pub fn new(ipv6_address: Ipv6Addr, port: u16, channel: u16) -> Self { Self { ipv6_address: ipv6_address.octets(), - port: port.to_be_bytes(), - _padding_port: [0u8; 6], - channel: channel.to_be_bytes(), - _padding_channel: [0u8; 6], - - _padding_struct: [0u8; 32], } } @@ -109,15 +82,8 @@ impl ClientAndChannelV6 { #[cfg_attr(feature = "std", derive(Debug))] pub struct PortAndPeerV4 { ipv4_address: [u8; 4], - _padding_ipv4_address: [u8; 4], - allocation_port: [u8; 2], - _padding_allocation_port: [u8; 6], - peer_port: [u8; 2], - _padding_dest_port: [u8; 6], - - _padding_struct: [u8; 40], } #[repr(C)] @@ -127,27 +93,15 @@ pub struct PortAndPeerV6 { ipv6_address: [u8; 16], allocation_port: [u8; 2], - _padding_allocation_port: [u8; 6], - peer_port: [u8; 2], - _padding_dest_port: [u8; 6], - - _padding_struct: [u8; 32], } impl PortAndPeerV4 { pub fn new(ipv4_address: Ipv4Addr, allocation_port: u16, peer_port: u16) -> Self { Self { ipv4_address: ipv4_address.octets(), - _padding_ipv4_address: [0u8; 4], - allocation_port: allocation_port.to_be_bytes(), - _padding_allocation_port: [0u8; 6], - peer_port: peer_port.to_be_bytes(), - _padding_dest_port: [0u8; 6], - - _padding_struct: [0u8; 40], } } @@ -174,12 +128,7 @@ impl PortAndPeerV6 { ipv6_address: ipv6_address.octets(), allocation_port: allocation_port.to_be_bytes(), - _padding_allocation_port: [0u8; 6], - peer_port: peer_port.to_be_bytes(), - _padding_dest_port: [0u8; 6], - - _padding_struct: [0u8; 32], } } @@ -285,28 +234,3 @@ mod userspace { unsafe impl aya::Pod for Config {} } - -#[cfg(all(test, feature = "std"))] -mod tests { - use super::*; - - #[test] - fn client_and_channel_v4_has_size_64() { - assert_eq!(std::mem::size_of::(), 64) - } - - #[test] - fn port_and_peer_v4_has_size_64() { - assert_eq!(std::mem::size_of::(), 64) - } - - #[test] - fn client_and_channel_v6_has_size_64() { - assert_eq!(std::mem::size_of::(), 64) - } - - #[test] - fn port_and_peer_v6_has_size_64() { - assert_eq!(std::mem::size_of::(), 64) - } -} diff --git a/rust/relay/ebpf-turn-router/src/main.rs b/rust/relay/ebpf-turn-router/src/main.rs index 292d93516..bbdf387a8 100644 --- a/rust/relay/ebpf-turn-router/src/main.rs +++ b/rust/relay/ebpf-turn-router/src/main.rs @@ -415,7 +415,7 @@ mod tests { const HASH_MAP_OVERHEAD: f32 = 1.5; #[test] - fn hashmaps_are_less_than_100_mb() { + fn hashmaps_are_less_than_11_mb() { let ipv4_datatypes = core::mem::size_of::() + core::mem::size_of::(); let ipv6_datatypes = @@ -427,6 +427,9 @@ mod tests { let total_map_size = (ipv4_map_size + ipv6_map_size) * 2_f32; let total_map_size_mb = total_map_size / 1024_f32 / 1024_f32; - assert!(total_map_size_mb < 100_f32); + assert!( + total_map_size_mb < 11_f32, + "Total map size = {total_map_size_mb} MB" + ); } }