Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aya: use montonic SinceBoot for loaded_at #799

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aya/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub mod pin;
pub mod programs;
pub use programs::loaded_programs;
mod sys;
pub mod time;
pub mod util;

pub use bpf::*;
Expand Down
9 changes: 5 additions & 4 deletions aya/src/programs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ use std::{
os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd},
path::{Path, PathBuf},
sync::Arc,
time::{Duration, SystemTime},
};

pub use cgroup_device::CgroupDevice;
Expand Down Expand Up @@ -110,13 +109,14 @@ use crate::{
maps::MapError,
obj::{self, btf::BtfError, VerifierLog},
pin::PinError,
programs::utils::{boot_time, get_fdinfo},
programs::utils::get_fdinfo,
sys::{
bpf_btf_get_fd_by_id, bpf_get_object, bpf_link_get_fd_by_id, bpf_link_get_info_by_fd,
bpf_load_program, bpf_pin_object, bpf_prog_get_fd_by_id, bpf_prog_get_info_by_fd,
bpf_prog_query, iter_link_ids, iter_prog_ids, retry_with_verifier_logs,
BpfLoadProgramAttrs, SyscallError,
},
time::SinceBoot,
util::KernelVersion,
VerifierLogLevel,
};
Expand Down Expand Up @@ -1086,8 +1086,9 @@ impl ProgramInfo {
}

/// The time the program was loaded.
pub fn loaded_at(&self) -> SystemTime {
boot_time() + Duration::from_nanos(self.0.load_time)
pub fn loaded_at(&self) -> SinceBoot {
// See https://github.com/torvalds/linux/blob/633b47cb/include/linux/bpf.h#L1418.
SinceBoot::from_nanos(self.0.load_time)
}

/// Returns a file descriptor referencing the program.
Expand Down
20 changes: 0 additions & 20 deletions aya/src/programs/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::{
io::{self, BufRead, BufReader},
os::fd::{AsFd as _, AsRawFd as _, BorrowedFd},
path::Path,
time::{Duration, SystemTime, UNIX_EPOCH},
};

use crate::{
Expand Down Expand Up @@ -58,25 +57,6 @@ pub(crate) fn find_tracefs_path() -> Result<&'static Path, ProgramError> {
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "tracefs not found").into())
}

/// The time at which the system is booted.
pub(crate) fn boot_time() -> SystemTime {
let get_time = |clock_id| {
let mut time = unsafe { std::mem::zeroed::<libc::timespec>() };
assert_eq!(
unsafe { libc::clock_gettime(clock_id, &mut time) },
0,
"clock_gettime({}, _)",
clock_id
);
let libc::timespec { tv_sec, tv_nsec } = time;

Duration::new(tv_sec as u64, tv_nsec as u32)
};
let since_boot = get_time(libc::CLOCK_BOOTTIME);
let since_epoch = get_time(libc::CLOCK_REALTIME);
UNIX_EPOCH + since_epoch - since_boot
}

