aya: Add `XskMap::unset`

pull/492/head
arctic-alpaca 1 year ago committed by Tamir Duberstein
parent ea76e0f62d
commit 73a34e1571

@ -2,12 +2,12 @@
use std::{ use std::{
borrow::{Borrow, BorrowMut}, borrow::{Borrow, BorrowMut},
os::fd::{AsFd, AsRawFd, RawFd}, os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd},
}; };
use crate::{ use crate::{
maps::{MapData, MapError, check_bounds, check_kv_size}, maps::{MapData, MapError, check_bounds, check_kv_size},
sys::{SyscallError, bpf_map_update_elem}, sys::{SyscallError, bpf_map_delete_elem, bpf_map_update_elem},
}; };
/// An array of AF_XDP sockets. /// An array of AF_XDP sockets.
@ -57,6 +57,16 @@ impl<T: Borrow<MapData>> XskMap<T> {
} }
impl<T: BorrowMut<MapData>> XskMap<T> { impl<T: BorrowMut<MapData>> XskMap<T> {
fn with_fd(
&mut self,
index: u32,
f: impl FnOnce(BorrowedFd<'_>) -> Result<(), SyscallError>,
) -> Result<(), MapError> {
let data = self.inner.borrow_mut();
check_bounds(data, index)?;
f(data.fd().as_fd()).map_err(Into::into)
}
/// Sets the `AF_XDP` socket at a 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 /// When redirecting a packet, the `AF_XDP` socket at `index` will recieve the packet. Note
@ -68,14 +78,28 @@ impl<T: BorrowMut<MapData>> XskMap<T> {
/// 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(&mut self, index: u32, socket_fd: impl AsRawFd, 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(); self.with_fd(index, |fd| {
check_bounds(data, index)?; bpf_map_update_elem(fd, Some(&index), &socket_fd.as_raw_fd(), flags).map_err(
let fd = data.fd().as_fd(); |io_error| SyscallError {
bpf_map_update_elem(fd, Some(&index), &socket_fd.as_raw_fd(), flags)
.map_err(|io_error| SyscallError {
call: "bpf_map_update_elem", call: "bpf_map_update_elem",
io_error, io_error,
},
)
})
}
/// Un-sets the `AF_XDP` socket at a given index.
///
/// # Errors
///
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
/// if `bpf_map_delete_elem` fails.
pub fn unset(&mut self, index: u32) -> Result<(), MapError> {
self.with_fd(index, |fd| {
bpf_map_delete_elem(fd, &index).map_err(|io_error| SyscallError {
call: "bpf_map_delete_elem",
io_error,
})
}) })
.map_err(Into::into)
} }
} }

