maps/xdp: improve XDP maps documentation

reviewable/pr527/r4
Tuetuopay 2 years ago
parent c716c0160a
commit 1450b9be63

@ -128,6 +128,35 @@ pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream {
} }
} }
/// Marks a function as an eBPF XDP program that can be attached to a network interface.
///
/// On some NIC drivers, XDP probes are compatible with jumbo frames through the use of
/// multi-buffer packets. Programs can opt-in this support by passing the `frags = "true"` argument.
///
/// XDP programs can also be chained through the use of CPU maps and dev maps, but must opt-in
/// with the `map = "cpumap"` or `map = "devmap"` arguments.
///
/// # Minimum kernel version
///
/// The minimum kernel version required to use this feature is 4.8.
///
/// # Examples
///
/// ```no_run
/// use aya_bpf::{bindings::xdp_action::XDP_PASS, macros::xdp, programs::XdpContext};
///
/// #[xdp(frags = "true")]
/// pub fn xdp(ctx: XdpContext) -> u32 {
/// match unsafe { try_xdp(ctx) } {
/// Ok(ret) => ret,
/// Err(ret) => ret,
/// }
/// }
///
/// unsafe fn try_xdp(_ctx: XdpContext) -> Result<u32, u32> {
/// Ok(XDP_PASS)
/// }
/// ```
#[proc_macro_error] #[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn xdp(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn xdp(attrs: TokenStream, item: TokenStream) -> TokenStream {

