Browse Source

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 <[email protected]>
Dave Tucker 2 years ago
parent
commit
a18693b
4 changed files with 42 additions and 7 deletions
  1. 25 3
      aya-obj/src/obj.rs
  2. 11 3
      aya/src/bpf.rs
  3. 4 0
      aya/src/programs/mod.rs
  4. 2 1
      aya/src/sys/bpf.rs

+ 25 - 3
aya-obj/src/obj.rs

@@ -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();

+ 11 - 3
aya/src/bpf.rs

@@ -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),
                         }),

+ 4 - 0
aya/src/programs/mod.rs

@@ -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;

+ 2 - 1
aya/src/sys/bpf.rs

@@ -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)
 }