aya-log: Add format hints for MAC addresses

Add `{:mac}` (for lower-case hex representation) and `{:MAC}` (for
upper-case hex representation) format hints for the `[u8; 6]` type,
which is the standard one in Linux to store physical addresses in.

Tested with: https://github.com/vadorovsky/aya-examples/tree/main/xdp-mac

Signed-off-by: Michal Rostecki <vadorovsky@gmail.com>
pull/436/head
Michal Rostecki 2 years ago
parent 82773f46c8
commit 2223ab828d

@ -44,6 +44,8 @@ pub enum RecordField {
NumArgs, NumArgs,
} }
/// Types which are supported by aya-log and can be safely sent from eBPF
/// programs to userspace.
#[repr(usize)] #[repr(usize)]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum Argument { pub enum Argument {
@ -64,7 +66,11 @@ pub enum Argument {
F32, F32,
F64, F64,
/// `[u8; 6]` array which represents a MAC address.
ArrU8Len6,
/// `[u8; 16]` array which represents an IPv6 address.
ArrU8Len16, ArrU8Len16,
/// `[u16; 8]` array which represents an IPv6 address.
ArrU16Len8, ArrU16Len8,
Str, Str,
@ -84,6 +90,10 @@ pub enum DisplayHint {
Ipv4, Ipv4,
/// `:ipv6` /// `:ipv6`
Ipv6, Ipv6,
/// `:mac`
LowerMac,
/// `:MAC`
UpperMac,
} }
#[cfg(feature = "userspace")] #[cfg(feature = "userspace")]
@ -178,6 +188,12 @@ impl WriteToBuf for [u16; 8] {
} }
} }
impl WriteToBuf for [u8; 6] {
fn write(&self, buf: &mut [u8]) -> Result<usize, ()> {
TagLenValue::<Argument>::new(Argument::ArrU8Len6, self).write(buf)
}
}
impl WriteToBuf for str { impl WriteToBuf for str {
fn write(&self, buf: &mut [u8]) -> Result<usize, ()> { fn write(&self, buf: &mut [u8]) -> Result<usize, ()> {
TagLenValue::<Argument>::new(Argument::Str, self.as_bytes()).write(buf) TagLenValue::<Argument>::new(Argument::Str, self.as_bytes()).write(buf)

@ -81,6 +81,8 @@ fn hint_to_expr(hint: DisplayHint) -> Result<Expr> {
DisplayHint::UpperHex => parse_str("::aya_log_ebpf::macro_support::DisplayHint::UpperHex"), DisplayHint::UpperHex => parse_str("::aya_log_ebpf::macro_support::DisplayHint::UpperHex"),
DisplayHint::Ipv4 => parse_str("::aya_log_ebpf::macro_support::DisplayHint::Ipv4"), DisplayHint::Ipv4 => parse_str("::aya_log_ebpf::macro_support::DisplayHint::Ipv4"),
DisplayHint::Ipv6 => parse_str("::aya_log_ebpf::macro_support::DisplayHint::Ipv6"), DisplayHint::Ipv6 => parse_str("::aya_log_ebpf::macro_support::DisplayHint::Ipv6"),
DisplayHint::LowerMac => parse_str("::aya_log_ebpf::macro_support::DisplayHint::LowerMac"),
DisplayHint::UpperMac => parse_str("::aya_log_ebpf::macro_support::DisplayHint::UpperMac"),
} }
} }

@ -59,6 +59,8 @@ fn parse_display_hint(s: &str) -> Result<DisplayHint, String> {
"X" => DisplayHint::UpperHex, "X" => DisplayHint::UpperHex,
"ipv4" => DisplayHint::Ipv4, "ipv4" => DisplayHint::Ipv4,
"ipv6" => DisplayHint::Ipv6, "ipv6" => DisplayHint::Ipv6,
"mac" => DisplayHint::LowerMac,
"MAC" => DisplayHint::UpperMac,
_ => return Err(format!("unknown display hint: {:?}", s)), _ => return Err(format!("unknown display hint: {:?}", s)),
}) })
} }

