-
Notifications
You must be signed in to change notification settings - Fork 141
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: yogaraj.s <[email protected]>
- Loading branch information
yogaraj.s
committed
Dec 14, 2023
1 parent
89994e6
commit 3252fd5
Showing
5 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | ||
} |