Browse Source

Skip `cpumap_chain` when attachment fails

Tamir Duberstein 2 weeks ago
parent
commit
907920a629
2 changed files with 32 additions and 2 deletions
  1. 14 0
      aya/src/sys/netlink.rs
  2. 18 2
      test/integration-test/src/tests/xdp.rs

+ 14 - 0
aya/src/sys/netlink.rs

@@ -48,6 +48,20 @@ pub(crate) enum NetlinkErrorInternal {
 #[error(transparent)]
 pub struct NetlinkError(#[from] NetlinkErrorInternal);
 
+impl NetlinkError {
+    pub fn raw_os_error(&self) -> Option<i32> {
+        let Self(inner) = self;
+        match inner {
+            NetlinkErrorInternal::Error { source, .. } => source.raw_os_error(),
+            NetlinkErrorInternal::IoError(err) => err.raw_os_error(),
+            NetlinkErrorInternal::NlAttrError(err) => match err {
+                NlAttrError::InvalidBufferLength { .. }
+                | NlAttrError::InvalidHeaderLength { .. } => None,
+            },
+        }
+    }
+}
+
 // Safety: marking this as unsafe overall because of all the pointer math required to comply with
 // netlink alignments
 pub(crate) unsafe fn netlink_set_xdp_fd(

+ 18 - 2
test/integration-test/src/tests/xdp.rs

@@ -1,9 +1,11 @@
 use std::{net::UdpSocket, num::NonZeroU32, time::Duration};
 
+use assert_matches::assert_matches;
 use aya::{
     Ebpf,
     maps::{Array, CpuMap, XskMap},
-    programs::{Xdp, XdpFlags},
+    programs::{ProgramError, Xdp, XdpError, XdpFlags, xdp::XdpLinkId},
+    util::KernelVersion,
 };
 use object::{Object as _, ObjectSection as _, ObjectSymbol as _, SymbolSection};
 use xdpilone::{BufIdx, IfInfo, Socket, SocketConfig, Umem, UmemConfig};
@@ -177,7 +179,21 @@ fn cpumap_chain() {
     // Load the main program
     let xdp: &mut Xdp = bpf.program_mut("redirect_cpu").unwrap().try_into().unwrap();
     xdp.load().unwrap();
-    xdp.attach("lo", XdpFlags::default()).unwrap();
+    let result = xdp.attach("lo", XdpFlags::default());
+    // Generic devices did not support cpumap XDP programs until 5.15.
+    //
+    // See https://github.com/torvalds/linux/commit/11941f8a85362f612df61f4aaab0e41b64d2111d.
+    if KernelVersion::current().unwrap() < KernelVersion::new(5, 15, 0) {
+        assert_matches!(result, Err(ProgramError::XdpError(XdpError::NetlinkError(err))) => {
+            assert_eq!(err.raw_os_error(), Some(libc::EINVAL))
+        });
+        eprintln!(
+            "skipping test - cpumap attachment not supported on generic (loopback) interface"
+        );
+        return;
+    } else {
+        let _: XdpLinkId = result.unwrap();
+    };
 
     const PAYLOAD: &str = "hello cpumap";