diff --git a/libbpf-rs/src/xdp.rs b/libbpf-rs/src/xdp.rs index 40488ebed..218cde468 100644 --- a/libbpf-rs/src/xdp.rs +++ b/libbpf-rs/src/xdp.rs @@ -1,5 +1,6 @@ use bitflags::bitflags; use std::mem::size_of; +use std::os::fd::RawFd; use std::os::unix::io::AsRawFd; use std::os::unix::io::BorrowedFd; @@ -91,4 +92,14 @@ impl<'fd> Xdp<'fd> { unsafe { libbpf_sys::bpf_xdp_query_id(ifindex, flags.bits() as i32, &mut prog_id) }; util::parse_ret(err).map(|()| prog_id) } + + /// Replace an existing xdp program (identified by old_prog_fd) with this xdp program + pub fn replace(&self, ifindex: i32, old_prog_fd: RawFd, flags: XdpFlags) -> Result<()> { + let mut opts = self.attach_opts; + opts.old_prog_fd = old_prog_fd; + let ret = unsafe { + libbpf_sys::bpf_xdp_attach(ifindex, self.fd.as_raw_fd(), flags.bits(), &opts) + }; + util::parse_ret(ret) + } } diff --git a/libbpf-rs/tests/test_xdp.rs b/libbpf-rs/tests/test_xdp.rs index 2b919a8a2..47bfb4009 100644 --- a/libbpf-rs/tests/test_xdp.rs +++ b/libbpf-rs/tests/test_xdp.rs @@ -1,4 +1,5 @@ use std::os::fd::AsFd; +use std::os::fd::AsRawFd; use scopeguard::defer; @@ -18,7 +19,11 @@ fn test_sudo_xdp() { let obj = get_test_object("xdp.bpf.o"); let fd = obj.prog("xdp_filter").unwrap().as_fd(); + let obj1 = get_test_object("xdp.bpf.o"); + let fd1 = obj1.prog("xdp_filter").unwrap().as_fd(); + let xdp_prog = Xdp::new(fd); + let xdp_prog1 = Xdp::new(fd1); defer! { xdp_prog.detach(LO_IFINDEX, XdpFlags::UPDATE_IF_NOEXIST).unwrap(); @@ -41,6 +46,10 @@ fn test_sudo_xdp() { .query(LO_IFINDEX, XdpFlags::UPDATE_IF_NOEXIST) .is_ok()); + assert!(xdp_prog1 + .replace(LO_IFINDEX, fd.as_raw_fd(), XdpFlags::REPLACE) + .is_ok()); + assert!(xdp_prog .detach(LO_IFINDEX, XdpFlags::UPDATE_IF_NOEXIST) .is_ok());