Browse Source

Merge pull request #436 from vadorovsky/aya-log-mac-addr

aya-log: Add format hints for MAC addresses
Dave Tucker 2 years ago
parent
commit
3adb9b049f
4 changed files with 109 additions and 0 deletions
  1. 16 0
      aya-log-common/src/lib.rs
  2. 2 0
      aya-log-ebpf-macros/src/expand.rs
  3. 2 0
      aya-log-parser/src/lib.rs
  4. 89 0
      aya-log/src/lib.rs

+ 16 - 0
aya-log-common/src/lib.rs

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

+ 2 - 0
aya-log-ebpf-macros/src/expand.rs

@@ -81,6 +81,8 @@ fn hint_to_expr(hint: DisplayHint) -> Result<Expr> {
         DisplayHint::UpperHex => parse_str("::aya_log_ebpf::macro_support::DisplayHint::UpperHex"),
         DisplayHint::Ipv4 => parse_str("::aya_log_ebpf::macro_support::DisplayHint::Ipv4"),
         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"),
     }
 }
 

+ 2 - 0
aya-log-parser/src/lib.rs

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

+ 89 - 0
aya-log/src/lib.rs

@@ -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 {
     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::Ipv4) => Ok(Ipv4Formatter::format(*self)),
             Some(DisplayHint::Ipv6) => Err(()),
+            Some(DisplayHint::LowerMac) => Err(()),
+            Some(DisplayHint::UpperMac) => Err(()),
             _ => 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] {
     fn format(&self, last_hint: Option<DisplayHint>) -> Result<String, ()> {
         match last_hint {
@@ -196,6 +233,8 @@ impl Format for [u8; 16] {
             Some(DisplayHint::UpperHex) => Err(()),
             Some(DisplayHint::Ipv4) => Err(()),
             Some(DisplayHint::Ipv6) => Ok(Ipv6Formatter::format(*self)),
+            Some(DisplayHint::LowerMac) => Err(()),
+            Some(DisplayHint::UpperMac) => Err(()),
             _ => Err(()),
         }
     }
@@ -209,6 +248,8 @@ impl Format for [u16; 8] {
             Some(DisplayHint::UpperHex) => Err(()),
             Some(DisplayHint::Ipv4) => Err(()),
             Some(DisplayHint::Ipv6) => Ok(Ipv6Formatter::format(*self)),
+            Some(DisplayHint::LowerMac) => Err(()),
+            Some(DisplayHint::UpperMac) => Err(()),
             _ => Err(()),
         }
     }
@@ -224,6 +265,8 @@ macro_rules! impl_format {
                     Some(DisplayHint::UpperHex) => Ok(UpperHexFormatter::format(self)),
                     Some(DisplayHint::Ipv4) => Err(()),
                     Some(DisplayHint::Ipv6) => Err(()),
+                    Some(DisplayHint::LowerMac) => Err(()),
+                    Some(DisplayHint::UpperMac) => Err(()),
                     _ => Ok(DefaultFormatter::format(self)),
                 }
             }
@@ -252,6 +295,8 @@ macro_rules! impl_format_float {
                     Some(DisplayHint::UpperHex) => Err(()),
                     Some(DisplayHint::Ipv4) => Err(()),
                     Some(DisplayHint::Ipv6) => Err(()),
+                    Some(DisplayHint::LowerMac) => Err(()),
+                    Some(DisplayHint::UpperMac) => Err(()),
                     _ => Ok(DefaultFormatter::format(self)),
                 }
             }
@@ -407,6 +452,10 @@ fn log_buf(mut buf: &[u8], logger: &dyn Log) -> Result<(), ()> {
                         .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 => {
                 let value: [u8; 16] = attr.value.try_into().map_err(|_| ())?;
                 full_log_msg.push_str(&value.format(last_hint.take())?);
@@ -650,4 +699,44 @@ mod test {
             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);
+        });
+    }
 }