@ -171,6 +171,26 @@ where
} }
} }
pub struct LowerMacFormatter;
impl Formatter<[u8; 6]> for LowerMacFormatter {
fn format(v: [u8; 6]) -> String {
format!(
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
v[0], v[1], v[2], v[3], v[4], v[5]
)
}
}
pub struct UpperMacFormatter;
impl Formatter<[u8; 6]> for UpperMacFormatter {
fn format(v: [u8; 6]) -> String {
format!(
"{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
v[0], v[1], v[2], v[3], v[4], v[5]
)
}
}
trait Format { trait Format {
fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()>; fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()>;
} }
@ -183,11 +203,28 @@ impl Format for u32 {
Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)), Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)),
Some(DisplayHint::Ipv4) => Ok(Ipv4Formatter::format(*self)), Some(DisplayHint::Ipv4) => Ok(Ipv4Formatter::format(*self)),
Some(DisplayHint::Ipv6) => Err(()), Some(DisplayHint::Ipv6) => Err(()),
Some(DisplayHint::LowerMac) => Err(()),
Some(DisplayHint::UpperMac) => Err(()),
_ => Ok(DefaultFormatter::format(self)), _ => Ok(DefaultFormatter::format(self)),
} }
} }
} }
impl Format for [u8; 6] {
fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()> {
match last_hint {
Some(DisplayHint::Default) => Err(()),
Some(DisplayHint::LowerHex) => Err(()),
Some(DisplayHint::UpperHex) => Err(()),
Some(DisplayHint::Ipv4) => Err(()),
Some(DisplayHint::Ipv6) => Err(()),
Some(DisplayHint::LowerMac) => Ok(LowerMacFormatter::format(*self)),
Some(DisplayHint::UpperMac) => Ok(UpperMacFormatter::format(*self)),
_ => Err(()),
}
}
}
impl Format for [u8; 16] { impl Format for [u8; 16] {
fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()> { fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()> {
match last_hint { match last_hint {
@ -196,6 +233,8 @@ impl Format for [u8; 16] {
Some(DisplayHint::UpperHex) => Err(()), Some(DisplayHint::UpperHex) => Err(()),
Some(DisplayHint::Ipv4) => Err(()), Some(DisplayHint::Ipv4) => Err(()),
Some(DisplayHint::Ipv6) => Ok(Ipv6Formatter::format(*self)), Some(DisplayHint::Ipv6) => Ok(Ipv6Formatter::format(*self)),
Some(DisplayHint::LowerMac) => Err(()),
Some(DisplayHint::UpperMac) => Err(()),
_ => Err(()), _ => Err(()),
} }
} }
@ -209,6 +248,8 @@ impl Format for [u16; 8] {
Some(DisplayHint::UpperHex) => Err(()), Some(DisplayHint::UpperHex) => Err(()),
Some(DisplayHint::Ipv4) => Err(()), Some(DisplayHint::Ipv4) => Err(()),
Some(DisplayHint::Ipv6) => Ok(Ipv6Formatter::format(*self)), Some(DisplayHint::Ipv6) => Ok(Ipv6Formatter::format(*self)),
Some(DisplayHint::LowerMac) => Err(()),
Some(DisplayHint::UpperMac) => Err(()),
_ => Err(()), _ => Err(()),
} }
} }
@ -224,6 +265,8 @@ macro_rules! impl_format {
Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)), Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)),
Some(DisplayHint::Ipv4) => Err(()), Some(DisplayHint::Ipv4) => Err(()),
Some(DisplayHint::Ipv6) => Err(()), Some(DisplayHint::Ipv6) => Err(()),
Some(DisplayHint::LowerMac) => Err(()),
Some(DisplayHint::UpperMac) => Err(()),
_ => Ok(DefaultFormatter::format(self)), _ => Ok(DefaultFormatter::format(self)),
} }
} }
@ -252,6 +295,8 @@ macro_rules! impl_format_float {
Some(DisplayHint::UpperHex) => Err(()), Some(DisplayHint::UpperHex) => Err(()),
Some(DisplayHint::Ipv4) => Err(()), Some(DisplayHint::Ipv4) => Err(()),
Some(DisplayHint::Ipv6) => Err(()), Some(DisplayHint::Ipv6) => Err(()),
Some(DisplayHint::LowerMac) => Err(()),
Some(DisplayHint::UpperMac) => Err(()),
_ => Ok(DefaultFormatter::format(self)), _ => Ok(DefaultFormatter::format(self)),
} }
} }
@ -407,6 +452,10 @@ fn log_buf(mut buf: &[u8], logger: &dyn Log) -> Result<(), ()> {
.format(last_hint.take())?, .format(last_hint.take())?,
); );
} }
Argument::ArrU8Len6 => {
let value: [u8; 6] = attr.value.try_into().map_err(|_| ())?;
full_log_msg.push_str(&value.format(last_hint.take())?);
}
Argument::ArrU8Len16 => { Argument::ArrU8Len16 => {
let value: [u8; 16] = attr.value.try_into().map_err(|_| ())?; let value: [u8; 16] = attr.value.try_into().map_err(|_| ())?;
full_log_msg.push_str(&value.format(last_hint.take())?); full_log_msg.push_str(&value.format(last_hint.take())?);
@ -650,4 +699,44 @@ mod test {
assert_eq!(captured_logs[0].level, Level::Info); assert_eq!(captured_logs[0].level, Level::Info);
}); });
} }
#[test]
fn test_display_hint_lower_mac() {
testing_logger::setup();
let (mut len, mut input) = new_log(3).unwrap();
len += "mac: ".write(&mut input[len..]).unwrap();
len += DisplayHint::LowerMac.write(&mut input[len..]).unwrap();
// 00:00:5e:00:53:af as byte array
let mac_arr: [u8; 6] = [0x00, 0x00, 0x5e, 0x00, 0x53, 0xaf];
mac_arr.write(&mut input[len..]).unwrap();
let logger = logger();
let _ = log_buf(&input, logger);
testing_logger::validate(|captured_logs| {
assert_eq!(captured_logs.len(), 1);
assert_eq!(captured_logs[0].body, "mac: 00:00:5e:00:53:af");
assert_eq!(captured_logs[0].level, Level::Info);
});
}
#[test]
fn test_display_hint_upper_mac() {
testing_logger::setup();
let (mut len, mut input) = new_log(3).unwrap();
len += "mac: ".write(&mut input[len..]).unwrap();
len += DisplayHint::UpperMac.write(&mut input[len..]).unwrap();
// 00:00:5E:00:53:AF as byte array
let mac_arr: [u8; 6] = [0x00, 0x00, 0x5e, 0x00, 0x53, 0xaf];
mac_arr.write(&mut input[len..]).unwrap();
let logger = logger();
let _ = log_buf(&input, logger);
testing_logger::validate(|captured_logs| {
assert_eq!(captured_logs.len(), 1);
assert_eq!(captured_logs[0].body, "mac: 00:00:5E:00:53:AF");
assert_eq!(captured_logs[0].level, Level::Info);
});
}
} }

Loading…
Cancel
Save