1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use crate::{bindings::bpf_xdp_sock, btf_maps::btf_map_def, lookup};
btf_map_def!(
/// A BTF-compatible array of `AF_XDP` sockets.
///
/// XDP programs use this map to redirect packets to a target `AF_XDP`
/// socket via [`XskMap::redirect`]. Userspace populates each slot
/// with the socket's file descriptor; the kernel rejects redirection
/// when the socket's bound queue does not match the current RX queue.
///
/// # Minimum kernel version
///
/// The minimum kernel version required to use this feature is 4.18.
///
/// # Example
///
/// ```rust
/// use aya_ebpf::{btf_maps::XskMap, macros::btf_map};
///
/// #[btf_map]
/// static SOCKS: XskMap<8> = XskMap::new();
/// ```
pub struct XskMap<; const MAX_ENTRIES: usize, const FLAGS: usize = 0>,
map_type: BPF_MAP_TYPE_XSKMAP,
max_entries: MAX_ENTRIES,
map_flags: FLAGS,
key_type: u32,
value_type: u32,
);
impl<const MAX_ENTRIES: usize, const FLAGS: usize> XskMap<MAX_ENTRIES, FLAGS> {
const _CHECK: () = {
assert!(
MAX_ENTRIES > 0,
"XskMap max_entries must be greater than zero.",
);
};
/// Returns the queue id the socket at `index` is bound to.
///
/// Returns `None` when `index` is out of range or no socket has been
/// inserted there.
#[inline(always)]
pub fn get(&self, index: u32) -> Option<u32> {
let () = Self::_CHECK;
let value = lookup(self.as_ptr(), &index)?;
let value: &bpf_xdp_sock = unsafe { value.as_ref() };
Some(value.queue_id)
}
/// Redirects the current packet to the `AF_XDP` socket at `index`.
///
/// On lookup miss the kernel encodes the fallback XDP action in the
/// lower two bits of `flags`, propagated as the `Err` variant.
///
/// If the socket at `index` is bound to a RX queue other than the
/// current one, the kernel drops the packet.
#[inline(always)]
pub fn redirect(&self, index: u32, flags: u64) -> Result<u32, u32> {
let () = Self::_CHECK;
super::try_redirect_map(self.as_ptr(), index, flags)
}
}