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 pub struct XdpFlags: u32 {
13 const NONE = 0;
15 const UPDATE_IF_NOEXIST = libbpf_sys::XDP_FLAGS_UPDATE_IF_NOEXIST as _;
17 const SKB_MODE = libbpf_sys::XDP_FLAGS_SKB_MODE as _;
19 const DRV_MODE = libbpf_sys::XDP_FLAGS_DRV_MODE as _;
21 const HW_MODE = libbpf_sys::XDP_FLAGS_HW_MODE as _;
23 const REPLACE = libbpf_sys::XDP_FLAGS_REPLACE as _;
25 const MODES = libbpf_sys::XDP_FLAGS_MODES as _;
27 const MASK = libbpf_sys::XDP_FLAGS_MASK as _;
29 }
30
31}
32
33#[derive(Debug)]
37pub struct Xdp<'fd> {
38 fd: BorrowedFd<'fd>,
39 attach_opts: libbpf_sys::bpf_xdp_attach_opts,
40 query_opts: libbpf_sys::bpf_xdp_query_opts,
41}
42
43impl<'fd> Xdp<'fd> {
44 pub fn new(fd: BorrowedFd<'fd>) -> Self {
47 let mut xdp = Xdp {
48 fd,
49 attach_opts: libbpf_sys::bpf_xdp_attach_opts::default(),
50 query_opts: libbpf_sys::bpf_xdp_query_opts::default(),
51 };
52 xdp.attach_opts.sz = size_of::<libbpf_sys::bpf_xdp_attach_opts>() as libbpf_sys::size_t;
53 xdp.query_opts.sz = size_of::<libbpf_sys::bpf_xdp_query_opts>() as libbpf_sys::size_t;
54 xdp
55 }
56
57 pub fn attach(&self, ifindex: i32, flags: XdpFlags) -> Result<()> {
64 let ret = unsafe {
65 libbpf_sys::bpf_xdp_attach(
66 ifindex,
67 self.fd.as_raw_fd(),
68 flags.bits(),
69 &self.attach_opts,
70 )
71 };
72 util::parse_ret(ret)
73 }
74
75 pub fn detach(&self, ifindex: i32, flags: XdpFlags) -> Result<()> {
77 let ret = unsafe { libbpf_sys::bpf_xdp_detach(ifindex, flags.bits(), &self.attach_opts) };
78 util::parse_ret(ret)
79 }
80
81 pub fn query(&self, ifindex: i32, flags: XdpFlags) -> Result<libbpf_sys::bpf_xdp_query_opts> {
83 let mut opts = self.query_opts;
84 let err = unsafe { libbpf_sys::bpf_xdp_query(ifindex, flags.bits() as i32, &mut opts) };
85 util::parse_ret(err).map(|()| opts)
86 }
87
88 pub fn query_id(&self, ifindex: i32, flags: XdpFlags) -> Result<u32> {
90 let mut prog_id = 0;
91 let err =
92 unsafe { libbpf_sys::bpf_xdp_query_id(ifindex, flags.bits() as i32, &mut prog_id) };
93 util::parse_ret(err).map(|()| prog_id)
94 }
95
96 pub fn replace(&self, ifindex: i32, old_prog_fd: BorrowedFd<'_>) -> Result<()> {
98 let mut opts = self.attach_opts;
99 opts.old_prog_fd = old_prog_fd.as_raw_fd();
100 let ret = unsafe {
101 libbpf_sys::bpf_xdp_attach(
102 ifindex,
103 self.fd.as_raw_fd(),
104 XdpFlags::REPLACE.bits(),
105 &opts,
106 )
107 };
108 util::parse_ret(ret)
109 }
110}