Browse Source

Merge pull request #519 from dave-tucker/frags

XDP Multi-Buffer Support
Alessandro Decina 2 years ago
parent
commit
bc83f208b1

+ 18 - 5
aya-bpf-macros/src/expand.rs

@@ -200,20 +200,33 @@ impl SkMsg {
 pub struct Xdp {
     item: ItemFn,
     name: Option<String>,
+    frags: bool,
 }
 
 impl Xdp {
     pub fn from_syn(mut args: Args, item: ItemFn) -> Result<Xdp> {
-        let name = name_arg(&mut args)?;
-
-        Ok(Xdp { item, name })
+        let name = pop_arg(&mut args, "name");
+        let mut frags = false;
+        if let Some(s) = pop_arg(&mut args, "frags") {
+            if let Ok(m) = s.parse() {
+                frags = m
+            } else {
+                return Err(Error::new_spanned(
+                    "mutlibuffer",
+                    "invalid value. should be 'true' or 'false'",
+                ));
+            }
+        }
+        err_on_unknown_args(&args)?;
+        Ok(Xdp { item, name, frags })
     }
 
     pub fn expand(&self) -> Result<TokenStream> {
+        let section_prefix = if self.frags { "xdp.frags" } else { "xdp" };
         let section_name = if let Some(name) = &self.name {
-            format!("xdp/{name}")
+            format!("{section_prefix}/{name}")
         } else {
-            "xdp".to_owned()
+            section_prefix.to_string()
         };
         let fn_vis = &self.item.vis;
         let fn_name = &self.item.sig.ident;

+ 34 - 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,14 @@ 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 +1844,30 @@ 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)
 }
 

+ 1 - 1
test/integration-ebpf/src/map_test.rs

@@ -14,7 +14,7 @@ static FOO: Array<u32> = Array::<u32>::with_max_entries(10, 0);
 #[map(name = "BAR")]
 static BAZ: Array<u32> = Array::<u32>::with_max_entries(10, 0);
 
-#[xdp]
+#[xdp(frags = "true")]
 pub fn pass(ctx: XdpContext) -> u32 {
     match unsafe { try_pass(ctx) } {
         Ok(ret) => ret,

+ 1 - 1
test/integration-ebpf/src/pass.rs

@@ -3,7 +3,7 @@
 
 use aya_bpf::{bindings::xdp_action, macros::xdp, programs::XdpContext};
 
-#[xdp(name = "pass")]
+#[xdp(name = "pass", frags = "true")]
 pub fn pass(ctx: XdpContext) -> u32 {
     match unsafe { try_pass(ctx) } {
         Ok(ret) => ret,