xdp_socket/
poll.rs

1//!
2//! # XDP Socket Poll Utilities
3//!
4//! This file provides utilities for polling XDP socket file descriptors. It enables waiting
5//! for readiness events such as readability or writability, which is essential for efficient
6//! I/O in high-performance networking scenarios. The utilities abstract low-level polling
7//! mechanisms and can be used to integrate XDP sockets with event-driven or blocking code.
8//!
9//! Since poll_wait is not a part of core API,
10//!   you have to import PollWait trait to enable it.
11//!
12//! ## How it works
13//!
14//! The `poll_wait` method blocks the current thread until the socket's file descriptor
15//! becomes ready for I/O. It uses `poll` to wait for the socket's readiness event,
16//! which depends on the socket direction:
17//! - For transmit sockets (`_TX`), it waits for the socket to be writable (`POLLOUT`).
18//! - For receive sockets (`_RX`), it waits for the socket to be readable (`POLLIN`).
19//!
20//! ## Main components
21//!
22//! - `impl PollWait<_TX>`: An implementation block for the transmit socket.
23//! - `impl PollWait<_RX>`: An implementation block for the receive socket.
24//! - `poll_wait()`: A method to block until a socket becomes ready for I/O.
25//!
26
27#![allow(non_upper_case_globals)]
28
29use crate::socket::{_Direction, _RX, _TX, Commit_, Socket};
30use std::io;
31use std::time::Duration;
32
33/// A trait for polling XDP sockets for readiness events.
34///
35/// This trait provides the `poll_wait` method, which blocks until the socket's file
36/// descriptor becomes ready for I/O. The readiness event depends on the socket direction:
37/// - For transmit sockets (`_TX`), it waits for the socket to be writable (`POLLOUT`).
38/// - For receive sockets (`_RX`), it waits for the socket to be readable (`POLLIN`).
39///
40/// # Type Parameters
41///
42/// * `t` - The direction of the socket (`_TX` or `_RX`).
43///
44/// # Example
45///
46/// ```rust
47/// use xdp_socket::{ create_socket, PollWaitExt as _ } ;
48/// let socket = ...; // your Socket<_TX> or Socket<_RX>
49/// socket.poll_wait(Some(std::time::Duration::from_secs(1)))?;
50/// ```
51pub trait PollWaitExt<const t: _Direction> {
52    fn poll_wait(&self, _timeout: Option<Duration>) -> Result<(), io::Error>;
53}
54
55impl<const t: _Direction> PollWaitExt<t> for Socket<t>
56where
57    Socket<t>: Commit_<t>,
58{
59    /// Waits for the socket to become ready for I/O, blocking until an event occurs.
60    ///
61    /// This function uses `poll` to wait for the socket's file descriptor to become
62    /// ready. For a `TxSocket`, it waits for `POLLOUT` (writable). For an `RxSocket`,
63    /// it waits for `POLLIN` (readable).
64    ///
65    /// # Arguments
66    ///
67    /// * `_timeout` - An optional timeout. If `None`, it blocks indefinitely.
68    ///
69    /// # Returns
70    ///
71    /// An `io::Result` indicating success or failure.
72    fn poll_wait(&self, _timeout: Option<Duration>) -> Result<(), io::Error> {
73        self.kick()?;
74        let mask = match t {
75            _TX => libc::POLLOUT,
76            _RX => libc::POLLIN,
77        };
78        unsafe {
79            loop {
80                let mut fds = [libc::pollfd {
81                    events: mask,
82                    revents: 0,
83                    fd: self.raw_fd,
84                }];
85                if 0 > libc::poll(fds.as_mut_ptr(), 1, -1) {
86                    //..
87                } else if (fds[0].revents & mask) != 0 {
88                    break;
89                }
90            }
91        }
92        Ok(())
93    }
94}