Forráskód Böngészése

programs: make `loaded_programs` opaque

Tamir Duberstein 1 éve
szülő
commit
a0af7e0b2f
3 módosított fájl, 53 hozzáadás és 93 törlés
  1. 18 56
      aya/src/programs/mod.rs
  2. 33 6
      aya/src/sys/bpf.rs
  3. 2 31
      xtask/public-api/aya.txt

+ 18 - 56
aya/src/programs/mod.rs

@@ -110,7 +110,7 @@ use crate::{
     pin::PinError,
     sys::{
         bpf_btf_get_fd_by_id, bpf_get_object, bpf_load_program, bpf_pin_object,
-        bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd, bpf_prog_get_next_id, bpf_prog_query,
+        bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd, bpf_prog_query, iter_prog_ids,
         retry_with_verifier_logs, BpfLoadProgramAttrs, SyscallError,
     },
     util::KernelVersion,
@@ -971,56 +971,6 @@ impl ProgramInfo {
     }
 }
 
-/// ProgramsIter is an Iterator over loaded eBPF programs.
-pub struct ProgramsIter {
-    current: u32,
-    error: bool,
-}
-
-impl Iterator for ProgramsIter {
-    type Item = Result<ProgramInfo, ProgramError>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        if self.error {
-            return None;
-        }
-        let current = self.current;
-
-        match bpf_prog_get_next_id(current) {
-            Ok(Some(next)) => {
-                self.current = next;
-                Some(
-                    bpf_prog_get_fd_by_id(next)
-                        .map_err(|io_error| SyscallError {
-                            call: "bpf_prog_get_fd_by_id",
-                            io_error,
-                        })
-                        .and_then(|fd| {
-                            bpf_prog_get_info_by_fd(fd.as_raw_fd())
-                                .map_err(|io_error| SyscallError {
-                                    call: "bpf_prog_get_info_by_fd",
-                                    io_error,
-                                })
-                                .map(ProgramInfo)
-                        })
-                        .map_err(Into::into),
-                )
-            }
-            Ok(None) => None,
-            Err((_, io_error)) => {
-                // If getting the next program failed, we have to yield None in our next
-                // iteration to avoid an infinite loop.
-                self.error = true;
-                Some(Err(SyscallError {
-                    call: "bpf_prog_get_fd_by_id",
-                    io_error,
-                }
-                .into()))
-            }
-        }
-    }
-}
-
 /// Returns an iterator over all loaded bpf programs.
 ///
 /// This differs from [`crate::Bpf::programs`] since it will return all programs