@ -26,12 +26,14 @@ fn af_xdp() {
xdp.load().unwrap(); xdp.load().unwrap();
xdp.attach("lo", XdpFlags::default()).unwrap(); xdp.attach("lo", XdpFlags::default()).unwrap();
const SIZE: usize = 2 * 4096;
// So this needs to be page aligned. Pages are 4k on all mainstream architectures except for // So this needs to be page aligned. Pages are 4k on all mainstream architectures except for
// Apple Silicon which uses 16k pages. So let's align on that for tests to run natively there. // Apple Silicon which uses 16k pages. So let's align on that for tests to run natively there.
#[repr(C, align(16384))] #[repr(C, align(16384))]
struct PageAligned([u8; 4096]); struct PageAligned([u8; SIZE]);
let mut alloc = Box::new(PageAligned([0; 4096])); let mut alloc = Box::new(PageAligned([0; SIZE]));
let umem = { let umem = {
let PageAligned(mem) = alloc.as_mut(); let PageAligned(mem) = alloc.as_mut();
let mem = mem.as_mut().into(); let mem = mem.as_mut().into();
@ -57,10 +59,12 @@ fn af_xdp() {
socks.set(0, rx.as_raw_fd(), 0).unwrap(); socks.set(0, rx.as_raw_fd(), 0).unwrap();
let frame = umem.frame(BufIdx(0)).unwrap(); let frame = umem.frame(BufIdx(0)).unwrap();
let frame1 = umem.frame(BufIdx(1)).unwrap();
// Produce a frame to be filled by the kernel // Produce two frames to be filled by the kernel
let mut writer = fq_cq.fill(1); let mut writer = fq_cq.fill(2);
writer.insert_once(frame.offset); writer.insert_once(frame.offset);
writer.insert_once(frame1.offset);
writer.commit(); writer.commit();
let sock = UdpSocket::bind("127.0.0.1:0").unwrap(); let sock = UdpSocket::bind("127.0.0.1:0").unwrap();
@ -81,6 +85,17 @@ fn af_xdp() {
assert_eq!(&udp[0..2], port.to_be_bytes().as_slice()); // Source assert_eq!(&udp[0..2], port.to_be_bytes().as_slice()); // Source
assert_eq!(&udp[2..4], 1777u16.to_be_bytes().as_slice()); // Dest assert_eq!(&udp[2..4], 1777u16.to_be_bytes().as_slice()); // Dest
assert_eq!(payload, b"hello AF_XDP"); assert_eq!(payload, b"hello AF_XDP");
assert_eq!(rx.available(), 1);
// Removes socket from map, no more packets will be redirected.
socks.unset(0).unwrap();
assert_eq!(rx.available(), 1);
sock.send_to(b"hello AF_XDP", "127.0.0.1:1777").unwrap();
assert_eq!(rx.available(), 1);
// Adds socket to map again, packets will be redirected again.
socks.set(0, rx.as_raw_fd(), 0).unwrap();
sock.send_to(b"hello AF_XDP", "127.0.0.1:1777").unwrap();
assert_eq!(rx.available(), 2);
} }
#[test] #[test]

@ -1084,6 +1084,7 @@ impl<T: core::borrow::Borrow<aya::maps::MapData>> aya::maps::XskMap<T>
pub fn aya::maps::XskMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::maps::XskMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(self, path: P) -> core::result::Result<(), aya::pin::PinError>
impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::XskMap<T> impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::XskMap<T>
pub fn aya::maps::XskMap<T>::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::XskMap<T>::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError>
pub fn aya::maps::XskMap<T>::unset(&mut self, index: u32) -> core::result::Result<(), aya::maps::MapError>
impl core::convert::TryFrom<aya::maps::Map> for aya::maps::XskMap<aya::maps::MapData> impl core::convert::TryFrom<aya::maps::Map> for aya::maps::XskMap<aya::maps::MapData>
pub type aya::maps::XskMap<aya::maps::MapData>::Error = aya::maps::MapError pub type aya::maps::XskMap<aya::maps::MapData>::Error = aya::maps::MapError
pub fn aya::maps::XskMap<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error> pub fn aya::maps::XskMap<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@ -2423,6 +2424,7 @@ impl<T: core::borrow::Borrow<aya::maps::MapData>> aya::maps::XskMap<T>
pub fn aya::maps::XskMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::maps::XskMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(self, path: P) -> core::result::Result<(), aya::pin::PinError>
impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::XskMap<T> impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::XskMap<T>
pub fn aya::maps::XskMap<T>::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> pub fn aya::maps::XskMap<T>::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError>
pub fn aya::maps::XskMap<T>::unset(&mut self, index: u32) -> core::result::Result<(), aya::maps::MapError>
impl core::convert::TryFrom<aya::maps::Map> for aya::maps::XskMap<aya::maps::MapData> impl core::convert::TryFrom<aya::maps::Map> for aya::maps::XskMap<aya::maps::MapData>
pub type aya::maps::XskMap<aya::maps::MapData>::Error = aya::maps::MapError pub type aya::maps::XskMap<aya::maps::MapData>::Error = aya::maps::MapError
pub fn aya::maps::XskMap<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error> pub fn aya::maps::XskMap<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>

Loading…
Cancel
Save