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+` /// - `iter+`, `iter.s+`
/// - `xdp.frags/cpumap`, `xdp/cpumap` /// - `xdp.frags/cpumap`, `xdp/cpumap`
/// - `xdp.frags/devmap`, `xdp/devmap` /// - `xdp.frags/devmap`, `xdp/devmap`
/// - `xdp.frags`
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum ProgramSection { pub enum ProgramSection {
@ -184,6 +183,7 @@ pub enum ProgramSection {
}, },
Xdp { Xdp {
name: String, name: String,
frags_supported: bool,
}, },
SkMsg { SkMsg {
name: String, name: String,
@ -266,7 +266,7 @@ impl ProgramSection {
ProgramSection::URetProbe { name } => name, ProgramSection::URetProbe { name } => name,
ProgramSection::TracePoint { name } => name, ProgramSection::TracePoint { name } => name,
ProgramSection::SocketFilter { name } => name, ProgramSection::SocketFilter { name } => name,
ProgramSection::Xdp { name } => name, ProgramSection::Xdp { name, .. } => name,
ProgramSection::SkMsg { name } => name, ProgramSection::SkMsg { name } => name,
ProgramSection::SkSkbStreamParser { name } => name, ProgramSection::SkSkbStreamParser { name } => name,
ProgramSection::SkSkbStreamVerdict { name } => name, ProgramSection::SkSkbStreamVerdict { name } => name,
@ -313,7 +313,8 @@ impl FromStr for ProgramSection {
"kretprobe" => KRetProbe { name }, "kretprobe" => KRetProbe { name },
"uprobe" => UProbe { name }, "uprobe" => UProbe { name },
"uretprobe" => URetProbe { name }, "uretprobe" => URetProbe { name },
"xdp" => Xdp { name }, "xdp" => Xdp { name, frags_supported: false},
"xdp.frags" => Xdp { name, frags_supported: true},
"tp_btf" => BtfTracePoint { name }, "tp_btf" => BtfTracePoint { name },
_ if kind.starts_with("tracepoint") || kind.starts_with("tp") => { _ if kind.starts_with("tracepoint") || kind.starts_with("tp") => {
// tracepoint sections are named `tracepoint/category/event_name`, // 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] #[test]
fn test_parse_section_raw_tp() { fn test_parse_section_raw_tp() {
let mut obj = fake_obj(); let mut obj = fake_obj();

@ -9,6 +9,7 @@ use std::{
use aya_obj::{ use aya_obj::{
btf::{BtfFeatures, BtfRelocationError}, btf::{BtfFeatures, BtfRelocationError},
generated::BPF_F_XDP_HAS_FRAGS,
relocation::BpfRelocationError, relocation::BpfRelocationError,
}; };
use log::debug; use log::debug;
@ -485,9 +486,16 @@ impl<'a> BpfLoader<'a> {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level),
}) })
} }
ProgramSection::Xdp { .. } => Program::Xdp(Xdp { ProgramSection::Xdp {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), 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 { ProgramSection::SkMsg { .. } => Program::SkMsg(SkMsg {
data: ProgramData::new(prog_name, obj, btf_fd, verifier_log_level), 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) btf_fd: Option<RawFd>,
pub(crate) verifier_log_level: u32, pub(crate) verifier_log_level: u32,
pub(crate) path: Option<PathBuf>, pub(crate) path: Option<PathBuf>,
pub(crate) flags: u32,
} }
impl<T: Link> ProgramData<T> { impl<T: Link> ProgramData<T> {
@ -436,6 +437,7 @@ impl<T: Link> ProgramData<T> {
btf_fd, btf_fd,
verifier_log_level, verifier_log_level,
path: None, path: None,
flags: 0,
} }
} }
@ -474,6 +476,7 @@ impl<T: Link> ProgramData<T> {
btf_fd: None, btf_fd: None,
verifier_log_level: 0, verifier_log_level: 0,
path: Some(path.to_path_buf()), path: Some(path.to_path_buf()),
flags: 0,
}) })
} }
@ -606,6 +609,7 @@ fn load_program<T: Link>(
func_info: func_info.clone(), func_info: func_info.clone(),
line_info_rec_size: *line_info_rec_size, line_info_rec_size: *line_info_rec_size,
line_info: line_info.clone(), line_info: line_info.clone(),
flags: data.flags,
}; };
let verifier_log_level = data.verifier_log_level; let verifier_log_level = data.verifier_log_level;

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

Loading…
Cancel
Save