#![no_std] #![no_main] #![expect(unused_crate_dependencies, reason = "used in other bins")] use core::{ hint::black_box, net::{IpAddr, Ipv4Addr, Ipv6Addr}, }; use aya_ebpf::{ macros::{map, uprobe}, maps::Array, programs::ProbeContext, }; use aya_log_ebpf::{debug, error, info, trace, warn}; use integration_common::log::Buffer; #[cfg(not(test))] extern crate ebpf_panic; #[map] static BUFFER: Array = Array::with_max_entries(1, 0); const TWO_KB_ARRAY: [u8; 2048] = [0u8; 2048]; const FOUR_KB_ARRAY: [u8; 4096] = [0u8; 4096]; const EIGHT_KB_ARRAY: [u8; 8192] = [0u8; 8192]; #[uprobe] fn test_log(ctx: ProbeContext) { debug!(&ctx, "Hello from eBPF!"); error!( &ctx, "{}, {}, {}, {:x}", 69, 420i32, "wao", "wao".as_bytes() ); // 10.0.0.1 let ipv4 = Ipv4Addr::new(10, 0, 0, 1); // 2001:db8::1 let ipv6 = Ipv6Addr::new(8193, 3512, 0, 0, 0, 0, 0, 1); info!( &ctx, "ip structs, without format hint: ipv4: {}, ipv6: {}", ipv4, ipv6 ); info!( &ctx, "ip structs, with format hint: ipv4: {:i}, ipv6: {:i}", ipv4, ipv6 ); let ipv4_enum = IpAddr::V4(ipv4); let ipv6_enum = IpAddr::V6(ipv6); info!( &ctx, "ip enums, without format hint: ipv4: {}, ipv6: {}", ipv4_enum, ipv6_enum ); info!( &ctx, "ip enums, with format hint: ipv4: {:i}, ipv6: {:i}", ipv4_enum, ipv6_enum ); // We don't format `Ipv6Addr::to_bits`, because `u128` is not supported by // eBPF. Even though Rust compiler does not complain, verifier would throw // an error about returning values not fitting into 64-bit registers. info!(&ctx, "ip as bits: ipv4: {:i}", ipv4.to_bits()); info!( &ctx, "ip as octets: ipv4: {:i}, ipv6: {:i}", ipv4.octets(), ipv6.octets() ); let mac = [4u8, 32u8, 6u8, 9u8, 0u8, 64u8]; trace!(&ctx, "mac lc: {:mac}, mac uc: {:MAC}", mac, mac); let hex = 0x2f; warn!(&ctx, "hex lc: {:x}, hex uc: {:X}", hex, hex); let hex = [0xde, 0xad, 0xbe, 0xef].as_slice(); debug!(&ctx, "hex lc: {:x}, hex uc: {:X}", hex, hex); let header = 42; let tmp = 43; let kind = 44; let value = 45; let size = 46; let op = 47; let buf = 48; debug!( &ctx, "{} {} {} {} {} {} {}", header, tmp, kind, value, size, op, buf ); let ptr = 0xdeadbeef as *const u8; debug!(&ctx, "ptr: {:p}", ptr); // Testing compilation only. if false { struct NoCopy {} impl NoCopy { fn consume(self) -> u64 { 0xdeadbeef } } let no_copy = NoCopy {}; // Check usage in expression position. let () = debug!(&ctx, "{:x}", no_copy.consume()); } let Some(Buffer { buf, len }) = BUFFER.get(0) else { return; }; let len = *len; let buf = &buf[..core::cmp::min(len, buf.len())]; info!(&ctx, "variable length buffer: {:x}", buf); info!(&ctx, "2KiB array: {:x}", &TWO_KB_ARRAY); info!(&ctx, "4KiB array: {:x}", &FOUR_KB_ARRAY); // This one is too big and should be dropped. info!(&ctx, "8KiB array: {:x}", &EIGHT_KB_ARRAY); } #[uprobe] fn test_log_omission(ctx: ProbeContext) { debug!( &ctx, "This is the last u32: {}", black_box(0u32..).last().unwrap_or(u32::MAX) ); }