|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
//! eXpress Data Path (XDP) programs.
|
|
|
|
|
use bitflags;
|
|
|
|
|
use libc::if_nametoindex;
|
|
|
|
|
use std::{ffi::CString, hash::Hash, io, os::unix::io::RawFd};
|
|
|
|
|
use std::{ffi::CString, hash::Hash, io, mem, os::unix::io::RawFd};
|
|
|
|
|
use thiserror::Error;
|
|
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
|
|
|
|
programs::{
|
|
|
|
|
define_link_wrapper, load_program, FdLink, Link, OwnedLink, ProgramData, ProgramError,
|
|
|
|
|
},
|
|
|
|
|
sys::{bpf_link_create, kernel_version, netlink_set_xdp_fd},
|
|
|
|
|
sys::{bpf_link_create, bpf_link_update, kernel_version, netlink_set_xdp_fd},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// The type returned when attaching an [`Xdp`] program fails on kernels `< 5.9`.
|
|
|
|
@ -141,6 +141,46 @@ impl Xdp {
|
|
|
|
|
pub fn take_link(&mut self, link_id: XdpLinkId) -> Result<OwnedLink<XdpLink>, ProgramError> {
|
|
|
|
|
Ok(OwnedLink::new(self.data.take_link(link_id)?))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Atomically replaces the program referenced by the provided link.
|
|
|
|
|
///
|
|
|
|
|
/// Ownership of the link will transfer to this program.
|
|
|
|
|
pub fn attach_to_link(&mut self, link: OwnedLink<XdpLink>) -> Result<XdpLinkId, ProgramError> {
|
|
|
|
|
let prog_fd = self.data.fd_or_err()?;
|
|
|
|
|
match &link.0 {
|
|
|
|
|
XdpLinkInner::FdLink(fd_link) => {
|
|
|
|
|
let link_fd = fd_link.fd;
|
|
|
|
|
bpf_link_update(link_fd, prog_fd, None, 0).map_err(|(_, io_error)| {
|
|
|
|
|
ProgramError::SyscallError {
|
|
|
|
|
call: "bpf_link_update".to_string(),
|
|
|
|
|
io_error,
|
|
|
|
|
}
|
|
|
|
|
})?;
|
|
|
|
|
// dispose of link and avoid detach on drop
|
|
|
|
|
mem::forget(link);
|
|
|
|
|
self.data
|
|
|
|
|
.links
|
|
|
|
|
.insert(XdpLink(XdpLinkInner::FdLink(FdLink::new(link_fd))))
|
|
|
|
|
}
|
|
|
|
|
XdpLinkInner::NlLink(nl_link) => {
|
|
|
|
|
let if_index = nl_link.if_index;
|
|
|
|
|
let old_prog_fd = nl_link.prog_fd;
|
|
|
|
|
let flags = nl_link.flags;
|
|
|
|
|
let replace_flags = flags | XdpFlags::REPLACE;
|
|
|
|
|
unsafe {
|
|
|
|
|
netlink_set_xdp_fd(if_index, prog_fd, Some(old_prog_fd), replace_flags.bits())
|
|
|
|
|
.map_err(|io_error| XdpError::NetlinkError { io_error })?;
|
|
|
|
|
}
|
|
|
|
|
// dispose of link and avoid detach on drop
|
|
|
|
|
mem::forget(link);
|
|
|
|
|
self.data.links.insert(XdpLink(XdpLinkInner::NlLink(NlLink {
|
|
|
|
|
if_index,
|
|
|
|
|
prog_fd,
|
|
|
|
|
flags,
|
|
|
|
|
})))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|