@ -60,19 +60,19 @@ impl<T: Borrow<MapData>> CpuMap<T> {
self.inner.borrow().obj.max_entries() self.inner.borrow().obj.max_entries()
} }
/// Returns the value stored at the given index. /// Returns the queue size and possible program for a given CPU index.
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// Returns [`MapError::OutOfBounds`] if `cpu_index` is out of bounds,
/// if `bpf_map_lookup_elem` fails. /// [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails.
pub fn get(&self, index: u32, flags: u64) -> Result<CpuMapValue, MapError> { pub fn get(&self, cpu_index: u32, flags: u64) -> Result<CpuMapValue, MapError> {
let data = self.inner.borrow(); let data = self.inner.borrow();
check_bounds(data, index)?; check_bounds(data, cpu_index)?;
let fd = data.fd; let fd = data.fd;
let value = let value =
bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError { bpf_map_lookup_elem(fd, &cpu_index, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem", call: "bpf_map_lookup_elem",
io_error, io_error,
})?; })?;
@ -87,7 +87,18 @@ impl<T: Borrow<MapData>> CpuMap<T> {
} }
impl<T: BorrowMut<MapData>> CpuMap<T> { impl<T: BorrowMut<MapData>> CpuMap<T> {
/// Sets the value of the element at the given index. /// Sets the queue size at the given CPU index, and optionally a chained program.
///
/// When sending the packet to the CPU at the given index, the kernel will queue up to
/// `queue_size` packets before dropping them.
///
/// Another XDP program can be passed in that will be run on the target CPU, instead of the CPU
/// that receives the packets. This allows to perform minimal computations on CPUs that
/// directly handle packets from a NIC's RX queues, and perform possibly heavier ones in other,
/// less busy CPUs.
///
/// Note that only XDP programs with the `map = "cpumap"` argument can be passed. See the
/// kernel-space `aya_bpf::xdp` for more information.
/// ///
/// # Errors /// # Errors
/// ///
@ -95,22 +106,22 @@ impl<T: BorrowMut<MapData>> CpuMap<T> {
/// if `bpf_map_update_elem` fails. /// if `bpf_map_update_elem` fails.
pub fn set( pub fn set(
&mut self, &mut self,
index: u32, cpu_index: u32,
value: u32, queue_size: u32,
program: Option<impl AsRawFd>, program: Option<impl AsRawFd>,
flags: u64, flags: u64,
) -> Result<(), MapError> { ) -> Result<(), MapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
check_bounds(data, index)?; check_bounds(data, cpu_index)?;
let fd = data.fd; let fd = data.fd;
let value = bpf_cpumap_val { let value = bpf_cpumap_val {
qsize: value, qsize: queue_size,
bpf_prog: bpf_cpumap_val__bindgen_ty_1 { bpf_prog: bpf_cpumap_val__bindgen_ty_1 {
fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(),
}, },
}; };
bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| { bpf_map_update_elem(fd, Some(&cpu_index), &value, flags).map_err(|(_, io_error)| {
SyscallError { SyscallError {
call: "bpf_map_update_elem", call: "bpf_map_update_elem",
io_error, io_error,

@ -54,7 +54,7 @@ impl<T: Borrow<MapData>> DevMap<T> {
self.inner.borrow().obj.max_entries() self.inner.borrow().obj.max_entries()
} }
/// Returns the value stored at the given index. /// Returns the target ifindex and possible program at a given index.
/// ///
/// # Errors /// # Errors
/// ///
@ -81,7 +81,17 @@ impl<T: Borrow<MapData>> DevMap<T> {
} }
impl<T: BorrowMut<MapData>> DevMap<T> { impl<T: BorrowMut<MapData>> DevMap<T> {
/// Sets the value of the element at the given index. /// Sets the target ifindex at index, and optionally a chained program.
///
/// When redirecting using `index`, packets will be transmitted by the interface with
/// `ifindex`.
///
/// Another XDP program can be passed in that will be run before actual transmission. It can be
/// used to modify the packet before transmission with NIC specific data (MAC address update,
/// checksum computations, etc) or other purposes.
///
/// Note that only XDP programs with the `map = "devmap"` argument can be passed. See the
/// kernel-space `aya_bpf::xdp` for more information.
/// ///
/// # Errors /// # Errors
/// ///
@ -90,7 +100,7 @@ impl<T: BorrowMut<MapData>> DevMap<T> {
pub fn set( pub fn set(
&mut self, &mut self,
index: u32, index: u32,
value: u32, ifindex: u32,
program: Option<impl AsRawFd>, program: Option<impl AsRawFd>,
flags: u64, flags: u64,
) -> Result<(), MapError> { ) -> Result<(), MapError> {
@ -99,7 +109,7 @@ impl<T: BorrowMut<MapData>> DevMap<T> {
let fd = data.fd; let fd = data.fd;
let value = bpf_devmap_val { let value = bpf_devmap_val {
ifindex: value, ifindex,
bpf_prog: bpf_devmap_val__bindgen_ty_1 { bpf_prog: bpf_devmap_val__bindgen_ty_1 {
fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(),
}, },

@ -48,16 +48,14 @@ impl<T: Borrow<MapData>> DevMapHash<T> {
Ok(Self { inner: map }) Ok(Self { inner: map })
} }
/// Returns the value stored at the given index. /// Returns the target ifindex and possible program for a given key.
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// Returns [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails.
/// if `bpf_map_lookup_elem` fails. pub fn get(&self, key: u32, flags: u64) -> Result<DevMapValue, MapError> {
pub fn get(&self, index: u32, flags: u64) -> Result<DevMapValue, MapError> {
let fd = self.inner.borrow().fd; let fd = self.inner.borrow().fd;
let value = let value = bpf_map_lookup_elem(fd, &key, flags).map_err(|(_, io_error)| SyscallError {
bpf_map_lookup_elem(fd, &index, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem", call: "bpf_map_lookup_elem",
io_error, io_error,
})?; })?;
@ -77,28 +75,37 @@ impl<T: Borrow<MapData>> DevMapHash<T> {
} }
impl<T: BorrowMut<MapData>> DevMapHash<T> { impl<T: BorrowMut<MapData>> DevMapHash<T> {
/// Inserts a value in the map. /// Inserts an ifindex and optionally a chained program in the map.
///
/// When redirecting using `key`, packets will be transmitted by the interface with `ifindex`.
///
/// Another XDP program can be passed in that will be run before actual transmission. It can be
/// used to modify the packet before transmission with NIC specific data (MAC address update,
/// checksum computations, etc) or other purposes.
///
/// Note that only XDP programs with the `map = "devmap"` argument can be passed. See the
/// kernel-space `aya_bpf::xdp` for more information.
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails. /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
pub fn insert( pub fn insert(
&mut self, &mut self,
index: u32, key: u32,
value: u32, ifindex: u32,
program: Option<impl AsRawFd>, program: Option<impl AsRawFd>,
flags: u64, flags: u64,
) -> Result<(), MapError> { ) -> Result<(), MapError> {
let value = bpf_devmap_val { let value = bpf_devmap_val {
ifindex: value, ifindex,
bpf_prog: bpf_devmap_val__bindgen_ty_1 { bpf_prog: bpf_devmap_val__bindgen_ty_1 {
fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(), fd: program.map(|prog| prog.as_raw_fd()).unwrap_or_default(),
}, },
}; };
hash_map::insert(self.inner.borrow_mut(), &index, &value, flags) hash_map::insert(self.inner.borrow_mut(), &key, &value, flags)
} }
/// Remove a value from the map. /// Removes a value from the map.
/// ///
/// # Errors /// # Errors
/// ///

@ -52,17 +52,21 @@ impl<T: Borrow<MapData>> XskMap<T> {
} }
impl<T: BorrowMut<MapData>> XskMap<T> { impl<T: BorrowMut<MapData>> XskMap<T> {
/// Sets the value of the element at the given index. /// Sets the `AF_XDP` socket at a given index.
///
/// When redirecting a packet, the `AF_XDP` socket at `index` will recieve the packet. Note
/// that it will do so only if the socket is bound to the same queue the packet was recieved
/// on.
/// ///
/// # Errors /// # Errors
/// ///
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
/// if `bpf_map_update_elem` fails. /// if `bpf_map_update_elem` fails.
pub fn set<V: AsRawFd>(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> { pub fn set(&mut self, index: u32, socket_fd: impl AsRawFd, flags: u64) -> Result<(), MapError> {
let data = self.inner.borrow_mut(); let data = self.inner.borrow_mut();
check_bounds(data, index)?; check_bounds(data, index)?;
let fd = data.fd; let fd = data.fd;
bpf_map_update_elem(fd, Some(&index), &value.as_raw_fd(), flags).map_err( bpf_map_update_elem(fd, Some(&index), &socket_fd.as_raw_fd(), flags).map_err(
|(_, io_error)| SyscallError { |(_, io_error)| SyscallError {
call: "bpf_map_update_elem", call: "bpf_map_update_elem",
io_error, io_error,

@ -41,8 +41,8 @@ impl CpuMap {
/// Creates a [`CpuMap`] with a set maximum number of elements. /// Creates a [`CpuMap`] with a set maximum number of elements.
/// ///
/// In a CPU Map, an entry represents a CPU core. Thus there should be as many entries as there /// In a CPU Map, an entry represents a CPU core. Thus there should be as many entries as there
/// are CPU cores on the system. To dynamically set the entry count at runtime, refer to the /// are CPU cores on the system. It can be set to zero here, and updated by userspace at
/// userspace documentation. /// runtime. Refer to the userspace documentation for more information.
/// ///
/// # Examples /// # Examples
/// ///

Loading…
Cancel
Save