Skip to content

Commit

Permalink
add: separate mod for xdp
Browse files Browse the repository at this point in the history
Signed-off-by: yogaraj.s <[email protected]>
  • Loading branch information
yogaraj.s committed Dec 14, 2023
1 parent 89994e6 commit 3252fd5
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 0 deletions.
3 changes: 3 additions & 0 deletions libbpf-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ mod ringbuf;
mod skeleton;
mod tc;
mod util;
mod xdp;

pub use libbpf_sys;

Expand Down Expand Up @@ -142,6 +143,8 @@ pub use crate::tc::TC_H_MIN_EGRESS;
pub use crate::tc::TC_H_MIN_INGRESS;
pub use crate::tc::TC_INGRESS;
pub use crate::util::num_possible_cpus;
pub use crate::xdp::Xdp;
pub use crate::xdp::XdpFlags;

/// Used for skeleton -- an end user may not consider this API stable
#[doc(hidden)]
Expand Down
96 changes: 96 additions & 0 deletions libbpf-rs/src/xdp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use bitflags::bitflags;
use std::mem::size_of;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::BorrowedFd;

use crate::util;
use crate::Error;
use crate::Result;

bitflags! {
/// Flags to configure the `XDP` operations
pub struct XdpFlags: u32 {
/// See [`libbpf_sys::XDP_FLAGS_UPDATE_IF_NOEXIST`].
const UPDATE_IF_NOEXIST = libbpf_sys::XDP_FLAGS_UPDATE_IF_NOEXIST as _;
/// See [`libbpf_sys::XDP_FLAGS_SKB_MODE`].
const SKB_MODE = libbpf_sys::XDP_FLAGS_SKB_MODE as _;
/// See [`libbpf_sys::XDP_FLAGS_DRV_MODE`].
const DRV_MODE = libbpf_sys::XDP_FLAGS_DRV_MODE as _;
/// See [`libbpf_sys::XDP_FLAGS_HW_MODE`].
const HW_MODE = libbpf_sys::XDP_FLAGS_HW_MODE as _;
/// See [`libbpf_sys::XDP_FLAGS_REPLACE`].
const REPLACE = libbpf_sys::XDP_FLAGS_REPLACE as _;
/// See [`libbpf_sys::XDP_FLAGS_MODES`].
const MODES = libbpf_sys::XDP_FLAGS_MODES as _;
/// See [`libbpf_sys::XDP_FLAGS_MASK`].
const MASK = libbpf_sys::XDP_FLAGS_MASK as _;
}

}

/// Represents a XDP program.
///
/// This struct exposes operations to attach, detach and query a XDP program
#[derive(Debug)]
pub struct Xdp<'fd> {
fd: BorrowedFd<'fd>,
attach_opts: libbpf_sys::bpf_xdp_attach_opts,
query_opts: libbpf_sys::bpf_xdp_query_opts,
}

impl<'fd> Xdp<'fd> {
/// Create a new xdp instance with the given file descriptor of the `SEC("xdp")` [`Program`][crate::Program].
pub fn new(fd: BorrowedFd<'fd>) -> Self {
let mut xdp = Xdp {
fd,
attach_opts: libbpf_sys::bpf_xdp_attach_opts::default(),
query_opts: libbpf_sys::bpf_xdp_query_opts::default(),
};
xdp.attach_opts.sz = size_of::<libbpf_sys::bpf_xdp_attach_opts>() as libbpf_sys::size_t;
xdp.query_opts.sz = size_of::<libbpf_sys::bpf_xdp_query_opts>() as libbpf_sys::size_t;
xdp
}

/// Attach the XDP program to the given interface to start processing the packets
pub fn attach(&self, ifindex: i32, flags: XdpFlags) -> Result<()> {
let ret = unsafe {
libbpf_sys::bpf_xdp_attach(
ifindex,
self.fd.as_raw_fd(),
flags.bits(),
&self.attach_opts,
)
};
util::parse_ret(ret)
}

/// Detach the XDP program from the interface
pub fn detach(&self, ifindex: i32, flags: XdpFlags) -> Result<()> {
let ret = unsafe { libbpf_sys::bpf_xdp_detach(ifindex, flags.bits(), &self.attach_opts) };
util::parse_ret(ret)
}

/// Query to inspect the program
pub fn query(&self, ifindex: i32, flags: XdpFlags) -> Result<libbpf_sys::bpf_xdp_query_opts> {
let mut opts = self.query_opts;
let err = unsafe { libbpf_sys::bpf_xdp_query(ifindex, flags.bits() as i32, &mut opts) };
if err != 0 {
Err(Error::from_raw_os_error(err))
} else {
Ok(opts)
}
}

/// Query to inspect the program identifier (prog_id)
pub fn query_id(&self, ifindex: i32, flags: XdpFlags) -> Result<u32> {
let mut prog_id: u32 = 0;
let err = unsafe {
libbpf_sys::bpf_xdp_query_id(ifindex, flags.bits() as i32, (&mut prog_id) as *mut u32)
};
if err != 0 {
Err(Error::from_raw_os_error(err))
} else {
Ok(prog_id)
}
}
}
7 changes: 7 additions & 0 deletions libbpf-rs/tests/bin/src/xdp.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

SEC("xdp")
int xdp_filter(struct xdp_md *ctx) {
return XDP_PASS;
}
Binary file added libbpf-rs/tests/bin/xdp.bpf.o
Binary file not shown.
40 changes: 40 additions & 0 deletions libbpf-rs/tests/test_xdp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
mod test;
use std::os::fd::AsFd;
use test::bump_rlimit_mlock;
use test::get_test_object;

use libbpf_rs::Xdp;
use libbpf_rs::XdpFlags;

const LO_IFINDEX: i32 = 1;

#[test]
fn test_sudo_xdp() {
bump_rlimit_mlock();

let obj = get_test_object("xdp.bpf.o");
let fd = obj.prog("xdp_filter").unwrap().as_fd();

let xdp_prog = Xdp::new(fd);

assert!(xdp_prog
.attach(LO_IFINDEX, XdpFlags::UPDATE_IF_NOEXIST)
.is_ok());

// Second attach should fail as a prog is already loaded
assert!(xdp_prog
.attach(LO_IFINDEX, XdpFlags::UPDATE_IF_NOEXIST)
.is_err());

assert!(xdp_prog
.query_id(LO_IFINDEX, XdpFlags::UPDATE_IF_NOEXIST)
.is_ok());

assert!(xdp_prog
.query(LO_IFINDEX, XdpFlags::UPDATE_IF_NOEXIST)
.is_ok());

assert!(xdp_prog
.detach(LO_IFINDEX, XdpFlags::UPDATE_IF_NOEXIST)
.is_ok());
}

0 comments on commit 3252fd5

Please sign in to comment.