浏览代码

src/helpers.rs: add `rand()` and `bpf_time_getns()` helpers

`bpf_time_getns()` mimics `bpf_ktime_getns()` from kernel and return
monotonic time since boot time, in nanoseconds.

`rand(min, max)` is specific to rbpf and returns a random value
comprised between `min` and `max` (inclusive).
Quentin Monnet 8 年之前
父节点
当前提交
fca752631e
共有 1 个文件被更改,包括 73 次插入0 次删除
  1. 73 0
      src/helpers.rs

+ 73 - 0
src/helpers.rs

@@ -20,11 +20,51 @@
 //! value. Hence some helpers have unused arguments, or return a 0 value in all cases, in order to
 //! respect this convention.
 
+extern crate libc;
+
 use std::u64;
 
 // Helpers associated to kernel helpers
 // See also linux/include/uapi/linux/bpf.h in Linux kernel sources.
 
+// bpf_ktime_getns()
+
+/// Index of helper `bpf_ktime_getns()`, equivalent to `bpf_time_getns()`, in Linux kernel, see
+/// <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/bpf.h>.
+pub const BPF_KTIME_GETNS_IDX: u32 = 5;
+
+/// Get monotonic time (since boot time) in nanoseconds. All arguments are unused.
+///
+/// If needed, you may e.g. create a helper returning real time by using the same code, but
+/// replacing `libc::CLOCK_MONOTONIC` with `libc::CLOCK_REALTIME`.
+///
+/// # Examples
+///
+/// ```
+/// use rbpf::helpers;
+///
+/// let t = helpers::bpf_time_getns(0, 0, 0, 0, 0);
+/// let d =  t / 10u64.pow(9)  / 60   / 60  / 24;
+/// let h = (t / 10u64.pow(9)  / 60   / 60) % 24;
+/// let m = (t / 10u64.pow(9)  / 60 ) % 60;
+/// let s = (t / 10u64.pow(9)) % 60;
+/// let ns = t % 10u64.pow(9);
+/// println!("Uptime: {:#x} == {} days {}:{}:{}, {} ns", t, d, h, m, s, ns);
+/// ```
+#[allow(dead_code)]
+#[allow(unused_variables)]
+pub fn bpf_time_getns (unused1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
+    unsafe {
+        let mut tp = libc::timespec {
+            tv_sec: 0,
+            tv_nsec: 0
+        };
+        let tp_ptr: *mut libc::timespec = &mut tp;
+        libc::clock_gettime(libc::CLOCK_MONOTONIC, tp_ptr);
+        ((*tp_ptr).tv_sec as u64) * 10u64.pow(9) + (*tp_ptr).tv_nsec as u64
+    }
+}
+
 // bpf_trace_printk()
 
 /// Index of helper `bpf_trace_printk()`, equivalent to `bpf_trace_printf()`, in Linux kernel, see
@@ -207,3 +247,36 @@ pub fn strcmp (arg1: u64, arg2: u64, arg3: u64, unused4: u64, unused5: u64) -> u
         }
     }
 }
+
+// Some additional helpers
+
+/// Returns a random u64 value comprised between `min` and `max` values (inclusive). Arguments 3 to
+/// 5 are unused.
+///
+/// Relies on `rand()` function from libc, so `libc::srand()` should be called once before this
+/// helper is used.
+///
+/// # Examples
+///
+/// ```
+/// extern crate libc;
+/// extern crate rbpf;
+///
+/// unsafe {
+///     libc::srand(libc::time(std::ptr::null_mut()) as u32);
+/// }
+///
+/// let n = rbpf::helpers::rand(3, 6, 0, 0, 0);
+/// assert!(3 <= n && n <= 6);
+/// ```
+#[allow(dead_code)]
+#[allow(unused_variables)]
+pub fn rand (min: u64, max: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
+    let mut n = unsafe {
+        (libc::rand() as u64).wrapping_shl(32) + libc::rand() as u64
+    };
+    if min < max {
+        n = n % (max + 1 - min) + min;
+    };
+    n
+}