### Get available buffers in the completion ring (DeviceQueue) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Returns the difference between the kernel's producer state and our consumer head, indicating available buffers in the completion ring. ```rust pub fn available(&self) -> u32 { self.fcq.cons.count_pending() } ``` -------------------------------- ### User::statistics_v2 Source: https://docs.rs/xdpilone/latest/xdpilone/struct.User.html Get the statistics of this XDP socket, including additional statistics exposed on >= Linux 5.9. ```APIDOC ## User::statistics_v2 ### Description Get the statistics of this XDP socket. ### Method `&self` ### Returns `Result` ``` -------------------------------- ### Get XDP Socket Statistics (V2) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/umem.rs.html Retrieves detailed statistics for an XDP socket. This is the recommended method for newer kernel versions. ```rust pub fn statistics_v2(&self) -> Result { XdpStatisticsV2::new(&self.socket.fd) } ``` -------------------------------- ### Get raw file descriptor (DeviceQueue) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Retrieves the raw file descriptor for the socket. Safety: Use the file descriptor to attach the ring to an XSK map, but do not close or modify it unless you understand the implications. ```rust pub fn as_raw_fd(&self) -> libc::c_int { self.socket.fd.0 } ``` -------------------------------- ### Get pending buffers in the fill ring (DeviceQueue) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Returns the difference between our committed consumer state and the kernel's producer state, indicating pending buffers in the fill ring. ```rust pub fn pending(&self) -> u32 { self.fcq.prod.count_pending() } ``` -------------------------------- ### Umem::fq_cq Source: https://docs.rs/xdpilone/latest/xdpilone/struct.Umem.html Configures the fill and completion queues for a specific interface queue. This method is intended to be called once per interface queue, although multiple calls are not strictly incorrect but can complicate administration. The kernel expects a single producer-consumer (SPSC) setup for these queues. ```APIDOC ## pub fn fq_cq(&self, interface: &Socket) -> Result ### Description Configure the fill and completion queue for a interface queue. ### Details The caller _should_ only call this once for each interface info. However, it’s not entirely incorrect to do it multiple times. Just, be careful that the administration becomes extra messy. All code is written under the assumption that only one controller/writer for the user-space portions of each queue is active at a time. The kernel won’t care about your broken code and race conditions writing to the same queue concurrently. It’s an SPSC. Probably only the first call for each interface succeeds. ### Parameters * `interface` (Socket) - The socket associated with the interface queue. ### Returns * `Result` - Ok(DeviceQueue) on success, or an Errno on failure. ``` -------------------------------- ### Get raw file descriptor (FillQueue) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Retrieves the raw file descriptor for the socket. Safety: Use the file descriptor to attach the ring to an XSK map, but do not close or modify it unless you understand the implications. ```rust pub fn as_raw_fd(&self) -> libc::c_int { self.fd.0 } ``` -------------------------------- ### Get Available Buffers in Completion Queue (Rust) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Returns the number of pending buffers in the completion queue. This represents the difference between the kernel's producer state and the consumer's head pointer. ```rust pub fn available(&self) -> u32 { self.cons.count_pending() } ``` -------------------------------- ### Umem Source: https://docs.rs/xdpilone/latest/src/xdpilone/lib.rs.html The entrypoint to the library is an instance of `Umem`. It represents the user-space side of one or more XDP sockets and is used for memory management and interaction with XDP rings. ```APIDOC ## Umem ### Description Represents the user-space side of one or more XDP sockets. It is the primary entrypoint for interacting with the AF_XDP interface, managing memory allocations, and binding to network device queues. ### Usage Instantiate `Umem` to begin using the library's features for XDP socket operations. ``` -------------------------------- ### Type ID Implementation for Any Trait Source: https://docs.rs/xdpilone/latest/xdpilone/struct.CompletionQueue.html Provides the Get the `TypeId` of `self`. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### User::as_raw_fd Source: https://docs.rs/xdpilone/latest/xdpilone/struct.User.html Get the raw file descriptor number underlying this socket. ```APIDOC ## User::as_raw_fd ### Description Get the raw file descriptor number underlying this socket. ### Method `&self` ### Returns `i32` ``` -------------------------------- ### Configure Fill and Completion Queues Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/umem.rs.html Sets up the fill and completion queues for a given interface queue. This function ensures that the device is registered and then configures the necessary rings for packet data. ```rust /// Configure the fill and completion queue for a interface queue. /// /// The caller _should_ only call this once for each interface info. However, it's not entirely /// incorrect to do it multiple times. Just, be careful that the administration becomes extra /// messy. All code is written under the assumption that only one controller/writer for the /// user-space portions of each queue is active at a time. The kernel won't care about your /// broken code and race conditions writing to the same queue concurrently. It's an SPSC. /// Probably only the first call for each interface succeeds. pub fn fq_cq(&self, interface: &Socket) -> Result { if !self.devices.insert(interface.info.ctx) { // We know this will just yield `-EBUSY` anyways. return Err(Errno(libc::EINVAL)); } struct DropableDevice<'info>(&'info IfCtx, &'info DeviceControl); impl Drop for DropableDevice<'_> { fn drop(&mut self) { self.1.remove(self.0); } } // Okay, got a device. Let's create the queues for it. On failure, cleanup. let _tmp_device = DropableDevice(&interface.info.ctx, &self.devices); let sock = &*interface.fd; Self::configure_cq(sock, &self.config)?; let map = SocketMmapOffsets::new(sock)?; // FIXME: should we be configured the `cached_consumer` and `cached_producer` and // potentially other values, here? The setup produces a very rough clone of _just_ the ring // itself and none of the logic beyond. let prod = unsafe { RingProd::fill(sock, &map, self.config.fill_size) }?; let cons = unsafe { RingCons::comp(sock, &map, self.config.complete_size) }?; let device = DeviceQueue { fcq: DeviceRings { map, cons, prod }, socket: Socket { info: interface.info.clone(), fd: interface.fd.clone(), }, registration: DeviceQueueRegistration { devices: self.devices.clone(), ctx: interface.info.ctx, }, }; core::mem::forget(_tmp_device); Ok(device) } ``` -------------------------------- ### RingRx::as_raw_fd Source: https://docs.rs/xdpilone/latest/xdpilone/struct.RingRx.html Gets the raw file descriptor associated with the RingRx queue. ```APIDOC ## as_raw_fd ### Description Get the raw file descriptor of this RX ring. ### Safety Use the file descriptor to attach the ring to an XSK map, for instance, but do not close it and avoid modifying it (unless you know what you’re doing). It should be treated as a `BorrowedFd<'_>`. That said, it’s not instant UB but probably delayed UB when the `RingRx` modifies a reused file descriptor that it assumes to own… ### Method `as_raw_fd` ### Returns `c_int` - The raw file descriptor. ``` -------------------------------- ### Prepare buffers for the fill ring (DeviceQueue) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Use this method to prepare buffers for the fill ring. The argument is an upper bound of buffers. Use the resulting object to pass specific buffers to the fill queue and commit the write. ```rust pub fn fill(&mut self, max: u32) -> WriteFill<'_> { WriteFill { idx: BufIdxIter::reserve(&mut self.fcq.prod, max), queue: &mut self.fcq.prod, } } ``` -------------------------------- ### Configure UMEM Completion and Fill Rings Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/umem.rs.html Configures the completion and fill ring sizes for a UMEM socket using `setsockopt`. Requires the socket file descriptor and `UmemConfig` containing the desired sizes. ```rust pub(crate) fn configure_cq(fd: &SocketFd, config: &UmemConfig) -> Result<(), Errno> { if unsafe { libc::setsockopt( fd.0, super::SOL_XDP, Umem::XDP_UMEM_COMPLETION_RING, (&config.complete_size) as *const _ as *const libc::c_void, core::mem::size_of_val(&config.complete_size) as libc::socklen_t, ) } != 0 { return Err(LastErrno)?; } if unsafe { libc::setsockopt( fd.0, super::SOL_XDP, Umem::XDP_UMEM_FILL_RING, (&config.fill_size) as *const _ as *const libc::c_void, core::mem::size_of_val(&config.fill_size) as libc::socklen_t, ) } != 0 { return Err(LastErrno)?; } Ok(()) } ``` -------------------------------- ### Get WriteFill Queue Capacity Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Returns the total number of available buffers in the WriteFill queue. ```rust pub fn capacity(&self) -> u32 { self.idx.buffers } ``` -------------------------------- ### Setting XDP Interface Options Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/iface.rs.html This snippet demonstrates how to set XDP interface options, including different modes like OPT_LATEST. It handles potential errors during the process. ```rust tx: fixup_v1(v1.tx), fr: fixup_v1(v1.fr), cr: fixup_v1(v1.cr), }; Ok(()) } Self::OPT_LATEST => { self.inner = unsafe { off.latest }; Ok(()) } _ => Err(Errno(-libc::EINVAL)) } } ``` -------------------------------- ### Get IfInfo ifindex Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/iface.rs.html Retrieves the numeric kernel interface index (ifindex) for the identified interface. ```rust /// Get the `ifindex`, numeric ID of the interface in the kernel, for the identified interface. pub fn ifindex(&self) -> u32 { self.ctx.ifindex } // ... ``` -------------------------------- ### Create a raw XDP socket file descriptor Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/socket.rs.html Creates a raw file descriptor for an XDP socket using the `libc::socket` function. Returns an error if the socket creation fails. ```rust pub(crate) fn new() -> Result { let fd = unsafe { libc::socket(libc::AF_XDP, libc::SOCK_RAW, 0) }; if fd < 0 { return Err(LastErrno)?; } Ok(SocketFd(fd)) } ``` -------------------------------- ### Get IfInfo Interface Index Source: https://docs.rs/xdpilone/latest/xdpilone/struct.IfInfo.html Retrieves the numeric kernel identifier (ifindex) for the identified interface. ```rust pub fn ifindex(&self) -> u32 ``` -------------------------------- ### DeviceQueue Methods Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Methods for managing XDP socket queues, including buffer preparation, completion, status checks, and wake-up signaling. ```APIDOC ## DeviceQueue::fill ### Description Prepare some buffers for the fill ring. The argument is an upper bound of buffers. Use the resulting object to pass specific buffers to the fill queue and commit the write. ### Signature `pub fn fill(&mut self, max: u32) -> WriteFill<'_>` ``` ```APIDOC ## DeviceQueue::complete ### Description Reap some buffers from the completion ring. Return an iterator over completed buffers. The argument is an upper bound of buffers. Use the resulting object to dequeue specific buffers from the completion queue and commit the read. ### Signature `pub fn complete(&mut self, n: u32) -> ReadComplete<'_>` ``` ```APIDOC ## DeviceQueue::available ### Description Return the difference between our the kernel's producer state and our consumer head. ### Signature `pub fn available(&self) -> u32` ``` ```APIDOC ## DeviceQueue::pending ### Description Return the difference between our committed consumer state and the kernel's producer state. ### Signature `pub fn pending(&self) -> u32` ``` ```APIDOC ## DeviceQueue::as_raw_fd ### Description Get the raw file descriptor of this ring. # Safety Use the file descriptor to attach the ring to an XSK map, for instance, but do not close it and avoid modifying it (unless you know what you're doing). It should be treated as a `BorrowedFd<'_>`. ### Signature `pub fn as_raw_fd(&self) -> libc::c_int` ``` ```APIDOC ## DeviceQueue::needs_wakeup ### Description Query if the fill queue needs to be woken to proceed receiving. This is only accurate if `Umem::XDP_BIND_NEED_WAKEUP` was set. ### Signature `pub fn needs_wakeup(&self) -> bool` ``` ```APIDOC ## DeviceQueue::wake ### Description Poll the fill queue descriptor, to wake it up. ### Signature `pub fn wake(&mut self)` ``` ```APIDOC ## DeviceQueue::into_parts ### Description Splits the [`DeviceQueue`] into independent [`FillQueue`] and [`CompletionQueue`] halves. The device is deregistered when the last half is dropped. ### Signature `pub fn into_parts(self) -> (FillQueue, CompletionQueue)` ``` -------------------------------- ### Get IfInfo Queue ID Source: https://docs.rs/xdpilone/latest/xdpilone/struct.IfInfo.html Retrieves the queue ID that was previously set using the `set_queue` method. ```rust pub fn queue_id(&self) -> u32 ``` -------------------------------- ### Prepare buffers for the fill ring (FillQueue) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Use this method to prepare buffers for the fill ring. The argument is an upper bound of buffers. Use the resulting object to pass specific buffers to the fill queue and commit the write. ```rust pub fn fill(&mut self, max: u32) -> WriteFill<'_> { WriteFill { idx: BufIdxIter::reserve(&mut self.prod, max), queue: &mut self.prod, } } ``` -------------------------------- ### Initializing XdpStatisticsV2 from Socket Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/iface.rs.html This function initializes XdpStatisticsV2 by retrieving data from a given socket file descriptor. It ensures the statistics are correctly populated, similar to XdpStatistics. ```rust impl XdpStatisticsV2 { pub(crate) fn new(sock: &SocketFd) -> Result { let mut this = Self::default(); this.set_from_fd(sock)?; Ok(this) } pub(crate) fn set_from_fd(&mut self, sock: &SocketFd) -> Result<(), Errno> { let mut optlen: libc::socklen_t = core::mem::size_of_val(self) as libc::socklen_t; let err = unsafe { libc::getsockopt( sock.0, super::SOL_XDP, super::Umem::XDP_STATISTICS, self as *mut _ as *mut libc::c_void, &mut optlen, ) }; if err != 0 { return Err(LastErrno)?; } Ok(()) } } ``` -------------------------------- ### Get Raw File Descriptor Source: https://docs.rs/xdpilone/latest/xdpilone/struct.Socket.html Retrieves the raw file descriptor number underlying the socket. Returns an i32. ```rust pub fn as_raw_fd(&self) -> i32 ``` -------------------------------- ### Default UmemConfig Implementation Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk.rs.html Provides a default configuration for `UmemConfig` with predefined sizes for fill and completion buffers, and frame size. This is useful for setting up a default User Memory (Umem) configuration. ```rust impl Default for UmemConfig { fn default() -> Self { UmemConfig { fill_size: 1 << 11, complete_size: 1 << 11, frame_size: 1 << 12, headroom: 0, flags: 0, } } } ``` -------------------------------- ### Umem::configure_cq Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/umem.rs.html Configures the completion and fill rings for a given socket file descriptor. This is a crucial step for setting up UMEM for XDP operations. ```APIDOC ## Umem::configure_cq ### Description Configures the completion and fill rings for a given socket file descriptor. This is a crucial step for setting up UMEM for XDP operations. ### Method ``` pub(crate) fn configure_cq(fd: &SocketFd, config: &UmemConfig) -> Result<(), Errno> ``` ### Parameters #### Path Parameters - `fd` (*SocketFd*) - The socket file descriptor to configure. - `config` (*UmemConfig*) - The configuration for the completion and fill rings. ### Returns - `Ok(())` on successful configuration. - `Err(Errno)` if the configuration fails. ``` -------------------------------- ### Get WriteFill Capacity Source: https://docs.rs/xdpilone/latest/xdpilone/struct.WriteFill.html Retrieves the total number of available slots in the fill queue. Use this to determine how many descriptors can be inserted. ```rust pub fn capacity(&self) -> u32 ``` -------------------------------- ### User::statistics Source: https://docs.rs/xdpilone/latest/xdpilone/struct.User.html Get the statistics of this XDP socket. This method is deprecated and statistics_v2 is recommended for additional statistics exposed on >= Linux 5.9. ```APIDOC ## User::statistics ### Description Get the statistics of this XDP socket. ### Deprecated Consider using `statistics_v2` for additional statistics exposed on >= Linux 5.9. ### Method `&self` ### Returns `Result` ``` -------------------------------- ### Create a completion ring Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/ring.rs.html Safely creates a completion ring for XDP. Requires valid file descriptor and memory map offsets from the kernel. Returns a `Result` with the `RingCons` or an `Errno`. ```rust pub(crate) unsafe fn comp( fd: &SocketFd, off: &SocketMmapOffsets, count: u32, ) -> Result { let (inner, mmap_addr) = XskRing::map( fd, &off.inner.cr, count, core::mem::size_of::() as u64, XskRing::XDP_UMEM_PGOFF_COMPLETION_RING, )?; Ok(RingCons { inner, mmap_addr }) } ``` -------------------------------- ### Get Pointer to Address Descriptor Source: https://docs.rs/xdpilone/latest/xdpilone/struct.RingCons.html Retrieves a pointer to an address descriptor within the ring. This method requires the ring to be a Fill or Completion ring. ```rust pub unsafe fn comp_addr(&self, idx: BufIdx) -> NonNull ``` -------------------------------- ### take Source: https://docs.rs/xdpilone/latest/xdpilone/struct.ReadComplete.html Creates an iterator that yields the first `n` elements, or fewer if the underlying iterator ends sooner. ```APIDOC ## fn take(self, n: usize) -> Take ### Description Creates an iterator that yields the first `n` elements, or fewer if the underlying iterator ends sooner. ### Parameters #### Path Parameters - **n** (usize) - Required - The maximum number of elements to yield. ### Method Iterator adapter ``` -------------------------------- ### Get Pending Buffers Source: https://docs.rs/xdpilone/latest/xdpilone/struct.FillQueue.html Returns the difference between the committed consumer state and the kernel's producer state, indicating the number of pending buffers. ```rust pub fn pending(&self) -> u32 ``` -------------------------------- ### Initializing XdpStatistics from Socket Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/iface.rs.html This function initializes XdpStatistics by retrieving data from a given socket file descriptor. It ensures the statistics are correctly populated. ```rust impl XdpStatistics { pub(crate) fn new(sock: &SocketFd) -> Result { let mut this = Self::default(); this.set_from_fd(sock)?; Ok(this) } pub(crate) fn set_from_fd(&mut self, sock: &SocketFd) -> Result<(), Errno> { let mut optlen: libc::socklen_t = core::mem::size_of_val(self) as libc::socklen_t; let err = unsafe { libc::getsockopt( sock.0, super::SOL_XDP, super::Umem::XDP_STATISTICS, self as *mut _ as *mut libc::c_void, &mut optlen, ) }; if err != 0 { return Err(LastErrno)?; } Ok(()) } } ``` -------------------------------- ### SocketFd::new Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/socket.rs.html Internal method to create a raw XDP socket file descriptor. ```APIDOC ## new ### Description Creates a new raw XDP socket file descriptor. ### Signature ```rust pub(crate) fn new() -> Result ``` ### Returns A `Result` containing a `SocketFd` on success, or an `Errno` on failure. ``` -------------------------------- ### Get XDP Socket Statistics Source: https://docs.rs/xdpilone/latest/xdpilone/struct.DeviceQueue.html Retrieves the statistics for an XDP socket. Consider using `statistics_v2` for more detailed information on Linux kernel 5.9 and later. ```rust pub fn statistics(&self) -> Result ``` -------------------------------- ### Get Raw Errno Value Source: https://docs.rs/xdpilone/latest/xdpilone/struct.Errno.html Retrieves the raw integer value of the errno error. This can be used for direct comparison or logging of specific error codes. ```rust pub fn get_raw(&self) -> c_int ``` -------------------------------- ### DeviceQueue Raw File Descriptor and Wakeup Source: https://docs.rs/xdpilone/latest/xdpilone/struct.DeviceQueue.html Provides access to the raw file descriptor of the ring and a method to wake up the fill queue. ```APIDOC ## DeviceQueue ### `as_raw_fd()` **Description**: Get the raw file descriptor of this ring. **Safety**: Use the file descriptor to attach the ring to an XSK map, for instance, but do not close it and avoid modifying it (unless you know what you’re doing). It should be treated as a `BorrowedFd<'_>`. **Returns**: `c_int` ### `wake()` **Description**: Poll the fill queue descriptor, to wake it up. **Returns**: `()` ``` -------------------------------- ### Create an XDP socket with specific file descriptor and interface info Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/socket.rs.html Internal function to create an XDP socket, handling the retrieval of the network namespace cookie. It configures the socket with the provided interface information and file descriptor. ```rust fn with_xdp_socket(interface: &IfInfo, fd: Arc) -> Result { let mut info = Arc::new(*interface); let mut netnscookie: u64 = 0; let mut optlen: libc::socklen_t = core::mem::size_of_val(&netnscookie) as libc::socklen_t; let err = unsafe { libc::getsockopt( fd.0, libc::SOL_SOCKET, Self::SO_NETNS_COOKIE, (&mut netnscookie) as *mut _ as *mut libc::c_void, &mut optlen, ) }; match err { 0 => {} // Success libc::ENOPROTOOPT => netnscookie = Self::INIT_NS, // Protocol not available, use default _ => return Err(LastErrno)?, } // Won't reallocate in practice. Arc::make_mut(&mut info).ctx.netnscookie = netnscookie; Ok(Socket { fd, info }) } ``` -------------------------------- ### Count Pending Ring Entries Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/ring.rs.html Gets the raw difference between the consumer and producer heads in shared memory using relaxed loads. No synchronization is implied by this operation. ```rust pub fn count_pending(&self) -> u32 { let available = self.inner.producer.load(Ordering::Relaxed); let consumed = self.inner.consumer.load(Ordering::Relaxed); available.wrapping_sub(consumed) } ``` -------------------------------- ### FillQueue Methods Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Methods for managing the fill queue of an XDP socket. ```APIDOC ## FillQueue::fill ### Description Prepare some buffers for the fill ring. The argument is an upper bound of buffers. Use the resulting object to pass specific buffers to the fill queue and commit the write. ### Signature `pub fn fill(&mut self, max: u32) -> WriteFill<'_>` ``` ```APIDOC ## FillQueue::pending ### Description Return the difference between our committed consumer state and the kernel's producer state. ### Signature `pub fn pending(&self) -> u32` ``` ```APIDOC ## FillQueue::as_raw_fd ### Description Get the raw file descriptor of this ring. # Safety Use the file descriptor to attach the ring to an XSK map, for instance, but do not close it and avoid modifying it (unless you know what you're doing). It should be treated as a `BorrowedFd<'_>`. ### Signature `pub fn as_raw_fd(&self) -> libc::c_int` ``` -------------------------------- ### Get Pointer to XDP Frame Descriptor Source: https://docs.rs/xdpilone/latest/xdpilone/struct.RingCons.html Retrieves a pointer to an XDP frame descriptor within the ring. This method requires the ring to be a Receive or Transmit ring. ```rust pub unsafe fn rx_desc(&self, idx: BufIdx) -> NonNull ``` -------------------------------- ### Get Extended XDP Socket Statistics Source: https://docs.rs/xdpilone/latest/xdpilone/struct.DeviceQueue.html Retrieves extended statistics for an XDP socket, including additional details available on Linux kernel 5.9 and later. ```rust pub fn statistics_v2(&self) -> Result ``` -------------------------------- ### Clone Implementation for UmemConfig Source: https://docs.rs/xdpilone/latest/xdpilone/struct.UmemConfig.html Allows UmemConfig instances to be cloned. ```APIDOC ### impl Clone for UmemConfig #### fn clone(&self) -> UmemConfig Returns a duplicate of the value. ``` -------------------------------- ### Get Legacy XDP Socket Statistics Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/umem.rs.html Retrieves statistics for an XDP socket using the legacy method. Consider using `statistics_v2` for more comprehensive data on newer kernels. ```rust pub fn statistics(&self) -> Result { XdpStatistics::new(&self.socket.fd) } ``` -------------------------------- ### Default SocketConfig Implementation Source: https://docs.rs/xdpilone/latest/xdpilone/struct.SocketConfig.html Provides a default configuration for SocketConfig. This is useful for creating a basic socket configuration without specifying all parameters. ```rust fn default() -> SocketConfig ``` -------------------------------- ### RingProd Methods Source: https://docs.rs/xdpilone/latest/xdpilone/struct.RingProd.html Provides documentation for the public methods of the RingProd struct, including querying buffer status, reserving and submitting buffers, and checking flags. ```APIDOC ## pub fn count_free(&mut self, mininmum: u32) -> u32 ### Description Query for up to `nb` free entries. Serves small requests based on cached state about the kernel’s consumer head. Large requests may thus incur an extra refresh of the consumer head. ### Method `count_free` ### Parameters #### Path Parameters None #### Query Parameters * **mininmum** (u32) - Description: The minimum number of free entries to query for. #### Request Body None ### Response #### Success Response (u32) Returns the number of free entries available, up to the specified minimum. ### Request Example None ### Response Example None ``` ```APIDOC ## pub fn reserve(&mut self, nb: RangeInclusive, idx: &mut BufIdx) -> u32 ### Description Prepare consuming some buffers on our-side, not submitting to the kernel yet. Writes the index of the next available buffer into `idx`. Fails if less than the requested amount of buffers can be reserved. Returns the number of actual buffers reserved. ### Method `reserve` ### Parameters #### Path Parameters None #### Query Parameters * **nb** (RangeInclusive) - Description: The range of buffers to reserve. * **idx** (&mut BufIdx) - Description: A mutable reference to a BufIdx to store the index of the next available buffer. #### Request Body None ### Response #### Success Response (u32) Returns the number of actual buffers reserved. ### Request Example None ### Response Example None ``` ```APIDOC ## pub fn cancel(&mut self, nb: u32) ### Description Cancel a previous `reserve`. If passed a smaller number, the remaining reservation stays active. ### Method `cancel` ### Parameters #### Path Parameters None #### Query Parameters * **nb** (u32) - Description: The number of buffers to cancel. #### Request Body None ### Response None ### Request Example None ### Response Example None ``` ```APIDOC ## pub fn submit(&mut self, nb: u32) ### Description Submit a number of buffers. Note: the client side state is _not_ adjusted. If you’ve called `reserve` before please check to maintain a consistent view. TODO: interestingly this could be implemented on a shared reference. But is doing so useful? There’s no affirmation that the _intended_ buffers are submitted. ### Method `submit` ### Parameters #### Path Parameters None #### Query Parameters * **nb** (u32) - Description: The number of buffers to submit. #### Request Body None ### Response None ### Request Example None ### Response Example None ``` ```APIDOC ## pub fn count_pending(&self) -> u32 ### Description Get the raw difference between consumer and producer heads in shared memory. Both variables are loaded with _relaxed_ loads. No synchronization with any other memory operations is implied by calling this method. For this, you would need make sure to have some form of barrier, acquire on receiving and release on transmitting, for operations within chunks. ### Method `count_pending` ### Parameters None ### Response #### Success Response (u32) Returns the raw difference between consumer and producer heads. ### Request Example None ### Response Example None ``` ```APIDOC ## pub fn check_flags(&self) -> u32 ### Description Return the bits behind the `flags` register in the mmap. ### Method `check_flags` ### Parameters None ### Response #### Success Response (u32) Returns the bits of the flags register. ### Request Example None ### Response Example None ``` -------------------------------- ### UmemConfig Clone Implementation Source: https://docs.rs/xdpilone/latest/xdpilone/struct.UmemConfig.html Allows creating a duplicate of an existing UmemConfig instance. Useful for passing configurations around or modifying them without affecting the original. ```rust fn clone(&self) -> UmemConfig ``` -------------------------------- ### Count Pending Entries Source: https://docs.rs/xdpilone/latest/xdpilone/struct.RingCons.html Gets the raw difference between the consumer and producer heads in shared memory. Uses relaxed loads, implying no synchronization guarantees with other memory operations. ```rust pub fn count_pending(&self) -> u32 ``` -------------------------------- ### Get Pending Transmit Buffers (Rust) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Returns the number of pending buffers in the transmit ring. This is calculated as the difference between the committed producer state and the kernel's consumer head. ```rust pub fn pending(&self) -> u32 { self.ring.count_pending() } ``` -------------------------------- ### UmemConfig Default Implementation Source: https://docs.rs/xdpilone/latest/xdpilone/struct.UmemConfig.html Provides a default configuration for UmemConfig. Use this when a sensible default is needed and specific values are not critical. ```rust fn default() -> Self ``` -------------------------------- ### Get pending buffers in the fill ring (FillQueue) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Returns the difference between our committed consumer state and the kernel's producer state, indicating pending buffers in the fill ring. ```rust pub fn pending(&self) -> u32 { self.prod.count_pending() } ``` -------------------------------- ### ReadComplete TryInto Implementation Source: https://docs.rs/xdpilone/latest/xdpilone/struct.ReadComplete.html Details the `TryInto` implementation for the `ReadComplete` struct, including its associated error type and the `try_into` method. ```APIDOC ## impl TryInto for T where U: TryFrom ### Associated Type: Error `type Error = >::Error` The type returned in the event of a conversion error. ### Method: try_into `fn try_into(self) -> Result>::Error>` Performs the conversion. ``` -------------------------------- ### Get Receive Ring Descriptor Pointer Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/ring.rs.html Retrieves a raw pointer to an XDP frame descriptor in a receive ring. This method is unsafe and requires the ring to be a Receive or Transmit ring. ```rust pub unsafe fn rx_desc(&self, idx: BufIdx) -> NonNull { let offset = (idx.0 & self.inner.mask) as isize; let base = self.inner.ring.cast::().as_ptr(); // Safety: all offsets within `self.inner.mask` are valid in our mmap. unsafe { NonNull::new_unchecked(base.offset(offset)) } } ``` -------------------------------- ### WriteFill Methods Source: https://docs.rs/xdpilone/latest/xdpilone/struct.WriteFill.html This section details the methods available on the WriteFill struct for managing fill queues. These include checking capacity, inserting descriptors, and committing writes. ```APIDOC ## WriteFill A writer to a fill queue. Created with `DeviceQueue::fill`. ### Methods #### `capacity(&self) -> u32` The total number of available slots. #### `insert_once(&mut self, nr: u64) -> bool` Fill one device descriptor to be filled. A descriptor is an offset in the respective Umem’s memory. Any offset within a chunk can be used to mark the chunk as available for fill. The kernel will overwrite the contents arbitrarily until the chunk is returned via the RX queue. Returns if the insert was successful, that is false if the ring is full. It’s guaranteed that the first `WriteFill::capacity` inserts with this function succeed. #### `insert(&mut self, it: impl Iterator) -> u32` Fill additional slots that were reserved. The iterator is polled only for each available slot until either is empty. Returns the total number of slots filled. #### `commit(&mut self)` Commit the previously written buffers to the kernel. ``` -------------------------------- ### Get Completion Ring Address Pointer Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/ring.rs.html Retrieves a raw pointer to a 64-bit address descriptor in a completion ring. This method is unsafe and requires the ring to be a Fill or Completion ring. ```rust pub unsafe fn comp_addr(&self, idx: BufIdx) -> NonNull { let offset = (idx.0 & self.inner.mask) as isize; let base = self.inner.ring.cast::().as_ptr(); // Safety: all offsets within `self.inner.mask` are valid in our mmap. unsafe { NonNull::new_unchecked(base.offset(offset)) } } ``` -------------------------------- ### Create SocketMmapOffsets from socket Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/iface.rs.html Initializes SocketMmapOffsets by querying the mmap offsets from an XDP socket file descriptor. Returns an error if the query fails. ```rust impl SocketMmapOffsets { const OPT_V1: libc::socklen_t = core::mem::size_of::() as libc::socklen_t; const OPT_LATEST: libc::socklen_t = core::mem::size_of::() as libc::socklen_t; /// Query the socket mmap offsets of an XDP socket. pub fn new(sock: &SocketFd) -> Result { let mut this = SocketMmapOffsets { inner: Default::default(), }; this.set_from_fd(sock)?; Ok(this) } // ... ``` -------------------------------- ### Get transmit descriptor address Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/ring.rs.html Retrieves the memory address of a transmit descriptor at a given index within the ring buffer. This is an unsafe operation as it directly manipulates memory pointers. ```rust pub(crate) unsafe fn tx_desc(&self, idx: BufIdx) -> NonNull { let offset = (idx.0 & self.inner.mask) as isize; let base = self.inner.ring.cast::().as_ptr(); unsafe { NonNull::new_unchecked(base.offset(offset)) } } ``` -------------------------------- ### DeviceQueue Bind Source: https://docs.rs/xdpilone/latest/xdpilone/struct.DeviceQueue.html Binds the XDP socket to a device queue and activates the receive and transmit queues. ```APIDOC ## DeviceQueue ### `bind(interface: &User)` **Description**: Bind the socket to a device queue, activate rx/tx queues. **Parameters**: * `interface` (*User*) - The user interface to bind to. **Returns**: `Result<(), Errno>` ``` -------------------------------- ### Clone to Uninit IfInfo Source: https://docs.rs/xdpilone/latest/xdpilone/struct.IfInfo.html Performs copy-assignment from `self` to a raw pointer destination. This is an experimental nightly-only API. ```rust unsafe fn clone_to_uninit(&self, dest: *mut u8) ``` -------------------------------- ### Get Fill Ring Address Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/ring.rs.html Returns a mutable pointer to a `u64` in the fill ring, used for providing buffer addresses. The caller must ensure the `idx` is valid for the ring. ```rust pub(crate) unsafe fn fill_addr(&self, idx: BufIdx) -> NonNull { let offset = (idx.0 & self.inner.mask) as isize; let base = self.inner.ring.cast::().as_ptr(); unsafe { NonNull::new_unchecked(base.offset(offset)) } } ``` -------------------------------- ### Pointer Length Utility Function Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk.rs.html A helper function `ptr_len` to get the length of a byte slice pointed to by a raw pointer. This is a workaround for older Rust versions where `pointer::len` was not stabilized. ```rust // FIXME: pending stabilization, use pointer::len directly. // // // FIXME: In 1.79 this was stabilized. Bump MSRV fine? fn ptr_len(ptr: *mut [u8]) -> usize { unsafe { (&*(ptr as *mut [()])).len() } } ``` -------------------------------- ### Prepare Buffers for Fill Ring Source: https://docs.rs/xdpilone/latest/xdpilone/struct.FillQueue.html Prepares buffers for the fill ring. The argument is an upper bound of buffers. Use the resulting object to pass specific buffers to the fill queue and commit the write. ```rust pub fn fill(&mut self, max: u32) -> WriteFill<'_> ``` -------------------------------- ### CompletionQueue Methods Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Provides methods for interacting with the completion queue, allowing users to reap completed buffers and query available space. ```APIDOC ## complete ### Description Reap some buffers from the completion ring. ### Parameters - **n** (u32) - The upper bound of buffers to reap. ### Returns An iterator over completed buffers. ## available ### Description Return the difference between the kernel's producer state and the consumer head. ### Returns The number of available descriptors (u32). ## as_raw_fd ### Description Get the raw file descriptor of this ring. ### Safety Use the file descriptor to attach the ring to an XSK map, for instance, but do not close it and avoid modifying it. It should be treated as a `BorrowedFd<'_>`. ``` -------------------------------- ### Configure Fill and Completion Queues Source: https://docs.rs/xdpilone/latest/xdpilone/struct.Umem.html Configures the fill and completion queues for a given interface queue. This should ideally be called once per interface. Concurrent calls may lead to race conditions as these queues are Single Producer, Single Consumer (SPSC). ```rust pub fn fq_cq(&self, interface: &Socket) -> Result ``` -------------------------------- ### Get Buffer Descriptor Address Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/ring.rs.html Returns a mutable pointer to a buffer descriptor in the ring. This method is intended for use with fill and completion rings, and the caller must guarantee the validity of the provided `idx`. ```rust /// Return the address of a buffer descriptor. /// /// # Safety /// /// To be used only in fill and complete rings. Further, the caller guarantees that the `idx` /// parameter is valid for the ring. ``` -------------------------------- ### rx_tx Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/umem.rs.html Configures the device address for a socket, binding it to a device. At least one of `rx_size` or `tx_size` must be non-zero for the binding to succeed. ```APIDOC ## rx_tx ### Description Activates a socket by binding it to a device. This function configures the receive (RX) and transmit (TX) rings. It requires that either the RX or TX ring size (or both) be non-zero; otherwise, the binding will fail. If the underlying socket file descriptor is shared, this operation will also bind other objects sharing that descriptor. ### Method `rx_tx` ### Parameters - `interface` (`&Socket`): A reference to the Socket representing the interface to bind. - `config` (`&SocketConfig`): A reference to the SocketConfig containing the desired RX and TX ring sizes and other configuration options. ### Returns - `Result`: On success, returns a `User` struct containing the socket, configuration, and memory mapping offsets. On failure, returns an `Errno` indicating the error. ``` -------------------------------- ### Wake Transmit Queue (Rust) Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/user.rs.html Sends a message to wake up the transmit queue. This uses `MSG_DONTWAIT` for non-blocking behavior. It's important to handle potential errors, though this example currently ignores them. ```rust pub fn wake(&self) { // FIXME: should somehow log this on failure, right? let _ = unsafe { libc::sendto( self.fd.0, core::ptr::null_mut(), 0, libc::MSG_DONTWAIT, core::ptr::null_mut(), 0, ) }; } ``` -------------------------------- ### Socket::with_shared Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/socket.rs.html Creates a new XDP socket using the file descriptor of an existing UMEM. This is useful for sharing resources between multiple sockets. ```APIDOC ## with_shared ### Description Create a socket using the FD of the `umem`. ### Signature ```rust pub fn with_shared(interface: &IfInfo, umem: &Umem) -> Result ``` ### Parameters * `interface` - A reference to the `IfInfo` struct representing the network interface. * `umem` - A reference to the `Umem` struct whose file descriptor will be used. ``` -------------------------------- ### User::map_rx Source: https://docs.rs/xdpilone/latest/xdpilone/struct.User.html Map the RX ring into memory, returning a handle. Fails if no size was provided for rx_size in the configuration. ```APIDOC ## User::map_rx ### Description Map the RX ring into memory, returning a handle. ### Caveats Fails if you did not pass any size for `rx_size` in the configuration. FIXME: we allow mapping the ring more than once. Not a memory safety problem afaik, but a correctness problem. ### Method `&self` ### Returns `Result` ``` -------------------------------- ### Create an XDP socket using a shared UMEM file descriptor Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/socket.rs.html Creates a new XDP socket that shares the UMEM file descriptor with another socket. This is useful for scenarios where multiple sockets need to access the same memory region. ```rust pub fn with_shared(interface: &IfInfo, umem: &Umem) -> Result { Self::with_xdp_socket(interface, umem.fd.clone()) } ``` -------------------------------- ### Get Umem Buffer Address Source: https://docs.rs/xdpilone/latest/xdpilone/struct.Umem.html Retrieves the memory address associated with a specific buffer index within the Umem. Ensures the index is within bounds. Use of the returned pointer must be handled properly. ```rust pub fn frame(&self, idx: BufIdx) -> Option ``` -------------------------------- ### User::map_tx Source: https://docs.rs/xdpilone/latest/xdpilone/struct.User.html Map the TX ring into memory, returning a handle. Fails if no size was provided for tx_size in the configuration. ```APIDOC ## User::map_tx ### Description Map the TX ring into memory, returning a handle. ### Caveats Fails if you did not pass any size for `tx_size` in the configuration. FIXME: we allow mapping the ring more than once. Not a memory safety problem afaik, but a correctness problem. ### Method `&self` ### Returns `Result` ``` -------------------------------- ### Get Raw File Descriptor for User Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk.rs.html Provides a method `as_raw_fd` for the `User` struct to retrieve the raw file descriptor of its associated socket. This allows access to the underlying file descriptor through the `User` context. ```rust impl User { /// Get the raw file descriptor number underlying this socket. pub fn as_raw_fd(&self) -> i32 { self.socket.as_raw_fd() } } ``` -------------------------------- ### by_ref Source: https://docs.rs/xdpilone/latest/xdpilone/struct.ReadComplete.html Creates a “by reference” adapter for this instance of `Iterator`. ```APIDOC ## fn by_ref(&mut self) -> &mut Self ### Description Creates a “by reference” adapter for this instance of `Iterator`. ### Method Iterator adapter ``` -------------------------------- ### Get Raw File Descriptor of CompletionQueue Source: https://docs.rs/xdpilone/latest/xdpilone/struct.CompletionQueue.html Retrieves the raw file descriptor associated with the CompletionQueue. This is useful for attaching the ring to an XSK map. Safety: Do not close or modify the file descriptor; treat it as BorrowedFd. ```rust pub fn as_raw_fd(&self) -> c_int ``` -------------------------------- ### SockAddrXdp Default Implementation Source: https://docs.rs/xdpilone/latest/src/xdpilone/xdp.rs.html Provides a default implementation for SockAddrXdp, initializing fields to common values. ```rust impl Default for SockAddrXdp { fn default() -> Self { SockAddrXdp { family: libc::AF_XDP as u16, flags: 0, ifindex: 0, queue_id: 0, shared_umem_fd: 0, } } } ``` -------------------------------- ### Get Raw File Descriptor for Socket Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk.rs.html Provides a method `as_raw_fd` for the `Socket` struct to retrieve its underlying raw file descriptor. This is useful for interacting with lower-level system calls or other libraries that require a file descriptor. ```rust impl Socket { /// Get the raw file descriptor number underlying this socket. pub fn as_raw_fd(&self) -> i32 { self.fd.0 } } ``` -------------------------------- ### ReadComplete Iterator step_by Method Source: https://docs.rs/xdpilone/latest/xdpilone/struct.ReadComplete.html Creates a new iterator that steps by a specified amount at each iteration. ```rust fn step_by(self, step: usize) -> StepBy where Self: Sized, ``` -------------------------------- ### Get Frame Address from Umem Source: https://docs.rs/xdpilone/latest/src/xdpilone/xsk/umem.rs.html Retrieves the `UmemChunk` (address and size) for a given buffer index, if the index is within the bounds of the Umem area. It performs bounds checking based on the configured frame size and total area size. ```rust pub fn frame(&self, idx: BufIdx) -> Option { let pitch: u32 = self.config.frame_size; let idx: u32 = idx.0; let area_size = ptr_len(self.umem_area.as_ptr()) as u64; // Validate that it fits. let offset = u64::from(pitch) * u64::from(idx); if area_size.checked_sub(u64::from(pitch)) < Some(offset) { return None; } // Now: area_size is converted, without loss, from an isize that denotes the [u8] length, // valid as guaranteed by the caller of the constructor. We have just checked: // // `[offset..offset+pitch) < area_size`. // // So all of the following is within the bounds of the constructor-guaranteed // address manipulation. } ```