@@ -1044,9 +994,21 @@ impl Iterator for ProgramsIter {
 /// next program id, get the program fd, or the [`ProgramInfo`] fail. In cases where
 /// iteration can't be performed, for example the caller does not have the necessary privileges,
 /// a single item will be yielded containing the error that occurred.
-pub fn loaded_programs() -> ProgramsIter {
-    ProgramsIter {
-        current: 0,
-        error: false,
-    }
+pub fn loaded_programs() -> impl Iterator<Item = Result<ProgramInfo, ProgramError>> {
+    iter_prog_ids()
+        .map(|id| {
+            let id = id?;
+            bpf_prog_get_fd_by_id(id).map_err(|io_error| SyscallError {
+                call: "bpf_prog_get_fd_by_id",
+                io_error,
+            })
+        })
+        .map(|fd| {
+            let fd = fd?;
+            bpf_prog_get_info_by_fd(fd.as_raw_fd()).map_err(|io_error| SyscallError {
+                call: "bpf_prog_get_info_by_fd",
+                io_error,
+            })
+        })
+        .map(|result| result.map(ProgramInfo).map_err(Into::into))
 }

+ 33 - 6
aya/src/sys/bpf.rs

@@ -1,7 +1,7 @@
 use std::{
     cmp::{self, min},
     ffi::{CStr, CString},
-    io,
+    io, iter,
     mem::{self, MaybeUninit},
     os::fd::{AsRawFd, BorrowedFd, FromRawFd as _, OwnedFd, RawFd},
     slice,
@@ -28,7 +28,7 @@ use crate::{
         },
         copy_instructions,
     },
-    sys::{syscall, SysResult, Syscall},
+    sys::{syscall, SysResult, Syscall, SyscallError},
     Btf, Pod, VerifierLogLevel, BPF_OBJ_NAME_LEN,
 };
 
@@ -909,17 +909,44 @@ fn sys_bpf(cmd: bpf_cmd, attr: &mut bpf_attr) -> SysResult<c_long> {
     syscall(Syscall::Bpf { cmd, attr })
 }
 
-pub(crate) fn bpf_prog_get_next_id(id: u32) -> Result<Option<u32>, (c_long, io::Error)> {
+fn bpf_prog_get_next_id(id: u32) -> Result<Option<u32>, SyscallError> {
     let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
     let u = unsafe { &mut attr.__bindgen_anon_6 };
     u.__bindgen_anon_1.start_id = id;
     match sys_bpf(bpf_cmd::BPF_PROG_GET_NEXT_ID, &mut attr) {
-        Ok(_) => Ok(Some(unsafe { attr.__bindgen_anon_6.next_id })),
-        Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
-        Err(e) => Err(e),
+        Ok(code) => {
+            assert_eq!(code, 0);
+            Ok(Some(unsafe { attr.__bindgen_anon_6.next_id }))
+        }
+        Err((code, io_error)) => {
+            assert_eq!(code, -1);
+            if io_error.raw_os_error() == Some(ENOENT) {
+                Ok(None)
+            } else {
+                Err(SyscallError {
+                    call: "bpf_prog_get_next_id",
+                    io_error,
+                })
+            }
+        }
     }
 }
 
+pub(crate) fn iter_prog_ids() -> impl Iterator<Item = Result<u32, SyscallError>> {
+    let mut current_id = Some(0);
+    iter::from_fn(move || {
+        let next_id = {
+            let current_id = current_id?;
+            bpf_prog_get_next_id(current_id).transpose()
+        };
+        current_id = next_id.as_ref().and_then(|next_id| match next_id {
+            Ok(next_id) => Some(*next_id),
+            Err(SyscallError { .. }) => None,
+        });
+        next_id
+    })
+}
+
 pub(crate) fn retry_with_verifier_logs<T>(
     max_retries: usize,
     f: impl Fn(&mut [u8]) -> SysResult<T>,

+ 2 - 31
xtask/public-api/aya.txt

@@ -6228,35 +6228,6 @@ impl<T> core::borrow::BorrowMut<T> for aya::programs::ProgramInfo where T: core:
 pub fn aya::programs::ProgramInfo::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya::programs::ProgramInfo
 pub fn aya::programs::ProgramInfo::from(t: T) -> T
-pub struct aya::programs::ProgramsIter
-impl core::iter::traits::iterator::Iterator for aya::programs::ProgramsIter
-pub type aya::programs::ProgramsIter::Item = core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
-pub fn aya::programs::ProgramsIter::next(&mut self) -> core::option::Option<Self::Item>
-impl core::marker::Send for aya::programs::ProgramsIter
-impl core::marker::Sync for aya::programs::ProgramsIter
-impl core::marker::Unpin for aya::programs::ProgramsIter
-impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::ProgramsIter
-impl core::panic::unwind_safe::UnwindSafe for aya::programs::ProgramsIter
-impl<I> core::iter::traits::collect::IntoIterator for aya::programs::ProgramsIter where I: core::iter::traits::iterator::Iterator
-pub type aya::programs::ProgramsIter::IntoIter = I
-pub type aya::programs::ProgramsIter::Item = <I as core::iter::traits::iterator::Iterator>::Item
-pub fn aya::programs::ProgramsIter::into_iter(self) -> I
-impl<T, U> core::convert::Into<U> for aya::programs::ProgramsIter where U: core::convert::From<T>
-pub fn aya::programs::ProgramsIter::into(self) -> U
-impl<T, U> core::convert::TryFrom<U> for aya::programs::ProgramsIter where U: core::convert::Into<T>
-pub type aya::programs::ProgramsIter::Error = core::convert::Infallible
-pub fn aya::programs::ProgramsIter::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
-impl<T, U> core::convert::TryInto<U> for aya::programs::ProgramsIter where U: core::convert::TryFrom<T>
-pub type aya::programs::ProgramsIter::Error = <U as core::convert::TryFrom<T>>::Error
-pub fn aya::programs::ProgramsIter::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
-impl<T> core::any::Any for aya::programs::ProgramsIter where T: 'static + core::marker::Sized
-pub fn aya::programs::ProgramsIter::type_id(&self) -> core::any::TypeId
-impl<T> core::borrow::Borrow<T> for aya::programs::ProgramsIter where T: core::marker::Sized
-pub fn aya::programs::ProgramsIter::borrow(&self) -> &T
-impl<T> core::borrow::BorrowMut<T> for aya::programs::ProgramsIter where T: core::marker::Sized
-pub fn aya::programs::ProgramsIter::borrow_mut(&mut self) -> &mut T
-impl<T> core::convert::From<T> for aya::programs::ProgramsIter
-pub fn aya::programs::ProgramsIter::from(t: T) -> T
 pub struct aya::programs::RawTracePoint
 impl aya::programs::RawTracePoint
 pub fn aya::programs::RawTracePoint::attach(&mut self, tp_name: &str) -> core::result::Result<RawTracePointLinkId, aya::programs::ProgramError>
@@ -6919,7 +6890,7 @@ impl aya::programs::links::Link for aya::programs::xdp::XdpLink
 pub type aya::programs::xdp::XdpLink::Id = aya::programs::xdp::XdpLinkId
 pub fn aya::programs::xdp::XdpLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
 pub fn aya::programs::xdp::XdpLink::id(&self) -> Self::Id
-pub fn aya::programs::loaded_programs() -> aya::programs::ProgramsIter
+pub fn aya::programs::loaded_programs() -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>>
 pub mod aya::util
 pub struct aya::util::KernelVersion
 impl aya::util::KernelVersion
@@ -7250,4 +7221,4 @@ impl aya::Pod for u8
 impl<K: aya::Pod> aya::Pod for aya::maps::lpm_trie::Key<K>
 impl<T: aya::Pod, const N: usize> aya::Pod for [T; N]
 pub fn aya::features() -> &'static aya_obj::obj::Features
-pub fn aya::loaded_programs() -> aya::programs::ProgramsIter
+pub fn aya::loaded_programs() -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>>