pull/1396/merge
Sven Cowart 4 days ago committed by GitHub
commit a52e796a16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -205,12 +205,47 @@ impl SchedClassifier {
///
/// The returned value can be used to detach, see [SchedClassifier::detach].
///
/// # Link Pinning (TCX mode, kernel >= 6.6)
///
/// Links can be pinned to bpffs for atomic replacement across process restarts.
///
/// ```no_run
/// # use std::{io, path::Path};
/// # use aya::programs::{tc, SchedClassifier, TcAttachType, tc::TcAttachOptions, LinkOrder, links::{FdLink, PinnedLink}, LinkError};
/// # use aya::sys::SyscallError;
/// # let mut bpf = aya::Ebpf::load(&[])?;
/// # let prog: &mut SchedClassifier = bpf.program_mut("prog").unwrap().try_into()?;
/// # prog.load()?;
/// let pin_path = "/sys/fs/bpf/my_link";
///
/// let link_id = match PinnedLink::from_pin(pin_path) {
/// Ok(old) => {
/// let link = FdLink::from(old).try_into()?;
/// prog.attach_to_link(link)?
/// }
/// Err(LinkError::SyscallError(SyscallError { io_error, .. }))
/// if io_error.kind() == io::ErrorKind::NotFound =>
/// {
/// prog.attach_with_options(
/// "eth0",
/// TcAttachType::Ingress,
/// TcAttachOptions::TcxOrder(LinkOrder::default()),
/// )?
/// }
/// Err(e) => return Err(e.into()),
/// };
///
/// let link = prog.take_link(link_id)?;
/// let fd_link: FdLink = link.try_into()?;
/// fd_link.pin(pin_path)?;
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
///
/// # Errors
///
/// [`TcError::NetlinkError`] is returned if attaching fails. A common cause
/// of failure is not having added the `clsact` qdisc to the given
/// interface, see [`qdisc_add_clsact`]
///
/// interface, see [`qdisc_add_clsact`].
pub fn attach_with_options(
&mut self,
interface: &str,

@ -6,11 +6,13 @@ use aya::{
maps::Array,
pin::PinError,
programs::{
FlowDissector, KProbe, ProbeKind, Program, ProgramError, TracePoint, UProbe, Xdp, XdpFlags,
FlowDissector, KProbe, LinkOrder, ProbeKind, Program, ProgramError, SchedClassifier,
TcAttachType, TracePoint, UProbe, Xdp, XdpFlags,
flow_dissector::{FlowDissectorLink, FlowDissectorLinkId},
kprobe::{KProbeLink, KProbeLinkId},
links::{FdLink, LinkError, PinnedLink},
loaded_links, loaded_programs,
tc::TcAttachOptions,
trace_point::{TracePointLink, TracePointLinkId},
uprobe::{UProbeLink, UProbeLinkId},
xdp::{XdpLink, XdpLinkId},
@ -394,6 +396,58 @@ fn pin_link() {
assert_unloaded(program_name);
}
#[test_log::test]
fn pin_tcx_link() {
// TCX links require kernel >= 6.6
let kernel_version = KernelVersion::current().unwrap();
if kernel_version < KernelVersion::new(6, 6, 0) {
eprintln!("skipping pin_tcx_link test on kernel {kernel_version:?}");
return;
}
use crate::utils::NetNsGuard;
let _netns = NetNsGuard::new();
let program_name = "tcx_next";
let pin_path = "/sys/fs/bpf/aya-tcx-test-lo";
let mut bpf = Ebpf::load(crate::TCX).unwrap();
let prog: &mut SchedClassifier = bpf.program_mut(program_name).unwrap().try_into().unwrap();
prog.load().unwrap();
let link_id = prog
.attach_with_options(
"lo",
TcAttachType::Ingress,
TcAttachOptions::TcxOrder(LinkOrder::default()),
)
.unwrap();
let link = prog.take_link(link_id).unwrap();
assert_loaded(program_name);
let fd_link: FdLink = link.try_into().unwrap();
fd_link.pin(pin_path).unwrap();
// Because of the pin, the program is still attached
prog.unload().unwrap();
assert_loaded(program_name);
// Load a new program and atomically replace the old one using attach_to_link
let mut bpf = Ebpf::load(crate::TCX).unwrap();
let prog: &mut SchedClassifier = bpf.program_mut(program_name).unwrap().try_into().unwrap();
prog.load().unwrap();
let old_link = PinnedLink::from_pin(pin_path).unwrap();
let link = FdLink::from(old_link).try_into().unwrap();
let _link_id = prog.attach_to_link(link).unwrap();
assert_loaded(program_name);
// Clean up: remove the stale pin file and drop the bpf instance (which drops the program and link)
remove_file(pin_path).unwrap();
drop(bpf);
assert_unloaded(program_name);
}
trait PinProgramOps {
fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), PinError>;
fn unpin(&mut self) -> Result<(), std::io::Error>;

Loading…
Cancel
Save