libeth_xdp_tx_xmit_bulk(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… libeth_xdp_tx_xmit_bulk β€” the main XDP Tx function, bestie

okay so this page lives in the Kernel API Manual (libeth_xdp_tx_xmit_bulk(9)), and it's literally the main XDP Tx function. no cap. sit down, grab a strawberry πŸ“, we're learning kernel networking.


✨ NAME ✨

libeth_xdp_tx_xmit_bulk β€” the main XDP Tx function. that's it, that's the whole name, and honestly? iconic.


🌈 SYNOPSIS 🌈

__nocfi_generic u32 libeth_xdp_tx_xmit_bulk (const struct
libeth_xdp_tx_frame *bulk , void *xdpsq , u32 n , bool unroll , u64 priv
, u32 (*prep)(void *xdpsq, struct libeth_xdpsq *sq) , struct
libeth_xdp_tx_desc (*fill)(struct libeth_xdp_tx_frame frm, u32 i, const
struct libeth_xdpsq *sq, u64 priv) , void (*xmit)(struct
libeth_xdp_tx_desc desc, u32 i, const struct libeth_xdpsq *sq, u64 priv)
);

like, look at all those callbacks. she's got range. πŸ’œ


πŸŽ€ ARGUMENTS πŸŽ€

  • bulk β€” array of frames to send. the whole squad, lined up 🫢
  • xdpsq β€” pointer to the driver-specific XDPSQ struct
  • n β€” number of frames to send. how many besties are we pushing out the door
  • unroll β€” whether to unroll the queue filling loop for speed. speedrun mode, basically πŸ”₯
  • priv β€” driver-specific private data. the little secret bag only the driver knows about πŸ™ˆ
  • prep β€” callback for cleaning the queue and filling abstract libeth_xdpsq. she does the tidying before the party
  • fill β€” internal callback for filling libeth_sqe and libeth_xdp_tx_desc
  • xmit β€” callback for filling a HW descriptor with the frame info. this is where the frame actually gets written down ✍️

πŸ’… DESCRIPTION πŸ’…

so this is an internal abstraction for placing n XDP Tx frames on the HW XDPSQ, and it's used for all types of frames: `XDP_TX, .ndo_xdp_xmit, XSk XDP_TX`, and XSk xmit. one function, every frame type, no notes. main character energy fr.

now the important bits, and lowkey this is a warning too so pay attention:

prep must lock the queue β€” because this function releases it at the end. so the lock/unlock is a two-person job, and only one of you is in this manpage. πŸ’€

unroll greatly increases the object code size, but also greatly increases XSk xmit performance. for other types of frames, it's not enabled. so like, big code, big speed, specific use case. know your vibe check.

and the cute low-level detail: the compilers inline all those onstack abstractions to direct data accesses. slay, honestly. 🧚


⭐ RETURN ⭐

number of frames actually placed on the queue, and that's <= n. the function can't fail, but it can send less frames if there's no enough free descriptors available. the actual free space is returned by prep from the driver.

so: never errors, sometimes under-delivers. relatable but make it kernel. 😭


πŸ‘‘ SEE ALSO πŸ‘‘

bestie this list is long, and every single one of these is getting its moment:

Kernel file ./include/net/libeth/xdp.h, struct libeth_xdp_buff(9), __LIBETH_XDP_ONSTACK_BUFF(9), LIBETH_XDP_ONSTACK_BUFF(9), libeth_xdpsq_num(9), libeth_xdpsq_shared(9), libeth_xdpsq_id(9), libeth_xdpsq_get(9), libeth_xdpsq_put(9), libeth_xdpsq_lock(9), libeth_xdpsq_unlock(9), libeth_xdpsq_deinit_timer(9), libeth_xdpsq_queue_timer(9), libeth_xdpsq_run_timer(9), enum (anonymous)(9), enum (anonymous)(9), struct libeth_xdp_tx_frame(9), struct libeth_xdp_tx_bulk(9), LIBETH_XDP_ONSTACK_BULK(9), struct libeth_xdpsq(9), struct libeth_xdp_tx_desc(9), libeth_xdp_ptr_to_priv(9), libeth_xdp_priv_to_ptr(9), libeth_xdp_tx_queue_head(9), libeth_xdp_tx_queue_frag(9), libeth_xdp_tx_queue_bulk(9), libeth_xdp_tx_fill_stats(9), libeth_xdp_tx_fill_buf(9), __libeth_xdp_tx_flush_bulk(9), libeth_xdp_tx_flush_bulk(9), libeth_xdp_xmit_init_bulk(9), libeth_xdp_xmit_frame_dma(9), libeth_xdp_xmit_queue_head(9), libeth_xdp_xmit_queue_frag(9), libeth_xdp_xmit_queue_bulk(9), libeth_xdp_xmit_fill_buf(9), libeth_xdp_xmit_flush_bulk(9), __libeth_xdp_xmit_do_bulk(9), libeth_xdp_xmit_do_bulk(9), libeth_xdp_tx_init_bulk(9), libeth_xdp_init_buff(9), libeth_xdp_save_buff(9), libeth_xdp_return_stash(9), libeth_xdp_return_buff(9), libeth_xdp_prepare_buff(9), libeth_xdp_process_buff(9), libeth_xdp_buff_stats_frags(9), __libeth_xdp_run_prog(9), __libeth_xdp_run_flush(9), libeth_xdp_run_prog(9), __libeth_xdp_run_pass(9), libeth_xdp_run_pass(9), libeth_xdp_finalize_rx(9), LIBETH_XDP_DEFINE_TIMER(9), LIBETH_XDP_DEFINE_FLUSH_TX(9), LIBETH_XDP_DEFINE_FLUSH_XMIT(9), LIBETH_XDP_DEFINE_RUN_PROG(9), LIBETH_XDP_DEFINE_RUN_PASS(9), LIBETH_XDP_DEFINE_RUN(9), LIBETH_XDP_DEFINE_FINALIZE(9), libeth_xdp_buff_to_rq(9), libeth_xdpmo_rx_hash(9), __libeth_xdp_complete_tx(9), libeth_xdp_set_features(9), libeth_xdp_set_features_noredir(9).

iykyk. πŸ“š


and that's the page, bestie β€” sourced straight from ./include/net/libeth, dated October 2026, and titled libeth_xdp_tx_xmit_bulk(9) like the queen she is. go forth and Tx responsibly πŸ¦‹πŸ’–

πŸ“¦ where this page comes from