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
This commit is contained in:
Thomas Eizinger
2025-04-19 21:46:58 +10:00
committed by GitHub
parent 5669c83835
commit b4afd0bffb
2 changed files with 5 additions and 78 deletions

View File

@@ -1,6 +1,5 @@
//! Shared data structures between the kernel and userspace.
//!
//! To learn more about the layout requirements of these structs, read <https://github.com/foniod/redbpf/issues/150#issuecomment-964017857>.
//! 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::<ClientAndChannelV4>(), 64)
}
#[test]
fn port_and_peer_v4_has_size_64() {
assert_eq!(std::mem::size_of::<PortAndPeerV4>(), 64)
}
#[test]
fn client_and_channel_v6_has_size_64() {
assert_eq!(std::mem::size_of::<ClientAndChannelV6>(), 64)
}
#[test]
fn port_and_peer_v6_has_size_64() {
assert_eq!(std::mem::size_of::<PortAndPeerV6>(), 64)
}
}

View File

@@ -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::<PortAndPeerV4>() + core::mem::size_of::<ClientAndChannelV4>();
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"
);
}
}