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;
17 const SKB_MODE = libbpf_sys::XDP_FLAGS_SKB_MODE;
19 const DRV_MODE = libbpf_sys::XDP_FLAGS_DRV_MODE;
21 const HW_MODE = libbpf_sys::XDP_FLAGS_HW_MODE;
23 const REPLACE = libbpf_sys::XDP_FLAGS_REPLACE;
25 const MODES = libbpf_sys::XDP_FLAGS_MODES;
27 const MASK = libbpf_sys::XDP_FLAGS_MASK;
29 }
30
31}
32
33#[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 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 #[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 #[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 #[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 #[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 #[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}