chore(eBPF): include return value in errors (#8626)

At present, we only check for the return value of the various helper
functions and bail out if they fail. What we don't learn is what the
actual return code is. To further help with debugging, we include the
return code in the error so we can print it later.

We can't use the formatting macro within the `write` function so we need
to stitch the message together ourselves.
This commit is contained in:
Thomas Eizinger
2025-04-03 12:21:47 +11:00
committed by GitHub
parent d00995a91e
commit 8c55c2a46a
3 changed files with 64 additions and 38 deletions

View File

@@ -12,9 +12,9 @@ pub enum Error {
BadChannelDataLength,
NoEntry(SupportedChannel),
UnsupportedChannel(UnsupportedChannel),
XdpLoadBytesFailed,
XdpAdjustHeadFailed,
XdpStoreBytesFailed,
XdpLoadBytesFailed(i64),
XdpAdjustHeadFailed(i64),
XdpStoreBytesFailed(i64),
}
#[derive(Debug, Clone, Copy)]
@@ -36,45 +36,66 @@ pub enum UnsupportedChannel {
impl aya_log_ebpf::WriteToBuf for Error {
#[inline(always)]
fn write(self, buf: &mut [u8]) -> Option<NonZeroUsize> {
let msg = match self {
Error::PacketTooShort => "Packet is too short",
Error::NotUdp => "Not a UDP packet",
Error::NotTurn => "Not TURN traffic",
Error::NotIp => "Not an IP packet",
Error::NoMacAddress => "No MAC address",
Error::Ipv4PacketWithOptions => "IPv4 packet has options",
Error::NotAChannelDataMessage => "Not a channel data message",
Error::BadChannelDataLength => "Channel data length does not match packet length",
match self {
Error::PacketTooShort => "Packet is too short".write(buf),
Error::NotUdp => "Not a UDP packet".write(buf),
Error::NotTurn => "Not TURN traffic".write(buf),
Error::NotIp => "Not an IP packet".write(buf),
Error::NoMacAddress => "No MAC address".write(buf),
Error::Ipv4PacketWithOptions => "IPv4 packet has options".write(buf),
Error::NotAChannelDataMessage => "Not a channel data message".write(buf),
Error::BadChannelDataLength => {
"Channel data length does not match packet length".write(buf)
}
Error::NoEntry(SupportedChannel::UdpToChan44) => {
"No entry in UDPv4 to channel IPv4 map"
"No entry in UDPv4 to channel IPv4 map.write(buf)".write(buf)
}
Error::NoEntry(SupportedChannel::ChanToUdp44) => {
"No entry in channel IPv4 to UDPv4 map"
"No entry in channel IPv4 to UDPv4 map.write(buf)".write(buf)
}
Error::NoEntry(SupportedChannel::UdpToChan66) => {
"No entry in UDPv6 to channel IPv6 map"
"No entry in UDPv6 to channel IPv6 map.write(buf)".write(buf)
}
Error::NoEntry(SupportedChannel::ChanToUdp66) => {
"No entry in channel IPv6 to UDPv6 map"
"No entry in channel IPv6 to UDPv6 map.write(buf)".write(buf)
}
Error::UnsupportedChannel(UnsupportedChannel::UdpToChan46) => {
"Relaying UDPv4 to channel IPv6 is not supported"
"Relaying UDPv4 to channel IPv6 is not supported.write(buf)".write(buf)
}
Error::UnsupportedChannel(UnsupportedChannel::ChanToUdp46) => {
"Relaying channel IPv4 to UDPv6 is not supported"
"Relaying channel IPv4 to UDPv6 is not supported.write(buf)".write(buf)
}
Error::UnsupportedChannel(UnsupportedChannel::UdpToChan64) => {
"Relaying UDPv6 to channel IPv4 is not supported"
"Relaying UDPv6 to channel IPv4 is not supported.write(buf)".write(buf)
}
Error::UnsupportedChannel(UnsupportedChannel::ChanToUdp64) => {
"Relaying channel IPv6 to UDPv4 is not supported"
"Relaying channel IPv6 to UDPv4 is not supported.write(buf)".write(buf)
}
Error::XdpLoadBytesFailed => "Failed to load bytes",
Error::XdpAdjustHeadFailed => "Failed to adjust head",
Error::XdpStoreBytesFailed => "Failed to store bytes",
};
Error::XdpLoadBytesFailed(ret) => {
let mut written = 0;
msg.write(buf)
written += "Failed to load bytes: ".write(buf)?.get();
written += ret.write(buf)?.get();
NonZeroUsize::new(written)
}
Error::XdpAdjustHeadFailed(ret) => {
let mut written = 0;
written += "Failed to adjust head: ".write(buf)?.get();
written += ret.write(buf)?.get();
NonZeroUsize::new(written)
}
Error::XdpStoreBytesFailed(ret) => {
let mut written = 0;
written += "Failed to store bytes: ".write(buf)?.get();
written += ret.write(buf)?.get();
NonZeroUsize::new(written)
}
}
}
}

View File

@@ -85,9 +85,9 @@ pub fn handle_turn(ctx: XdpContext) -> u32 {
}
Error::BadChannelDataLength
| Error::XdpStoreBytesFailed
| Error::XdpAdjustHeadFailed
| Error::XdpLoadBytesFailed => {
| Error::XdpStoreBytesFailed(_)
| Error::XdpAdjustHeadFailed(_)
| Error::XdpLoadBytesFailed(_) => {
debug!(&ctx, "Dropping packet: {}", e);
xdp_action::XDP_DROP

View File

@@ -24,8 +24,9 @@ pub fn add_channel_data_header_ipv4(ctx: &XdpContext, mut header: [u8; 4]) -> Re
let header_ptr = &mut header as *mut _ as *mut c_void;
let header_len = CdHdr::LEN as u32;
if unsafe { bpf_xdp_store_bytes(ctx.ctx, offset, header_ptr, header_len) } < 0 {
return Err(Error::XdpStoreBytesFailed);
let ret = unsafe { bpf_xdp_store_bytes(ctx.ctx, offset, header_ptr, header_len) };
if ret < 0 {
return Err(Error::XdpStoreBytesFailed(ret));
}
Ok(())
@@ -44,8 +45,9 @@ pub fn add_channel_data_header_ipv6(ctx: &XdpContext, mut header: [u8; 4]) -> Re
let header_ptr = &mut header as *mut _ as *mut c_void;
let header_len = CdHdr::LEN as u32;
if unsafe { bpf_xdp_store_bytes(ctx.ctx, offset, header_ptr, header_len) } < 0 {
return Err(Error::XdpStoreBytesFailed);
let ret = unsafe { bpf_xdp_store_bytes(ctx.ctx, offset, header_ptr, header_len) };
if ret < 0 {
return Err(Error::XdpStoreBytesFailed(ret));
}
Ok(())
@@ -68,17 +70,20 @@ fn move_headers<const DELTA: i32, const IP_HEADER_LEN: usize>(
let headers_len = (EthHdr::LEN + IP_HEADER_LEN + UdpHdr::LEN) as u32;
// Copy headers into buffer.
if unsafe { bpf_xdp_load_bytes(ctx.ctx, 0, headers_ptr, headers_len) } < 0 {
return Err(Error::XdpLoadBytesFailed);
let ret = unsafe { bpf_xdp_load_bytes(ctx.ctx, 0, headers_ptr, headers_len) };
if ret < 0 {
return Err(Error::XdpLoadBytesFailed(ret));
}
if unsafe { bpf_xdp_adjust_head(ctx.ctx, DELTA) } < 0 {
return Err(Error::XdpAdjustHeadFailed);
let ret = unsafe { bpf_xdp_adjust_head(ctx.ctx, DELTA) };
if ret < 0 {
return Err(Error::XdpAdjustHeadFailed(ret));
}
// Copy the headers back.
if unsafe { bpf_xdp_store_bytes(ctx.ctx, 0, headers_ptr, headers_len) } < 0 {
return Err(Error::XdpStoreBytesFailed);
let ret = unsafe { bpf_xdp_store_bytes(ctx.ctx, 0, headers_ptr, headers_len) };
if ret < 0 {
return Err(Error::XdpStoreBytesFailed(ret));
}
Ok(())