Skip to main content

libbpf_rs/
xdp.rs

1use std::mem::size_of;
2use std::os::unix::io::AsRawFd;
3use std::os::unix::io::BorrowedFd;
4
5use bitflags::bitflags;
6
7use crate::util;
8use crate::Result;
9
10bitflags! {
11    /// Flags to configure the `XDP` operations
12    pub struct XdpFlags: u32 {
13        /// No flags.
14        const NONE              = 0;
15        /// See [`libbpf_sys::XDP_FLAGS_UPDATE_IF_NOEXIST`].
16        const UPDATE_IF_NOEXIST = libbpf_sys::XDP_FLAGS_UPDATE_IF_NOEXIST;
17        /// See [`libbpf_sys::XDP_FLAGS_SKB_MODE`].
18        const SKB_MODE          = libbpf_sys::XDP_FLAGS_SKB_MODE;
19        /// See [`libbpf_sys::XDP_FLAGS_DRV_MODE`].
20        const DRV_MODE          = libbpf_sys::XDP_FLAGS_DRV_MODE;
21        /// See [`libbpf_sys::XDP_FLAGS_HW_MODE`].
22        const HW_MODE           = libbpf_sys::XDP_FLAGS_HW_MODE;
23        /// See [`libbpf_sys::XDP_FLAGS_REPLACE`].
24        const REPLACE           = libbpf_sys::XDP_FLAGS_REPLACE;
25        /// See [`libbpf_sys::XDP_FLAGS_MODES`].
26        const MODES             = libbpf_sys::XDP_FLAGS_MODES;
27        /// See [`libbpf_sys::XDP_FLAGS_MASK`].
28        const MASK              = libbpf_sys::XDP_FLAGS_MASK;
29    }
30
31}
32
33/// Represents a XDP program.
34///
35/// This struct exposes operations to attach, detach and query a XDP program
36#[derive(Debug)]
37#[doc(alias = "bpf_xdp_attach_opts")]
38#[doc(alias = "bpf_xdp_query_opts")]
39pub struct Xdp<'fd> {
40    fd: BorrowedFd<'fd>,
41    attach_opts: libbpf_sys::bpf_xdp_attach_opts,
42    query_opts: libbpf_sys::bpf_xdp_query_opts,
43}
44
45impl<'fd> Xdp<'fd> {
46    /// Create a new XDP instance with the given file descriptor of the
47    /// `SEC("xdp")` [`Program`][crate::Program].
48    pub fn new(fd: BorrowedFd<'fd>) -> Self {
49        let mut xdp = Xdp {
50            fd,
51            attach_opts: libbpf_sys::bpf_xdp_attach_opts::default(),
52            query_opts: libbpf_sys::bpf_xdp_query_opts::default(),
53        };
54        xdp.attach_opts.sz = size_of::<libbpf_sys::bpf_xdp_attach_opts>() as libbpf_sys::size_t;
55        xdp.query_opts.sz = size_of::<libbpf_sys::bpf_xdp_query_opts>() as libbpf_sys::size_t;
56        xdp
57    }
58
59    /// Attach the XDP program to the given interface to start processing the
60    /// packets
61    ///
62    /// # Notes
63    /// Once a program is attached, it will outlive the userspace program. Make
64    /// sure to detach the program if its not desired.
65    #[doc(alias = "bpf_xdp_attach")]
66    pub fn attach(&self, ifindex: i32, flags: XdpFlags) -> Result<()> {
67        let ret = unsafe {
68            libbpf_sys::bpf_xdp_attach(
69                ifindex,
70                self.fd.as_raw_fd(),
71                flags.bits(),
72                &self.attach_opts,
73            )
74        };
75        util::parse_ret(ret)
76    }
77
78    /// Detach the XDP program from the interface
79    #[doc(alias = "bpf_xdp_detach")]
80    pub fn detach(&self, ifindex: i32, flags: XdpFlags) -> Result<()> {
81        let ret = unsafe { libbpf_sys::bpf_xdp_detach(ifindex, flags.bits(), &self.attach_opts) };
82        util::parse_ret(ret)
83    }
84
85    /// Query to inspect the program
86    #[doc(alias = "bpf_xdp_query")]
87    pub fn query(&self, ifindex: i32, flags: XdpFlags) -> Result<libbpf_sys::bpf_xdp_query_opts> {
88        let mut opts = self.query_opts;
89        let err = unsafe { libbpf_sys::bpf_xdp_query(ifindex, flags.bits() as i32, &mut opts) };
90        util::parse_ret(err).map(|()| opts)
91    }
92
93    /// Query to inspect the program identifier (`prog_id`)
94    #[doc(alias = "bpf_xdp_query_id")]
95    pub fn query_id(&self, ifindex: i32, flags: XdpFlags) -> Result<u32> {
96        let mut prog_id = 0;
97        let err =
98            unsafe { libbpf_sys::bpf_xdp_query_id(ifindex, flags.bits() as i32, &mut prog_id) };
99        util::parse_ret(err).map(|()| prog_id)
100    }
101
102    /// Replace an existing xdp program (identified by `old_prog_fd`) with this xdp program
103    #[doc(alias = "bpf_xdp_attach")]
104    pub fn replace(&self, ifindex: i32, old_prog_fd: BorrowedFd<'_>) -> Result<()> {
105        let mut opts = self.attach_opts;
106        opts.old_prog_fd = old_prog_fd.as_raw_fd();
107        let ret = unsafe {
108            libbpf_sys::bpf_xdp_attach(
109                ifindex,
110                self.fd.as_raw_fd(),
111                XdpFlags::REPLACE.bits(),
112                &opts,
113            )
114        };
115        util::parse_ret(ret)
116    }
117}