Explorar el Código

aya: Replace From<FdLink> for XdpLink with TryFrom

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
Dave Tucker hace 2 años
padre
commit
f961cbb
Se han modificado 2 ficheros con 46 adiciones y 20 borrados
  1. 21 4
      aya/src/programs/xdp.rs
  2. 25 16
      aya/src/sys/bpf.rs

+ 21 - 4
aya/src/programs/xdp.rs

@@ -7,6 +7,7 @@ use thiserror::Error;
 use crate::{
     generated::{
         bpf_attach_type::{self, BPF_XDP},
+        bpf_link_type,
         bpf_prog_type::BPF_PROG_TYPE_XDP,
         XDP_FLAGS_DRV_MODE, XDP_FLAGS_HW_MODE, XDP_FLAGS_REPLACE, XDP_FLAGS_SKB_MODE,
         XDP_FLAGS_UPDATE_IF_NOEXIST,
@@ -14,7 +15,10 @@ use crate::{
     programs::{
         define_link_wrapper, load_program, FdLink, Link, LinkError, ProgramData, ProgramError,
     },
-    sys::{bpf_link_create, bpf_link_update, kernel_version, netlink_set_xdp_fd},
+    sys::{
+        bpf_link_create, bpf_link_get_info_by_fd, bpf_link_update, kernel_version,
+        netlink_set_xdp_fd,
+    },
 };
 
 /// The type returned when attaching an [`Xdp`] program fails on kernels `< 5.9`.
@@ -250,9 +254,22 @@ impl TryFrom<XdpLink> for FdLink {
     }
 }
 
-impl From<FdLink> for XdpLink {
-    fn from(fd_link: FdLink) -> Self {
-        XdpLink(XdpLinkInner::FdLink(fd_link))
+impl TryFrom<FdLink> for XdpLink {
+    type Error = LinkError;
+
+    fn try_from(fd_link: FdLink) -> Result<Self, Self::Error> {
+        // unwrap of fd_link.fd will not panic since it's only None when being dropped.
+        let info = bpf_link_get_info_by_fd(fd_link.fd.unwrap()).map_err(|io_error| {
+            LinkError::SyscallError {
+                call: "BPF_OBJ_GET_INFO_BY_FD".to_string(),
+                code: 0,
+                io_error,
+            }
+        })?;
+        if info.type_ == (bpf_link_type::BPF_LINK_TYPE_XDP as u32) {
+            return Ok(XdpLink(XdpLinkInner::FdLink(fd_link)));
+        }
+        Err(LinkError::InvalidLink)
     }
 }
 

+ 25 - 16
aya/src/sys/bpf.rs

@@ -1,16 +1,3 @@
-use crate::{
-    generated::BPF_F_REPLACE,
-    obj::{
-        btf::{
-            BtfParam, BtfType, DataSec, DataSecEntry, DeclTag, Float, Func, FuncLinkage, FuncProto,
-            Int, IntEncoding, Ptr, TypeTag, Var, VarLinkage,
-        },
-        copy_instructions,
-    },
-    Btf,
-};
-use libc::{c_char, c_long, close, ENOENT, ENOSPC};
-
 use std::{
     cmp::{self, min},
     ffi::{CStr, CString},
@@ -20,18 +7,25 @@ use std::{
     slice,
 };
 
+use libc::{c_char, c_long, close, ENOENT, ENOSPC};
+
 use crate::{
     generated::{
-        bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_prog_info, bpf_prog_type,
+        bpf_attach_type, bpf_attr, bpf_btf_info, bpf_cmd, bpf_insn, bpf_link_info, bpf_prog_info,
+        bpf_prog_type, BPF_F_REPLACE,
     },
     maps::PerCpuValues,
     obj::{
         self,
-        btf::{FuncSecInfo, LineSecInfo},
+        btf::{
+            BtfParam, BtfType, DataSec, DataSecEntry, DeclTag, Float, Func, FuncLinkage, FuncProto,
+            FuncSecInfo, Int, IntEncoding, LineSecInfo, Ptr, TypeTag, Var, VarLinkage,
+        },
+        copy_instructions,
     },
     sys::{kernel_version, syscall, SysResult, Syscall},
     util::VerifierLog,
-    Pod, BPF_OBJ_NAME_LEN,
+    Btf, Pod, BPF_OBJ_NAME_LEN,
 };
 
 pub(crate) fn bpf_create_map(name: &CStr, def: &obj::Map, btf_fd: Option<RawFd>) -> SysResult {
@@ -457,6 +451,21 @@ pub(crate) fn bpf_prog_get_info_by_fd(prog_fd: RawFd) -> Result<bpf_prog_info, i
     }
 }
 
+pub(crate) fn bpf_link_get_info_by_fd(link_fd: RawFd) -> Result<bpf_link_info, io::Error> {
+    let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
+    // info gets entirely populated by the kernel
+    let info = unsafe { MaybeUninit::zeroed().assume_init() };
+
+    attr.info.bpf_fd = link_fd as u32;
+    attr.info.info = &info as *const _ as u64;
+    attr.info.info_len = mem::size_of::<bpf_link_info>() as u32;
+
+    match sys_bpf(bpf_cmd::BPF_OBJ_GET_INFO_BY_FD, &attr) {
+        Ok(_) => Ok(info),
+        Err((_, err)) => Err(err),
+    }
+}
+
 pub(crate) fn btf_obj_get_info_by_fd(
     prog_fd: RawFd,
     buf: &mut [u8],