use bitflags::bitflags;
use libxdp_sys::{
XSK_RING_CONS__DEFAULT_NUM_DESCS, XSK_RING_PROD__DEFAULT_NUM_DESCS, xsk_socket_config,
xsk_socket_config__bindgen_ty_1,
};
use std::{
convert::{TryFrom, TryInto},
ffi::{CStr, CString, NulError},
str::FromStr,
};
use super::QueueSize;
bitflags! {
#[derive(Debug, Clone, Copy)]
pub struct LibxdpFlags: u32 {
const XSK_LIBXDP_FLAGS_INHIBIT_PROG_LOAD = 1;
}
}
bitflags! {
#[derive(Debug, Clone, Copy)]
pub struct XdpFlags: u32 {
const XDP_FLAGS_UPDATE_IF_NOEXIST = 1;
const XDP_FLAGS_SKB_MODE = 2;
const XDP_FLAGS_DRV_MODE = 4;
const XDP_FLAGS_HW_MODE = 8;
}
}
bitflags! {
#[derive(Debug, Clone, Copy)]
pub struct BindFlags: u16 {
const XDP_COPY = 2;
const XDP_ZEROCOPY = 4;
const XDP_USE_NEED_WAKEUP = 8;
const XDP_USE_SG = 16;
}
}
#[derive(Debug, Clone)]
pub struct Interface(CString);
impl Interface {
pub fn new(name: CString) -> Self {
Self(name)
}
pub(crate) fn as_cstr(&self) -> &CStr {
&self.0
}
}
impl FromStr for Interface {
type Err = NulError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.as_bytes().try_into()
}
}
impl TryFrom<&[u8]> for Interface {
type Error = NulError;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
CString::new(bytes).map(Self)
}
}
impl TryFrom<Vec<u8>> for Interface {
type Error = NulError;
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
CString::new(bytes).map(Self)
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct ConfigBuilder {
config: Config,
}
impl ConfigBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn rx_queue_size(&mut self, size: QueueSize) -> &mut Self {
self.config.rx_queue_size = size;
self
}
pub fn tx_queue_size(&mut self, size: QueueSize) -> &mut Self {
self.config.tx_queue_size = size;
self
}
pub fn libxdp_flags(&mut self, flags: LibxdpFlags) -> &mut Self {
self.config.libxdp_flags = flags;
self
}
pub fn xdp_flags(&mut self, flags: XdpFlags) -> &mut Self {
self.config.xdp_flags = flags;
self
}
pub fn bind_flags(&mut self, flags: BindFlags) -> &mut Self {
self.config.bind_flags = flags;
self
}
pub fn build(&self) -> Config {
self.config
}
}
#[derive(Debug, Clone, Copy)]
pub struct Config {
rx_queue_size: QueueSize,
tx_queue_size: QueueSize,
libxdp_flags: LibxdpFlags,
xdp_flags: XdpFlags,
bind_flags: BindFlags,
}
impl Config {
pub fn builder() -> ConfigBuilder {
ConfigBuilder::new()
}
pub fn rx_queue_size(&self) -> QueueSize {
self.rx_queue_size
}
pub fn tx_queue_size(&self) -> QueueSize {
self.tx_queue_size
}
pub fn libxdp_flags(&self) -> &LibxdpFlags {
&self.libxdp_flags
}
pub fn xdp_flags(&self) -> &XdpFlags {
&self.xdp_flags
}
pub fn bind_flags(&self) -> &BindFlags {
&self.bind_flags
}
}
impl Default for Config {
fn default() -> Self {
Self {
rx_queue_size: QueueSize(XSK_RING_CONS__DEFAULT_NUM_DESCS),
tx_queue_size: QueueSize(XSK_RING_PROD__DEFAULT_NUM_DESCS),
libxdp_flags: LibxdpFlags::empty(),
xdp_flags: XdpFlags::empty(),
bind_flags: BindFlags::empty(),
}
}
}
impl From<Config> for xsk_socket_config {
fn from(c: Config) -> Self {
let xsk_socket_config = xsk_socket_config__bindgen_ty_1 {
libxdp_flags: c.libxdp_flags.bits(),
};
xsk_socket_config {
rx_size: c.rx_queue_size.get(),
tx_size: c.tx_queue_size.get(),
xdp_flags: c.xdp_flags.bits(),
bind_flags: c.bind_flags.bits(),
__bindgen_anon_1: xsk_socket_config,
}
}
}