/// Get the specified information from a file descriptor's fdinfo.
pub(crate) fn get_fdinfo(fd: BorrowedFd<'_>, key: &str) -> Result<u32, ProgramError> {
let info = File::open(format!("/proc/self/fdinfo/{}", fd.as_raw_fd()))?;
Expand Down
68 changes: 68 additions & 0 deletions aya/src/time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! Utilities for working with time.

use std::time::{Duration, SystemTime, UNIX_EPOCH};

/// A timestamp relative to the system boot time.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct SinceBoot(Duration);

impl SinceBoot {
/// The current SinceBoot.
///
/// Note that these calls will be monotonic.
pub fn now() -> Self {
Self(get_time(libc::CLOCK_BOOTTIME))
}

/// Converts the timestamp to a `SystemTime`.
///
/// Note that this will not be robust to changes in the system clock, and thus these
/// times should not be used for comparisons.
pub fn into_system(self) -> SystemTime {
let Self(since_boot) = self;
boot_time() + since_boot
}

pub(crate) fn from_nanos(nanos: u64) -> Self {
Self(Duration::from_nanos(nanos))
}
}

fn boot_time() -> SystemTime {
let since_boot = get_time(libc::CLOCK_BOOTTIME);
let since_epoch = get_time(libc::CLOCK_REALTIME);
UNIX_EPOCH + since_epoch - since_boot
}

fn get_time(clock_id: libc::clockid_t) -> Duration {
let mut time = unsafe { std::mem::zeroed::<libc::timespec>() };
assert_eq!(
unsafe { libc::clock_gettime(clock_id, &mut time) },
0,
"clock_gettime({}, _)",
clock_id
);
let libc::timespec { tv_sec, tv_nsec } = time;
Duration::new(tv_sec as u64, tv_nsec as u32)
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_since_boot_now_into_system_near_system_time() {
let since_boot = SinceBoot::now().into_system();
let system_time = SystemTime::now();
let delta = system_time
.duration_since(since_boot)
.unwrap_or_else(|err| err.duration());
const MAX_DELTA: Duration = Duration::from_micros(10);
assert!(
delta <= MAX_DELTA,
"delta {delta:?} > {MAX_DELTA:?}: since_boot: {:?}, system_time: {:?}",
since_boot,
system_time
);
}
}
6 changes: 4 additions & 2 deletions test/integration-test/src/tests/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use aya::{
links::{FdLink, PinnedLink},
loaded_links, loaded_programs, KProbe, TracePoint, UProbe, Xdp, XdpFlags,
},
time::SinceBoot,
util::KernelVersion,
Bpf,
};
Expand Down Expand Up @@ -154,9 +155,10 @@ fn unload_xdp() {
fn test_loaded_at() {
let mut bpf = Bpf::load(crate::TEST).unwrap();
let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap();
let t1 = SystemTime::now();

let t1 = SinceBoot::now();
prog.load().unwrap();
let t2 = SystemTime::now();
let t2 = SinceBoot::now();
assert_loaded("pass");

let loaded_at = prog.info().unwrap().loaded_at();
Expand Down
46 changes: 45 additions & 1 deletion xtask/public-api/aya.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6582,7 +6582,7 @@ pub fn aya::programs::ProgramInfo::fd(&self) -> core::result::Result<aya::progra
pub fn aya::programs::ProgramInfo::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
pub fn aya::programs::ProgramInfo::gpl_compatible(&self) -> bool
pub fn aya::programs::ProgramInfo::id(&self) -> u32
pub fn aya::programs::ProgramInfo::loaded_at(&self) -> std::time::SystemTime
pub fn aya::programs::ProgramInfo::loaded_at(&self) -> aya::time::SinceBoot
pub fn aya::programs::ProgramInfo::map_ids(&self) -> core::result::Result<alloc::vec::Vec<u32>, aya::programs::ProgramError>
pub fn aya::programs::ProgramInfo::memory_locked(&self) -> core::result::Result<u32, aya::programs::ProgramError>
pub fn aya::programs::ProgramInfo::name(&self) -> &[u8]
Expand Down Expand Up @@ -7294,6 +7294,50 @@ 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() -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>>
pub mod aya::time
pub struct aya::time::SinceBoot(_)
impl aya::time::SinceBoot
pub fn aya::time::SinceBoot::into_system(self) -> std::time::SystemTime
pub fn aya::time::SinceBoot::now() -> Self
impl core::clone::Clone for aya::time::SinceBoot
pub fn aya::time::SinceBoot::clone(&self) -> aya::time::SinceBoot
impl core::cmp::Eq for aya::time::SinceBoot
impl core::cmp::Ord for aya::time::SinceBoot
pub fn aya::time::SinceBoot::cmp(&self, other: &aya::time::SinceBoot) -> core::cmp::Ordering
impl core::cmp::PartialEq<aya::time::SinceBoot> for aya::time::SinceBoot
pub fn aya::time::SinceBoot::eq(&self, other: &aya::time::SinceBoot) -> bool
impl core::cmp::PartialOrd<aya::time::SinceBoot> for aya::time::SinceBoot
pub fn aya::time::SinceBoot::partial_cmp(&self, other: &aya::time::SinceBoot) -> core::option::Option<core::cmp::Ordering>
impl core::fmt::Debug for aya::time::SinceBoot
pub fn aya::time::SinceBoot::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
impl core::marker::Copy for aya::time::SinceBoot
impl core::marker::StructuralEq for aya::time::SinceBoot
impl core::marker::StructuralPartialEq for aya::time::SinceBoot
impl core::marker::Send for aya::time::SinceBoot
impl core::marker::Sync for aya::time::SinceBoot
impl core::marker::Unpin for aya::time::SinceBoot
impl core::panic::unwind_safe::RefUnwindSafe for aya::time::SinceBoot
impl core::panic::unwind_safe::UnwindSafe for aya::time::SinceBoot
impl<T, U> core::convert::Into<U> for aya::time::SinceBoot where U: core::convert::From<T>
pub fn aya::time::SinceBoot::into(self) -> U
impl<T, U> core::convert::TryFrom<U> for aya::time::SinceBoot where U: core::convert::Into<T>
pub type aya::time::SinceBoot::Error = core::convert::Infallible
pub fn aya::time::SinceBoot::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
impl<T, U> core::convert::TryInto<U> for aya::time::SinceBoot where U: core::convert::TryFrom<T>
pub type aya::time::SinceBoot::Error = <U as core::convert::TryFrom<T>>::Error
pub fn aya::time::SinceBoot::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
impl<T> alloc::borrow::ToOwned for aya::time::SinceBoot where T: core::clone::Clone
pub type aya::time::SinceBoot::Owned = T
pub fn aya::time::SinceBoot::clone_into(&self, target: &mut T)
pub fn aya::time::SinceBoot::to_owned(&self) -> T
impl<T> core::any::Any for aya::time::SinceBoot where T: 'static + core::marker::Sized
pub fn aya::time::SinceBoot::type_id(&self) -> core::any::TypeId
impl<T> core::borrow::Borrow<T> for aya::time::SinceBoot where T: core::marker::Sized
pub fn aya::time::SinceBoot::borrow(&self) -> &T
impl<T> core::borrow::BorrowMut<T> for aya::time::SinceBoot where T: core::marker::Sized
pub fn aya::time::SinceBoot::borrow_mut(&mut self) -> &mut T
impl<T> core::convert::From<T> for aya::time::SinceBoot
pub fn aya::time::SinceBoot::from(t: T) -> T
pub mod aya::util
pub struct aya::util::KernelVersion
impl aya::util::KernelVersion
Expand Down
Loading