aya: Add support for multibuffer programs

This adds support for loading XDP programs that are multi-buffer
capable, which is signalled using the xdp.frags section name. When this
is set, we should set the BPF_F_XDP_HAS_FRAGS flag when loading the
program into the kernel.

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
pull/519/head
Dave Tucker 2 years ago
parent 811ab299de
commit a18693b42d

@ -160,7 +160,6 @@ pub struct Function {
/// - `iter+`, `iter.s+`
/// - `xdp.frags/cpumap`, `xdp/cpumap`
/// - `xdp.frags/devmap`, `xdp/devmap`
/// - `xdp.frags`
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum ProgramSection {
@ -184,6 +183,7 @@ pub enum ProgramSection {
},
Xdp {
name: String,
frags_supported: bool,
},
SkMsg {
name: String,
@ -266,7 +266,7 @@ impl ProgramSection {
ProgramSection::URetProbe { name } => name,
ProgramSection::TracePoint { name } => name,
ProgramSection::SocketFilter { name } => name,
ProgramSection::Xdp { name } => name,
ProgramSection::Xdp { name, .. } => name,
ProgramSection::SkMsg { name } => name,
ProgramSection::SkSkbStreamParser { name } => name,
ProgramSection::SkSkbStreamVerdict { name } => name,
@ -313,7 +313,8 @@ impl FromStr for ProgramSection {
"kretprobe" => KRetProbe { name },
"uprobe" => UProbe { name },
"uretprobe" => URetProbe { name },
"xdp" => Xdp { name },
"xdp" => Xdp { name, frags_supported: false},
"xdp.frags" => Xdp { name, frags_supported: true},
"tp_btf" => BtfTracePoint { name },
_ if kind.starts_with("tracepoint") || kind.starts_with("tp") => {
// tracepoint sections are named `tracepoint/category/event_name`,
@ -1837,6 +1838,27 @@ mod tests {
);
}
#[test]
fn test_parse_section_xdp_frags() {
let mut obj = fake_obj();
assert_matches!(
obj.parse_section(fake_section(
BpfSectionKind::Program,
"xdp.frags/foo",
bytes_of(&fake_ins())
)),
Ok(())
);
assert_matches!(
obj.programs.get("foo"),
Some(Program {
section: ProgramSection::Xdp { frags_supported: true, .. },
..
})
);
}
#[test]
fn test_parse_section_raw_tp() {
let mut obj = fake_obj();

@ -9,6 +9,7 @@ use std::{
use aya_obj::{
btf::{BtfFeatures, BtfRelocationError},
generated::BPF_F_XDP_HAS_FRAGS,
relocation::BpfRelocationError,
};
use log::debug;
@ -485,9 +486,16 @@ impl<'a> BpfLoader<'a> {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level),
})
}
ProgramSection::Xdp { .. } => Program::Xdp(Xdp {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level),
}),
ProgramSection::Xdp {
frags_supported, ..
} => {
let mut data =
ProgramData::new(prog_name, obj, btf_fd, verifier_log_level);
if *frags_supported {
data.flags = BPF_F_XDP_HAS_FRAGS;
}
Program::Xdp(Xdp { data })
}
ProgramSection::SkMsg { .. } => Program::SkMsg(SkMsg {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level),
}),

@ -415,6 +415,7 @@ pub(crate) struct ProgramData<T: Link> {
pub(crate) btf_fd: Option<RawFd>,
pub(crate) verifier_log_level: u32,
pub(crate) path: Option<PathBuf>,
pub(crate) flags: u32,
}
impl<T: Link> ProgramData<T> {
@ -436,6 +437,7 @@ impl<T: Link> ProgramData<T> {
btf_fd,
verifier_log_level,
path: None,
flags: 0,
}
}
@ -474,6 +476,7 @@ impl<T: Link> ProgramData<T> {
btf_fd: None,
verifier_log_level: 0,
path: Some(path.to_path_buf()),
flags: 0,
})
}
@ -606,6 +609,7 @@ fn load_program<T: Link>(
func_info: func_info.clone(),
line_info_rec_size: *line_info_rec_size,
line_info: line_info.clone(),
flags: data.flags,
};
let verifier_log_level = data.verifier_log_level;

@ -115,6 +115,7 @@ pub(crate) struct BpfLoadProgramAttrs<'a> {
pub(crate) func_info: FuncSecInfo,
pub(crate) line_info_rec_size: usize,
pub(crate) line_info: LineSecInfo,
pub(crate) flags: u32,
}
pub(crate) fn bpf_load_program(
@ -136,6 +137,7 @@ pub(crate) fn bpf_load_program(
u.prog_name = name;
}
u.prog_flags = aya_attr.flags;
u.prog_type = aya_attr.ty as u32;
if let Some(v) = aya_attr.expected_attach_type {
u.expected_attach_type = v as u32;
@ -179,7 +181,6 @@ pub(crate) fn bpf_load_program(
if let Some(v) = aya_attr.attach_btf_id {
u.attach_btf_id = v;
}
sys_bpf(bpf_cmd::BPF_PROG_LOAD, &attr)
}

Loading…
Cancel
Save