4
0
Эх сурвалжийг харах

Add support for Flow Dissector programs

Closes #216.

Co-authored-by: Zenna Allwein <[email protected]>
Signed-off-by: Tamir Duberstein <[email protected]>
Tamir Duberstein 1 долоо хоног өмнө
parent
commit
77b1c6194c

+ 71 - 0
aya-ebpf-macros/src/flow_dissector.rs

@@ -0,0 +1,71 @@
+use proc_macro2::TokenStream;
+use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
+use quote::quote;
+use syn::{ItemFn, spanned::Spanned as _};
+
+pub(crate) struct FlowDissector {
+    item: ItemFn,
+}
+
+impl FlowDissector {
+    pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
+        if !attrs.is_empty() {
+            return Err(attrs.span().error("unexpected attribute"));
+        }
+        let item = syn::parse2(item)?;
+        Ok(FlowDissector { item })
+    }
+
+    pub(crate) fn expand(&self) -> TokenStream {
+        let Self { item } = self;
+        let ItemFn {
+            attrs: _,
+            vis,
+            sig,
+            block: _,
+        } = item;
+        let fn_name = &sig.ident;
+        quote! {
+            #[unsafe(no_mangle)]
+            #[unsafe(link_section = "flow_dissector")]
+            #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> u32 {
+                return #fn_name(::aya_ebpf::programs::FlowDissectorContext::new(ctx));
+
+                #item
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use syn::parse_quote;
+
+    use super::*;
+
+    #[test]
+    fn test_flow_dissector() {
+        let prog = FlowDissector::parse(
+            parse_quote! {},
+            parse_quote! {
+                fn prog(ctx: &mut ::aya_ebpf::programs::FlowDissectorContext) -> u32 {
+                    0
+                }
+            },
+        )
+        .unwrap();
+        let expanded = prog.expand();
+        let expected = quote! {
+            #[unsafe(no_mangle)]
+            #[unsafe(link_section = "flow_dissector")]
+            fn prog(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> u32 {
+                return prog(::aya_ebpf::programs::FlowDissectorContext::new(ctx));
+
+                fn prog(ctx: &mut ::aya_ebpf::programs::FlowDissectorContext) -> u32 {
+                    0
+                }
+            }
+        };
+        assert_eq!(expected.to_string(), expanded.to_string());
+    }
+}

+ 43 - 0
aya-ebpf-macros/src/lib.rs

@@ -8,6 +8,7 @@ mod cgroup_sockopt;
 mod cgroup_sysctl;
 mod fentry;
 mod fexit;
+mod flow_dissector;
 mod kprobe;
 mod lsm;
 mod map;
@@ -32,6 +33,7 @@ use cgroup_sockopt::CgroupSockopt;
 use cgroup_sysctl::CgroupSysctl;
 use fentry::FEntry;
 use fexit::FExit;
+use flow_dissector::FlowDissector;
 use kprobe::{KProbe, KProbeKind};
 use lsm::Lsm;
 use map::Map;
@@ -542,6 +544,47 @@ pub fn fexit(attrs: TokenStream, item: TokenStream) -> TokenStream {
     .into()
 }
 
+/// Marks a function as an eBPF Flow Dissector program.
+///
+/// Flow dissector is a program type that parses metadata out of the packets.
+///
+/// BPF flow dissectors can be attached per network namespace. These programs
+/// are given a packet and expected to populate the fields of
+/// `FlowDissectorContext::flow_keys`. The return code of the BPF program is
+/// either [`BPF_OK`] to indicate successful dissection, [`BPF_DROP`] to
+/// indicate parsing error, or [`BPF_FLOW_DISSECTOR_CONTINUE`] to indicate that
+/// no custom dissection was performed, and fallback to standard dissector is
+/// requested.
+///
+/// # Minimum kernel version
+///
+/// The minimum kernel version required to use this feature is 4.20.
+///
+/// # Examples
+///
+/// ```no_run
+/// use aya_ebpf::{bindings::bpf_ret_code, macros::flow_dissector, programs::FlowDissectorContext};
+///
+/// #[flow_dissector]
+/// pub fn dissect(_ctx: FlowDissectorContext) -> u32 {
+///     // TODO: do something useful here.
+///     bpf_ret_code::BPF_FLOW_DISSECTOR_CONTINUE
+/// }
+/// ```
+///
+/// [`FlowDissectorContext::flow_keys`]: ../aya_ebpf/programs/flow_dissector/struct.FlowDissectorContext.html#method.flow_keys
+/// [`BPF_OK`]: ../aya_ebpf/bindings/bpf_ret_code/constant.bpf_ok
+/// [`BPF_DROP`]: ../aya_ebpf/bindings/bpf_ret_code/constant.bpf_drop
+/// [`BPF_FLOW_DISSECTOR_CONTINUE`]: ../aya_ebpf/bindings/bpf_ret_code/constant.bpf_flow_dissector_continue
+#[proc_macro_attribute]
+pub fn flow_dissector(attrs: TokenStream, item: TokenStream) -> TokenStream {
+    match FlowDissector::parse(attrs.into(), item.into()) {
+        Ok(prog) => prog.expand(),
+        Err(err) => err.emit_as_expr_tokens(),
+    }
+    .into()
+}
+
 /// Marks a function as an eBPF Socket Lookup program that can be attached to
 /// a network namespace.
 ///

+ 2 - 0
aya-obj/src/obj.rs

@@ -281,6 +281,7 @@ pub enum ProgramSection {
     FExit {
         sleepable: bool,
     },
+    FlowDissector,
     Extension,
     SkLookup,
     CgroupSock {
@@ -439,6 +440,7 @@ impl FromStr for ProgramSection {
             "fentry.s" => FEntry { sleepable: true },
             "fexit" => FExit { sleepable: false },
             "fexit.s" => FExit { sleepable: true },
+            "flow_dissector" => FlowDissector,
             "freplace" => Extension,
             "sk_lookup" => SkLookup,
             "iter" => Iter { sleepable: false },

+ 8 - 3
aya/src/bpf.rs

@@ -23,9 +23,10 @@ use crate::{
     maps::{Map, MapData, MapError},
     programs::{
         BtfTracePoint, CgroupDevice, CgroupSkb, CgroupSkbAttachType, CgroupSock, CgroupSockAddr,
-        CgroupSockopt, CgroupSysctl, Extension, FEntry, FExit, Iter, KProbe, LircMode2, Lsm,
-        PerfEvent, ProbeKind, Program, ProgramData, ProgramError, RawTracePoint, SchedClassifier,
-        SkLookup, SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp,
+        CgroupSockopt, CgroupSysctl, Extension, FEntry, FExit, FlowDissector, Iter, KProbe,
+        LircMode2, Lsm, PerfEvent, ProbeKind, Program, ProgramData, ProgramError, RawTracePoint,
+        SchedClassifier, SkLookup, SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint,
+        UProbe, Xdp,
     },
     sys::{
         bpf_load_btf, is_bpf_cookie_supported, is_bpf_global_data_supported,
@@ -430,6 +431,7 @@ impl<'a> EbpfLoader<'a> {
                                 | ProgramSection::PerfEvent
                                 | ProgramSection::RawTracePoint
                                 | ProgramSection::SkLookup
+                                | ProgramSection::FlowDissector
                                 | ProgramSection::CgroupSock { attach_type: _ }
                                 | ProgramSection::CgroupDevice => {}
                             }
@@ -661,6 +663,9 @@ impl<'a> EbpfLoader<'a> {
                             }
                             Program::FExit(FExit { data })
                         }
+                        ProgramSection::FlowDissector => Program::FlowDissector(FlowDissector {
+                            data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
+                        }),
                         ProgramSection::Extension => Program::Extension(Extension {
                             data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
                         }),

+ 156 - 0
aya/src/programs/flow_dissector.rs

@@ -0,0 +1,156 @@
+//! Flow dissector programs.
+
+use std::os::fd::AsFd;
+
+use aya_obj::generated::{
+    bpf_attach_type::BPF_FLOW_DISSECTOR, bpf_prog_type::BPF_PROG_TYPE_FLOW_DISSECTOR,
+};
+
+use crate::{
+    programs::{
+        CgroupAttachMode, FdLink, Link, ProgAttachLink, ProgramData, ProgramError,
+        define_link_wrapper, id_as_key, load_program,
+    },
+    sys::{LinkTarget, SyscallError, bpf_link_create},
+    util::KernelVersion,
+};
+
+/// Flow dissector is a program type that parses metadata out of the packets.
+///
+/// BPF flow dissectors can be attached per network namespace. These programs
+/// are given a packet and expected to populate the fields of
+/// `FlowDissectorContext::flow_keys`. The return code of the BPF program is
+/// either [`BPF_OK`] to indicate successful dissection, [`BPF_DROP`] to
+/// indicate parsing error, or [`BPF_FLOW_DISSECTOR_CONTINUE`] to indicate that
+/// no custom dissection was performed, and fallback to standard dissector is
+/// requested.
+///
+/// # Minimum kernel version
+///
+/// The minimum kernel version required to use this feature is 4.20.
+///
+/// # Examples
+///
+/// ```no_run
+/// # #[derive(Debug, thiserror::Error)]
+/// # enum Error {
+/// #     #[error(transparent)]
+/// #     IO(#[from] std::io::Error),
+/// #     #[error(transparent)]
+/// #     Map(#[from] aya::maps::MapError),
+/// #     #[error(transparent)]
+/// #     Program(#[from] aya::programs::ProgramError),
+/// #     #[error(transparent)]
+/// #     Ebpf(#[from] aya::EbpfError)
+/// # }
+/// # let mut bpf = aya::Ebpf::load(&[])?;
+/// use aya::programs::FlowDissector;
+///
+/// let program: &mut FlowDissector = bpf.program_mut("filename_lookup").unwrap().try_into()?;
+/// program.load()?;
+///
+/// let net_ns = std::fs::File::open("/proc/self/ns/net")?;
+/// program.attach(net_ns)?;
+/// # Ok::<(), Error>(())
+/// ```
+///
+/// [`FlowDissectorContext::flow_keys`]: ../../../aya-ebpf/programs/flow_dissector/struct.FlowDissectorContext.html#method.flow_keys
+/// [`BPF_OK`]: ../../../aya-ebpf/bindings/bpf_ret_code/constant.bpf_ok
+/// [`BPF_DROP`]: ../../../aya-ebpf/bindings/bpf_ret_code/constant.bpf_drop
+/// [`BPF_FLOW_DISSECTOR_CONTINUE`]: ../../../aya-ebpf/bindings/bpf_ret_code/constant.bpf_flow_dissector_continue
+#[derive(Debug)]
+#[doc(alias = "BPF_PROG_TYPE_FLOW_DISSECTOR")]
+pub struct FlowDissector {
+    pub(crate) data: ProgramData<FlowDissectorLink>,
+}
+
+impl FlowDissector {
+    /// Loads the program inside the kernel.
+    pub fn load(&mut self) -> Result<(), ProgramError> {
+        self.data.expected_attach_type = Some(BPF_FLOW_DISSECTOR);
+        load_program(BPF_PROG_TYPE_FLOW_DISSECTOR, &mut self.data)
+    }
+
+    /// Attaches the program to the given network namespace.
+    ///
+    /// The returned value can be used to detach, see [FlowDissector::detach].
+    pub fn attach<T: AsFd>(&mut self, netns: T) -> Result<FlowDissectorLinkId, ProgramError> {
+        let prog_fd = self.fd()?;
+        let prog_fd = prog_fd.as_fd();
+        let netns_fd = netns.as_fd();
+
+        if KernelVersion::at_least(5, 7, 0) {
+            let link_fd = bpf_link_create(
+                prog_fd,
+                LinkTarget::Fd(netns_fd),
+                BPF_FLOW_DISSECTOR,
+                0,
+                None,
+            )
+            .map_err(|io_error| SyscallError {
+                call: "bpf_link_create",
+                io_error,
+            })?;
+            self.data
+                .links
+                .insert(FlowDissectorLink::new(FlowDissectorLinkInner::Fd(
+                    FdLink::new(link_fd),
+                )))
+        } else {
+            let link = ProgAttachLink::attach(
+                prog_fd,
+                netns_fd,
+                BPF_FLOW_DISSECTOR,
+                CgroupAttachMode::default(),
+            )?;
+
+            self.data
+                .links
+                .insert(FlowDissectorLink::new(FlowDissectorLinkInner::ProgAttach(
+                    link,
+                )))
+        }
+    }
+}
+
+#[derive(Debug, Hash, Eq, PartialEq)]
+enum FlowDissectorLinkIdInner {
+    Fd(<FdLink as Link>::Id),
+    ProgAttach(<ProgAttachLink as Link>::Id),
+}
+
+#[derive(Debug)]
+enum FlowDissectorLinkInner {
+    Fd(FdLink),
+    ProgAttach(ProgAttachLink),
+}
+
+impl Link for FlowDissectorLinkInner {
+    type Id = FlowDissectorLinkIdInner;
+
+    fn id(&self) -> Self::Id {
+        match self {
+            Self::Fd(fd) => FlowDissectorLinkIdInner::Fd(fd.id()),
+            Self::ProgAttach(p) => FlowDissectorLinkIdInner::ProgAttach(p.id()),
+        }
+    }
+
+    fn detach(self) -> Result<(), ProgramError> {
+        match self {
+            Self::Fd(fd) => fd.detach(),
+            Self::ProgAttach(p) => p.detach(),
+        }
+    }
+}
+
+id_as_key!(FlowDissectorLinkInner, FlowDissectorLinkIdInner);
+
+define_link_wrapper!(
+    /// The link used by [FlowDissector] programs.
+    FlowDissectorLink,
+    /// The type returned by [FlowDissector::attach]. Can be passed to [FlowDissector::detach].
+    FlowDissectorLinkId,
+    FlowDissectorLinkInner,
+    FlowDissectorLinkIdInner,
+    FlowDissector,
+);

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

@@ -51,6 +51,7 @@ pub mod cgroup_sysctl;
 pub mod extension;
 pub mod fentry;
 pub mod fexit;
+pub mod flow_dissector;
 pub mod iter;
 pub mod kprobe;
 pub mod links;
@@ -101,6 +102,7 @@ pub use crate::programs::{
     extension::{Extension, ExtensionError},
     fentry::FEntry,
     fexit::FExit,
+    flow_dissector::FlowDissector,
     iter::Iter,
     kprobe::{KProbe, KProbeError},
     links::{CgroupAttachMode, Link, LinkOrder},
@@ -311,6 +313,8 @@ pub enum Program {
     FEntry(FEntry),
     /// A [`FExit`] program
     FExit(FExit),
+    /// A [`FlowDissector`] program
+    FlowDissector(FlowDissector),
     /// A [`Extension`] program
     Extension(Extension),
     /// A [`SkLookup`] program
@@ -359,6 +363,7 @@ impl Program {
             Self::SkLookup(_) => ProgramType::SkLookup,
             Self::CgroupSock(_) => ProgramType::CgroupSock,
             Self::CgroupDevice(_) => ProgramType::CgroupDevice,
+            Self::FlowDissector(_) => ProgramType::FlowDissector,
         }
     }
 
@@ -384,6 +389,7 @@ impl Program {
             Self::BtfTracePoint(p) => p.pin(path),
             Self::FEntry(p) => p.pin(path),
             Self::FExit(p) => p.pin(path),
+            Self::FlowDissector(p) => p.pin(path),
             Self::Extension(p) => p.pin(path),
             Self::CgroupSockAddr(p) => p.pin(path),
             Self::SkLookup(p) => p.pin(path),
@@ -415,6 +421,7 @@ impl Program {
             Self::BtfTracePoint(mut p) => p.unload(),
             Self::FEntry(mut p) => p.unload(),
             Self::FExit(mut p) => p.unload(),
+            Self::FlowDissector(mut p) => p.unload(),
             Self::Extension(mut p) => p.unload(),
             Self::CgroupSockAddr(mut p) => p.unload(),
             Self::SkLookup(mut p) => p.unload(),
@@ -448,6 +455,7 @@ impl Program {
             Self::BtfTracePoint(p) => p.fd(),
             Self::FEntry(p) => p.fd(),
             Self::FExit(p) => p.fd(),
+            Self::FlowDissector(p) => p.fd(),
             Self::Extension(p) => p.fd(),
             Self::CgroupSockAddr(p) => p.fd(),
             Self::SkLookup(p) => p.fd(),
@@ -482,6 +490,7 @@ impl Program {
             Self::BtfTracePoint(p) => p.info(),
             Self::FEntry(p) => p.info(),
             Self::FExit(p) => p.info(),
+            Self::FlowDissector(p) => p.info(),
             Self::Extension(p) => p.info(),
             Self::CgroupSockAddr(p) => p.info(),
             Self::SkLookup(p) => p.info(),
@@ -796,6 +805,7 @@ impl_program_unload!(
     BtfTracePoint,
     FEntry,
     FExit,
+    FlowDissector,
     Extension,
     CgroupSockAddr,
     SkLookup,
@@ -837,6 +847,7 @@ impl_fd!(
     BtfTracePoint,
     FEntry,
     FExit,
+    FlowDissector,
     Extension,
     CgroupSockAddr,
     SkLookup,
@@ -943,6 +954,7 @@ impl_program_pin!(
     BtfTracePoint,
     FEntry,
     FExit,
+    FlowDissector,
     Extension,
     CgroupSockAddr,
     SkLookup,
@@ -984,6 +996,7 @@ impl_from_pin!(
     BtfTracePoint,
     FEntry,
     FExit,
+    FlowDissector,
     Extension,
     SkLookup,
     SockOps,
@@ -1039,6 +1052,7 @@ impl_try_from_program!(
     BtfTracePoint,
     FEntry,
     FExit,
+    FlowDissector,
     Extension,
     CgroupSockAddr,
     SkLookup,
@@ -1066,6 +1080,7 @@ impl_info!(
     BtfTracePoint,
     FEntry,
     FExit,
+    FlowDissector,
     Extension,
     CgroupSockAddr,
     SkLookup,

+ 44 - 0
ebpf/aya-ebpf/src/programs/flow_dissector.rs

@@ -0,0 +1,44 @@
+use aya_ebpf_cty::{c_long, c_void};
+
+use crate::{
+    EbpfContext,
+    bindings::{__sk_buff, bpf_flow_keys},
+    programs::sk_buff::SkBuff,
+};
+
+pub struct FlowDissectorContext {
+    skb: SkBuff,
+}
+
+impl FlowDissectorContext {
+    pub fn new(skb: *mut __sk_buff) -> FlowDissectorContext {
+        let skb = SkBuff { skb };
+        FlowDissectorContext { skb }
+    }
+
+    #[inline]
+    pub fn data(&self) -> usize {
+        self.skb.data()
+    }
+
+    #[inline]
+    pub fn data_end(&self) -> usize {
+        self.skb.data_end()
+    }
+
+    #[inline]
+    pub fn flow_keys(&mut self) -> &mut bpf_flow_keys {
+        unsafe { &mut *(*self.skb.skb).__bindgen_anon_1.flow_keys }
+    }
+
+    #[inline(always)]
+    pub fn load_bytes(&self, offset: usize, dst: &mut [u8]) -> Result<usize, c_long> {
+        self.skb.load_bytes(offset, dst)
+    }
+}
+
+impl EbpfContext for FlowDissectorContext {
+    fn as_ptr(&self) -> *mut c_void {
+        self.skb.as_ptr()
+    }
+}

+ 2 - 0
ebpf/aya-ebpf/src/programs/mod.rs

@@ -1,6 +1,7 @@
 pub mod device;
 pub mod fentry;
 pub mod fexit;
+pub mod flow_dissector;
 pub mod lsm;
 pub mod perf_event;
 pub mod probe;
@@ -22,6 +23,7 @@ pub mod xdp;
 pub use device::DeviceContext;
 pub use fentry::FEntryContext;
 pub use fexit::FExitContext;
+pub use flow_dissector::FlowDissectorContext;
 pub use lsm::LsmContext;
 pub use perf_event::PerfEventContext;
 pub use probe::ProbeContext;

+ 12 - 3
test/integration-ebpf/src/test.rs

@@ -2,9 +2,11 @@
 #![no_main]
 
 use aya_ebpf::{
-    bindings::xdp_action,
-    macros::{kprobe, kretprobe, tracepoint, uprobe, uretprobe, xdp},
-    programs::{ProbeContext, RetProbeContext, TracePointContext, XdpContext},
+    bindings::{bpf_ret_code, xdp_action},
+    macros::{flow_dissector, kprobe, kretprobe, tracepoint, uprobe, uretprobe, xdp},
+    programs::{
+        FlowDissectorContext, ProbeContext, RetProbeContext, TracePointContext, XdpContext,
+    },
 };
 
 #[xdp]
@@ -44,6 +46,13 @@ pub fn test_uretprobe(_ctx: RetProbeContext) -> u32 {
     0
 }
 
+#[flow_dissector]
+pub fn test_flow(_ctx: FlowDissectorContext) -> u32 {
+    // TODO: write an actual flow dissector. See tools/testing/selftests/bpf/progs/bpf_flow.c in the
+    // Linux kernel for inspiration.
+    bpf_ret_code::BPF_FLOW_DISSECTOR_CONTINUE
+}
+
 #[cfg(not(test))]
 #[panic_handler]
 fn panic(_info: &core::panic::PanicInfo) -> ! {

+ 29 - 1
test/integration-test/src/tests/load.rs

@@ -4,7 +4,7 @@ use aya::{
     Ebpf,
     maps::Array,
     programs::{
-        KProbe, TracePoint, UProbe, Xdp, XdpFlags,
+        FlowDissector, KProbe, TracePoint, UProbe, Xdp, XdpFlags,
         links::{FdLink, PinnedLink},
         loaded_links, loaded_programs,
     },
@@ -311,6 +311,34 @@ fn basic_uprobe() {
     assert_unloaded("test_uprobe");
 }
 
+#[test]
+fn basic_flow_dissector() {
+    let mut bpf = Ebpf::load(crate::TEST).unwrap();
+    let prog: &mut FlowDissector = bpf.program_mut("test_flow").unwrap().try_into().unwrap();
+
+    prog.load().unwrap();
+    assert_loaded("test_flow");
+
+    let net_ns = std::fs::File::open("/proc/self/ns/net").unwrap();
+    let link = prog.attach(net_ns.try_clone().unwrap()).unwrap();
+    {
+        let _link_owned = prog.take_link(link).unwrap();
+        prog.unload().unwrap();
+        assert_loaded_and_linked("test_flow");
+    };
+
+    assert_unloaded("test_flow");
+    prog.load().unwrap();
+
+    assert_loaded("test_flow");
+    prog.attach(net_ns).unwrap();
+
+    assert_loaded("test_flow");
+    prog.unload().unwrap();
+
+    assert_unloaded("test_flow");
+}
+
 #[test]
 fn pin_link() {
     let kernel_version = KernelVersion::current().unwrap();

+ 1 - 0
xtask/public-api/aya-ebpf-macros.txt

@@ -9,6 +9,7 @@ pub proc macro aya_ebpf_macros::#[cgroup_sysctl]
 pub proc macro aya_ebpf_macros::#[classifier]
 pub proc macro aya_ebpf_macros::#[fentry]
 pub proc macro aya_ebpf_macros::#[fexit]
+pub proc macro aya_ebpf_macros::#[flow_dissector]
 pub proc macro aya_ebpf_macros::#[kprobe]
 pub proc macro aya_ebpf_macros::#[kretprobe]
 pub proc macro aya_ebpf_macros::#[lsm]

+ 65 - 0
xtask/public-api/aya-ebpf.txt

@@ -1452,6 +1452,38 @@ impl<T> core::borrow::BorrowMut<T> for aya_ebpf::programs::fexit::FExitContext w
 pub fn aya_ebpf::programs::fexit::FExitContext::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya_ebpf::programs::fexit::FExitContext
 pub fn aya_ebpf::programs::fexit::FExitContext::from(t: T) -> T
+pub mod aya_ebpf::programs::flow_dissector
+pub struct aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl aya_ebpf::programs::flow_dissector::FlowDissectorContext
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::data(&self) -> usize
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::data_end(&self) -> usize
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::flow_keys(&mut self) -> &mut aya_ebpf_bindings::x86_64::bindings::bpf_flow_keys
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::load_bytes(&self, offset: usize, dst: &mut [u8]) -> core::result::Result<usize, aya_ebpf_cty::od::c_long>
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::new(skb: *mut aya_ebpf_bindings::x86_64::bindings::__sk_buff) -> aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl aya_ebpf::EbpfContext for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::as_ptr(&self) -> *mut aya_ebpf_cty::c_void
+impl core::marker::Freeze for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl !core::marker::Send for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl !core::marker::Sync for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl core::marker::Unpin for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl<T, U> core::convert::Into<U> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where U: core::convert::From<T>
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::into(self) -> U
+impl<T, U> core::convert::TryFrom<U> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where U: core::convert::Into<T>
+pub type aya_ebpf::programs::flow_dissector::FlowDissectorContext::Error = core::convert::Infallible
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
+impl<T, U> core::convert::TryInto<U> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where U: core::convert::TryFrom<T>
+pub type aya_ebpf::programs::flow_dissector::FlowDissectorContext::Error = <U as core::convert::TryFrom<T>>::Error
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
+impl<T> core::any::Any for aya_ebpf::programs::flow_dissector::FlowDissectorContext where T: 'static + ?core::marker::Sized
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::type_id(&self) -> core::any::TypeId
+impl<T> core::borrow::Borrow<T> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where T: ?core::marker::Sized
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::borrow(&self) -> &T
+impl<T> core::borrow::BorrowMut<T> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where T: ?core::marker::Sized
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::borrow_mut(&mut self) -> &mut T
+impl<T> core::convert::From<T> for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::from(t: T) -> T
 pub mod aya_ebpf::programs::lsm
 pub struct aya_ebpf::programs::lsm::LsmContext
 impl aya_ebpf::programs::lsm::LsmContext
@@ -2161,6 +2193,37 @@ impl<T> core::borrow::BorrowMut<T> for aya_ebpf::programs::fexit::FExitContext w
 pub fn aya_ebpf::programs::fexit::FExitContext::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya_ebpf::programs::fexit::FExitContext
 pub fn aya_ebpf::programs::fexit::FExitContext::from(t: T) -> T
+pub struct aya_ebpf::programs::FlowDissectorContext
+impl aya_ebpf::programs::flow_dissector::FlowDissectorContext
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::data(&self) -> usize
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::data_end(&self) -> usize
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::flow_keys(&mut self) -> &mut aya_ebpf_bindings::x86_64::bindings::bpf_flow_keys
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::load_bytes(&self, offset: usize, dst: &mut [u8]) -> core::result::Result<usize, aya_ebpf_cty::od::c_long>
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::new(skb: *mut aya_ebpf_bindings::x86_64::bindings::__sk_buff) -> aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl aya_ebpf::EbpfContext for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::as_ptr(&self) -> *mut aya_ebpf_cty::c_void
+impl core::marker::Freeze for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl !core::marker::Send for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl !core::marker::Sync for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl core::marker::Unpin for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl core::panic::unwind_safe::RefUnwindSafe for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl core::panic::unwind_safe::UnwindSafe for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+impl<T, U> core::convert::Into<U> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where U: core::convert::From<T>
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::into(self) -> U
+impl<T, U> core::convert::TryFrom<U> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where U: core::convert::Into<T>
+pub type aya_ebpf::programs::flow_dissector::FlowDissectorContext::Error = core::convert::Infallible
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
+impl<T, U> core::convert::TryInto<U> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where U: core::convert::TryFrom<T>
+pub type aya_ebpf::programs::flow_dissector::FlowDissectorContext::Error = <U as core::convert::TryFrom<T>>::Error
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
+impl<T> core::any::Any for aya_ebpf::programs::flow_dissector::FlowDissectorContext where T: 'static + ?core::marker::Sized
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::type_id(&self) -> core::any::TypeId
+impl<T> core::borrow::Borrow<T> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where T: ?core::marker::Sized
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::borrow(&self) -> &T
+impl<T> core::borrow::BorrowMut<T> for aya_ebpf::programs::flow_dissector::FlowDissectorContext where T: ?core::marker::Sized
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::borrow_mut(&mut self) -> &mut T
+impl<T> core::convert::From<T> for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::from(t: T) -> T
 pub struct aya_ebpf::programs::LsmContext
 impl aya_ebpf::programs::lsm::LsmContext
 pub unsafe fn aya_ebpf::programs::lsm::LsmContext::arg<T: aya_ebpf::args::FromBtfArgument>(&self, n: usize) -> T
@@ -2733,6 +2796,8 @@ impl aya_ebpf::EbpfContext for aya_ebpf::programs::fentry::FEntryContext
 pub fn aya_ebpf::programs::fentry::FEntryContext::as_ptr(&self) -> *mut core::ffi::c_void
 impl aya_ebpf::EbpfContext for aya_ebpf::programs::fexit::FExitContext
 pub fn aya_ebpf::programs::fexit::FExitContext::as_ptr(&self) -> *mut core::ffi::c_void
+impl aya_ebpf::EbpfContext for aya_ebpf::programs::flow_dissector::FlowDissectorContext
+pub fn aya_ebpf::programs::flow_dissector::FlowDissectorContext::as_ptr(&self) -> *mut aya_ebpf_cty::c_void
 impl aya_ebpf::EbpfContext for aya_ebpf::programs::lsm::LsmContext
 pub fn aya_ebpf::programs::lsm::LsmContext::as_ptr(&self) -> *mut core::ffi::c_void
 impl aya_ebpf::EbpfContext for aya_ebpf::programs::perf_event::PerfEventContext

+ 2 - 0
xtask/public-api/aya-obj.txt

@@ -7655,6 +7655,7 @@ pub aya_obj::obj::ProgramSection::FEntry
 pub aya_obj::obj::ProgramSection::FEntry::sleepable: bool
 pub aya_obj::obj::ProgramSection::FExit
 pub aya_obj::obj::ProgramSection::FExit::sleepable: bool
+pub aya_obj::obj::ProgramSection::FlowDissector
 pub aya_obj::obj::ProgramSection::Iter
 pub aya_obj::obj::ProgramSection::Iter::sleepable: bool
 pub aya_obj::obj::ProgramSection::KProbe
@@ -8517,6 +8518,7 @@ pub aya_obj::ProgramSection::FEntry
 pub aya_obj::ProgramSection::FEntry::sleepable: bool
 pub aya_obj::ProgramSection::FExit
 pub aya_obj::ProgramSection::FExit::sleepable: bool
+pub aya_obj::ProgramSection::FlowDissector
 pub aya_obj::ProgramSection::Iter
 pub aya_obj::ProgramSection::Iter::sleepable: bool
 pub aya_obj::ProgramSection::KProbe

+ 191 - 0
xtask/public-api/aya.txt

@@ -3742,6 +3742,132 @@ impl<T> core::borrow::BorrowMut<T> for aya::programs::fexit::FExitLinkId where T
 pub fn aya::programs::fexit::FExitLinkId::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya::programs::fexit::FExitLinkId
 pub fn aya::programs::fexit::FExitLinkId::from(t: T) -> T
+pub mod aya::programs::flow_dissector
+pub struct aya::programs::flow_dissector::FlowDissector
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::attach<T: std::os::fd::owned::AsFd>(&mut self, netns: T) -> core::result::Result<aya::programs::flow_dissector::FlowDissectorLinkId, aya::programs::ProgramError>
+pub fn aya::programs::flow_dissector::FlowDissector::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::detach(&mut self, link_id: aya::programs::flow_dissector::FlowDissectorLinkId) -> core::result::Result<(), aya::programs::ProgramError>
+pub fn aya::programs::flow_dissector::FlowDissector::take_link(&mut self, link_id: aya::programs::flow_dissector::FlowDissectorLinkId) -> core::result::Result<aya::programs::flow_dissector::FlowDissectorLink, aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+pub fn aya::programs::flow_dissector::FlowDissector::unpin(self) -> core::result::Result<(), std::io::error::Error>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
+impl core::fmt::Debug for aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+impl core::ops::drop::Drop for aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::drop(&mut self)
+impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::flow_dissector::FlowDissector
+pub type &'a aya::programs::flow_dissector::FlowDissector::Error = aya::programs::ProgramError
+pub fn &'a aya::programs::flow_dissector::FlowDissector::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::flow_dissector::FlowDissector, aya::programs::ProgramError>
+impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::flow_dissector::FlowDissector
+pub type &'a mut aya::programs::flow_dissector::FlowDissector::Error = aya::programs::ProgramError
+pub fn &'a mut aya::programs::flow_dissector::FlowDissector::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::flow_dissector::FlowDissector, aya::programs::ProgramError>
+impl core::marker::Freeze for aya::programs::flow_dissector::FlowDissector
+impl core::marker::Send for aya::programs::flow_dissector::FlowDissector
+impl core::marker::Sync for aya::programs::flow_dissector::FlowDissector
+impl core::marker::Unpin for aya::programs::flow_dissector::FlowDissector
+impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::flow_dissector::FlowDissector
+impl core::panic::unwind_safe::UnwindSafe for aya::programs::flow_dissector::FlowDissector
+impl<T, U> core::convert::Into<U> for aya::programs::flow_dissector::FlowDissector where U: core::convert::From<T>
+pub fn aya::programs::flow_dissector::FlowDissector::into(self) -> U
+impl<T, U> core::convert::TryFrom<U> for aya::programs::flow_dissector::FlowDissector where U: core::convert::Into<T>
+pub type aya::programs::flow_dissector::FlowDissector::Error = core::convert::Infallible
+pub fn aya::programs::flow_dissector::FlowDissector::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
+impl<T, U> core::convert::TryInto<U> for aya::programs::flow_dissector::FlowDissector where U: core::convert::TryFrom<T>
+pub type aya::programs::flow_dissector::FlowDissector::Error = <U as core::convert::TryFrom<T>>::Error
+pub fn aya::programs::flow_dissector::FlowDissector::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
+impl<T> core::any::Any for aya::programs::flow_dissector::FlowDissector where T: 'static + ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissector::type_id(&self) -> core::any::TypeId
+impl<T> core::borrow::Borrow<T> for aya::programs::flow_dissector::FlowDissector where T: ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissector::borrow(&self) -> &T
+impl<T> core::borrow::BorrowMut<T> for aya::programs::flow_dissector::FlowDissector where T: ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissector::borrow_mut(&mut self) -> &mut T
+impl<T> core::convert::From<T> for aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::from(t: T) -> T
+pub struct aya::programs::flow_dissector::FlowDissectorLink(_)
+impl aya::programs::links::Link for aya::programs::flow_dissector::FlowDissectorLink
+pub type aya::programs::flow_dissector::FlowDissectorLink::Id = aya::programs::flow_dissector::FlowDissectorLinkId
+pub fn aya::programs::flow_dissector::FlowDissectorLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
+pub fn aya::programs::flow_dissector::FlowDissectorLink::id(&self) -> Self::Id
+impl core::cmp::Eq for aya::programs::flow_dissector::FlowDissectorLink
+impl core::cmp::PartialEq for aya::programs::flow_dissector::FlowDissectorLink
+pub fn aya::programs::flow_dissector::FlowDissectorLink::eq(&self, other: &Self) -> bool
+impl core::fmt::Debug for aya::programs::flow_dissector::FlowDissectorLink
+pub fn aya::programs::flow_dissector::FlowDissectorLink::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+impl core::hash::Hash for aya::programs::flow_dissector::FlowDissectorLink
+pub fn aya::programs::flow_dissector::FlowDissectorLink::hash<H: core::hash::Hasher>(&self, state: &mut H)
+impl core::ops::drop::Drop for aya::programs::flow_dissector::FlowDissectorLink
+pub fn aya::programs::flow_dissector::FlowDissectorLink::drop(&mut self)
+impl equivalent::Equivalent<aya::programs::flow_dissector::FlowDissectorLink> for aya::programs::flow_dissector::FlowDissectorLinkId
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::equivalent(&self, key: &aya::programs::flow_dissector::FlowDissectorLink) -> bool
+impl core::marker::Freeze for aya::programs::flow_dissector::FlowDissectorLink
+impl core::marker::Send for aya::programs::flow_dissector::FlowDissectorLink
+impl core::marker::Sync for aya::programs::flow_dissector::FlowDissectorLink
+impl core::marker::Unpin for aya::programs::flow_dissector::FlowDissectorLink
+impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::flow_dissector::FlowDissectorLink
+impl core::panic::unwind_safe::UnwindSafe for aya::programs::flow_dissector::FlowDissectorLink
+impl<Q, K> equivalent::Equivalent<K> for aya::programs::flow_dissector::FlowDissectorLink where Q: core::cmp::Eq + ?core::marker::Sized, K: core::borrow::Borrow<Q> + ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissectorLink::equivalent(&self, key: &K) -> bool
+impl<T, U> core::convert::Into<U> for aya::programs::flow_dissector::FlowDissectorLink where U: core::convert::From<T>
+pub fn aya::programs::flow_dissector::FlowDissectorLink::into(self) -> U
+impl<T, U> core::convert::TryFrom<U> for aya::programs::flow_dissector::FlowDissectorLink where U: core::convert::Into<T>
+pub type aya::programs::flow_dissector::FlowDissectorLink::Error = core::convert::Infallible
+pub fn aya::programs::flow_dissector::FlowDissectorLink::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
+impl<T, U> core::convert::TryInto<U> for aya::programs::flow_dissector::FlowDissectorLink where U: core::convert::TryFrom<T>
+pub type aya::programs::flow_dissector::FlowDissectorLink::Error = <U as core::convert::TryFrom<T>>::Error
+pub fn aya::programs::flow_dissector::FlowDissectorLink::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
+impl<T> core::any::Any for aya::programs::flow_dissector::FlowDissectorLink where T: 'static + ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissectorLink::type_id(&self) -> core::any::TypeId
+impl<T> core::borrow::Borrow<T> for aya::programs::flow_dissector::FlowDissectorLink where T: ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissectorLink::borrow(&self) -> &T
+impl<T> core::borrow::BorrowMut<T> for aya::programs::flow_dissector::FlowDissectorLink where T: ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissectorLink::borrow_mut(&mut self) -> &mut T
+impl<T> core::convert::From<T> for aya::programs::flow_dissector::FlowDissectorLink
+pub fn aya::programs::flow_dissector::FlowDissectorLink::from(t: T) -> T
+pub struct aya::programs::flow_dissector::FlowDissectorLinkId(_)
+impl core::cmp::Eq for aya::programs::flow_dissector::FlowDissectorLinkId
+impl core::cmp::PartialEq for aya::programs::flow_dissector::FlowDissectorLinkId
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::eq(&self, other: &aya::programs::flow_dissector::FlowDissectorLinkId) -> bool
+impl core::fmt::Debug for aya::programs::flow_dissector::FlowDissectorLinkId
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+impl core::hash::Hash for aya::programs::flow_dissector::FlowDissectorLinkId
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::hash<__H: core::hash::Hasher>(&self, state: &mut __H)
+impl core::marker::StructuralPartialEq for aya::programs::flow_dissector::FlowDissectorLinkId
+impl equivalent::Equivalent<aya::programs::flow_dissector::FlowDissectorLink> for aya::programs::flow_dissector::FlowDissectorLinkId
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::equivalent(&self, key: &aya::programs::flow_dissector::FlowDissectorLink) -> bool
+impl core::marker::Freeze for aya::programs::flow_dissector::FlowDissectorLinkId
+impl core::marker::Send for aya::programs::flow_dissector::FlowDissectorLinkId
+impl core::marker::Sync for aya::programs::flow_dissector::FlowDissectorLinkId
+impl core::marker::Unpin for aya::programs::flow_dissector::FlowDissectorLinkId
+impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::flow_dissector::FlowDissectorLinkId
+impl core::panic::unwind_safe::UnwindSafe for aya::programs::flow_dissector::FlowDissectorLinkId
+impl<Q, K> equivalent::Equivalent<K> for aya::programs::flow_dissector::FlowDissectorLinkId where Q: core::cmp::Eq + ?core::marker::Sized, K: core::borrow::Borrow<Q> + ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::equivalent(&self, key: &K) -> bool
+impl<T, U> core::convert::Into<U> for aya::programs::flow_dissector::FlowDissectorLinkId where U: core::convert::From<T>
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::into(self) -> U
+impl<T, U> core::convert::TryFrom<U> for aya::programs::flow_dissector::FlowDissectorLinkId where U: core::convert::Into<T>
+pub type aya::programs::flow_dissector::FlowDissectorLinkId::Error = core::convert::Infallible
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
+impl<T, U> core::convert::TryInto<U> for aya::programs::flow_dissector::FlowDissectorLinkId where U: core::convert::TryFrom<T>
+pub type aya::programs::flow_dissector::FlowDissectorLinkId::Error = <U as core::convert::TryFrom<T>>::Error
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
+impl<T> core::any::Any for aya::programs::flow_dissector::FlowDissectorLinkId where T: 'static + ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::type_id(&self) -> core::any::TypeId
+impl<T> core::borrow::Borrow<T> for aya::programs::flow_dissector::FlowDissectorLinkId where T: ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::borrow(&self) -> &T
+impl<T> core::borrow::BorrowMut<T> for aya::programs::flow_dissector::FlowDissectorLinkId where T: ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::borrow_mut(&mut self) -> &mut T
+impl<T> core::convert::From<T> for aya::programs::flow_dissector::FlowDissectorLinkId
+pub fn aya::programs::flow_dissector::FlowDissectorLinkId::from(t: T) -> T
 pub mod aya::programs::iter
 pub struct aya::programs::iter::Iter
 impl aya::programs::iter::Iter
@@ -4485,6 +4611,10 @@ impl aya::programs::links::Link for aya::programs::fexit::FExitLink
 pub type aya::programs::fexit::FExitLink::Id = aya::programs::fexit::FExitLinkId
 pub fn aya::programs::fexit::FExitLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
 pub fn aya::programs::fexit::FExitLink::id(&self) -> Self::Id
+impl aya::programs::links::Link for aya::programs::flow_dissector::FlowDissectorLink
+pub type aya::programs::flow_dissector::FlowDissectorLink::Id = aya::programs::flow_dissector::FlowDissectorLinkId
+pub fn aya::programs::flow_dissector::FlowDissectorLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
+pub fn aya::programs::flow_dissector::FlowDissectorLink::id(&self) -> Self::Id
 impl aya::programs::links::Link for aya::programs::iter::IterLink
 pub type aya::programs::iter::IterLink::Id = aya::programs::iter::IterLinkId
 pub fn aya::programs::iter::IterLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
@@ -7383,6 +7513,7 @@ pub aya::programs::Program::CgroupSysctl(aya::programs::cgroup_sysctl::CgroupSys
 pub aya::programs::Program::Extension(aya::programs::extension::Extension)
 pub aya::programs::Program::FEntry(aya::programs::fentry::FEntry)
 pub aya::programs::Program::FExit(aya::programs::fexit::FExit)
+pub aya::programs::Program::FlowDissector(aya::programs::flow_dissector::FlowDissector)
 pub aya::programs::Program::Iter(aya::programs::iter::Iter)
 pub aya::programs::Program::KProbe(aya::programs::kprobe::KProbe)
 pub aya::programs::Program::LircMode2(aya::programs::lirc_mode2::LircMode2)
@@ -7433,6 +7564,9 @@ pub fn &'a aya::programs::fentry::FEntry::try_from(program: &'a aya::programs::P
 impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::fexit::FExit
 pub type &'a aya::programs::fexit::FExit::Error = aya::programs::ProgramError
 pub fn &'a aya::programs::fexit::FExit::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::fexit::FExit, aya::programs::ProgramError>
+impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::flow_dissector::FlowDissector
+pub type &'a aya::programs::flow_dissector::FlowDissector::Error = aya::programs::ProgramError
+pub fn &'a aya::programs::flow_dissector::FlowDissector::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::flow_dissector::FlowDissector, aya::programs::ProgramError>
 impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::iter::Iter
 pub type &'a aya::programs::iter::Iter::Error = aya::programs::ProgramError
 pub fn &'a aya::programs::iter::Iter::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::iter::Iter, aya::programs::ProgramError>
@@ -7508,6 +7642,9 @@ pub fn &'a mut aya::programs::fentry::FEntry::try_from(program: &'a mut aya::pro
 impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::fexit::FExit
 pub type &'a mut aya::programs::fexit::FExit::Error = aya::programs::ProgramError
 pub fn &'a mut aya::programs::fexit::FExit::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::fexit::FExit, aya::programs::ProgramError>
+impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::flow_dissector::FlowDissector
+pub type &'a mut aya::programs::flow_dissector::FlowDissector::Error = aya::programs::ProgramError
+pub fn &'a mut aya::programs::flow_dissector::FlowDissector::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::flow_dissector::FlowDissector, aya::programs::ProgramError>
 impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::iter::Iter
 pub type &'a mut aya::programs::iter::Iter::Error = aya::programs::ProgramError
 pub fn &'a mut aya::programs::iter::Iter::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::iter::Iter, aya::programs::ProgramError>
@@ -8540,6 +8677,56 @@ impl<T> core::borrow::BorrowMut<T> for aya::programs::fexit::FExit where T: ?cor
 pub fn aya::programs::fexit::FExit::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya::programs::fexit::FExit
 pub fn aya::programs::fexit::FExit::from(t: T) -> T
+pub struct aya::programs::FlowDissector
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::attach<T: std::os::fd::owned::AsFd>(&mut self, netns: T) -> core::result::Result<aya::programs::flow_dissector::FlowDissectorLinkId, aya::programs::ProgramError>
+pub fn aya::programs::flow_dissector::FlowDissector::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::detach(&mut self, link_id: aya::programs::flow_dissector::FlowDissectorLinkId) -> core::result::Result<(), aya::programs::ProgramError>
+pub fn aya::programs::flow_dissector::FlowDissector::take_link(&mut self, link_id: aya::programs::flow_dissector::FlowDissectorLinkId) -> core::result::Result<aya::programs::flow_dissector::FlowDissectorLink, aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::from_pin<P: core::convert::AsRef<std::path::Path>>(path: P) -> core::result::Result<Self, aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::info(&self) -> core::result::Result<aya::programs::ProgramInfo, aya::programs::ProgramError>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+pub fn aya::programs::flow_dissector::FlowDissector::unpin(self) -> core::result::Result<(), std::io::error::Error>
+impl aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError>
+impl core::fmt::Debug for aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
+impl core::ops::drop::Drop for aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::drop(&mut self)
+impl<'a> core::convert::TryFrom<&'a aya::programs::Program> for &'a aya::programs::flow_dissector::FlowDissector
+pub type &'a aya::programs::flow_dissector::FlowDissector::Error = aya::programs::ProgramError
+pub fn &'a aya::programs::flow_dissector::FlowDissector::try_from(program: &'a aya::programs::Program) -> core::result::Result<&'a aya::programs::flow_dissector::FlowDissector, aya::programs::ProgramError>
+impl<'a> core::convert::TryFrom<&'a mut aya::programs::Program> for &'a mut aya::programs::flow_dissector::FlowDissector
+pub type &'a mut aya::programs::flow_dissector::FlowDissector::Error = aya::programs::ProgramError
+pub fn &'a mut aya::programs::flow_dissector::FlowDissector::try_from(program: &'a mut aya::programs::Program) -> core::result::Result<&'a mut aya::programs::flow_dissector::FlowDissector, aya::programs::ProgramError>
+impl core::marker::Freeze for aya::programs::flow_dissector::FlowDissector
+impl core::marker::Send for aya::programs::flow_dissector::FlowDissector
+impl core::marker::Sync for aya::programs::flow_dissector::FlowDissector
+impl core::marker::Unpin for aya::programs::flow_dissector::FlowDissector
+impl core::panic::unwind_safe::RefUnwindSafe for aya::programs::flow_dissector::FlowDissector
+impl core::panic::unwind_safe::UnwindSafe for aya::programs::flow_dissector::FlowDissector
+impl<T, U> core::convert::Into<U> for aya::programs::flow_dissector::FlowDissector where U: core::convert::From<T>
+pub fn aya::programs::flow_dissector::FlowDissector::into(self) -> U
+impl<T, U> core::convert::TryFrom<U> for aya::programs::flow_dissector::FlowDissector where U: core::convert::Into<T>
+pub type aya::programs::flow_dissector::FlowDissector::Error = core::convert::Infallible
+pub fn aya::programs::flow_dissector::FlowDissector::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
+impl<T, U> core::convert::TryInto<U> for aya::programs::flow_dissector::FlowDissector where U: core::convert::TryFrom<T>
+pub type aya::programs::flow_dissector::FlowDissector::Error = <U as core::convert::TryFrom<T>>::Error
+pub fn aya::programs::flow_dissector::FlowDissector::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
+impl<T> core::any::Any for aya::programs::flow_dissector::FlowDissector where T: 'static + ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissector::type_id(&self) -> core::any::TypeId
+impl<T> core::borrow::Borrow<T> for aya::programs::flow_dissector::FlowDissector where T: ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissector::borrow(&self) -> &T
+impl<T> core::borrow::BorrowMut<T> for aya::programs::flow_dissector::FlowDissector where T: ?core::marker::Sized
+pub fn aya::programs::flow_dissector::FlowDissector::borrow_mut(&mut self) -> &mut T
+impl<T> core::convert::From<T> for aya::programs::flow_dissector::FlowDissector
+pub fn aya::programs::flow_dissector::FlowDissector::from(t: T) -> T
 pub struct aya::programs::Iter
 impl aya::programs::iter::Iter
 pub fn aya::programs::iter::Iter::attach(&mut self) -> core::result::Result<aya::programs::iter::IterLinkId, aya::programs::ProgramError>
@@ -9580,6 +9767,10 @@ impl aya::programs::links::Link for aya::programs::fexit::FExitLink
 pub type aya::programs::fexit::FExitLink::Id = aya::programs::fexit::FExitLinkId
 pub fn aya::programs::fexit::FExitLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
 pub fn aya::programs::fexit::FExitLink::id(&self) -> Self::Id
+impl aya::programs::links::Link for aya::programs::flow_dissector::FlowDissectorLink
+pub type aya::programs::flow_dissector::FlowDissectorLink::Id = aya::programs::flow_dissector::FlowDissectorLinkId
+pub fn aya::programs::flow_dissector::FlowDissectorLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>
+pub fn aya::programs::flow_dissector::FlowDissectorLink::id(&self) -> Self::Id
 impl aya::programs::links::Link for aya::programs::iter::IterLink
 pub type aya::programs::iter::IterLink::Id = aya::programs::iter::IterLinkId
 pub fn aya::programs::iter::IterLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError>