diff options
| author | Alexander Lobakin <aleksander.lobakin@intel.com> | 2025-06-12 19:02:32 +0300 | 
|---|---|---|
| committer | Tony Nguyen <anthony.l.nguyen@intel.com> | 2025-06-16 21:40:15 +0300 | 
| commit | 5495c58c65aa3d650cccaa19dc59115b9a0069a5 (patch) | |
| tree | 3daff5094f628a535455e7e3884141cf937b2e58 /drivers/net/ethernet/intel/libeth | |
| parent | 40e846d122df9b299e700ec86d01ef647fc0b09f (diff) | |
| download | linux-5495c58c65aa3d650cccaa19dc59115b9a0069a5.tar.xz | |
libeth: xsk: add XSk Rx processing support
Add XSk counterparts for preparing XSk &libeth_xdp_buff (adding head and
frags), running the program, and handling the verdict, inc. XDP_PASS.
Shortcuts in comparison with regular Rx: frags and all verdicts except
XDP_REDIRECT are under unlikely() and out of line; no checks for XDP
program presence as it's always true for XSk.
Suggested-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> # optimizations
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/libeth')
| -rw-r--r-- | drivers/net/ethernet/intel/libeth/priv.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/libeth/xdp.c | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/libeth/xsk.c | 107 | 
3 files changed, 115 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/libeth/priv.h b/drivers/net/ethernet/intel/libeth/priv.h index 03e74382b2cb..9b811d31015c 100644 --- a/drivers/net/ethernet/intel/libeth/priv.h +++ b/drivers/net/ethernet/intel/libeth/priv.h @@ -8,6 +8,7 @@  /* XDP */ +enum xdp_action;  struct libeth_xdp_buff;  struct libeth_xdp_tx_frame;  struct skb_shared_info; @@ -17,6 +18,8 @@ extern const struct xsk_tx_metadata_ops libeth_xsktmo_slow;  void libeth_xsk_tx_return_bulk(const struct libeth_xdp_tx_frame *bq,  			       u32 count); +u32 libeth_xsk_prog_exception(struct libeth_xdp_buff *xdp, enum xdp_action act, +			      int ret);  struct libeth_xdp_ops {  	void	(*bulk)(const struct skb_shared_info *sinfo, diff --git a/drivers/net/ethernet/intel/libeth/xdp.c b/drivers/net/ethernet/intel/libeth/xdp.c index b5fb2ce92da8..d4ac027d9584 100644 --- a/drivers/net/ethernet/intel/libeth/xdp.c +++ b/drivers/net/ethernet/intel/libeth/xdp.c @@ -286,7 +286,8 @@ EXPORT_SYMBOL_GPL(libeth_xdp_buff_add_frag);   * @act: original XDP prog verdict   * @ret: error code if redirect failed   * - * External helper used by __libeth_xdp_run_prog(), do not call directly. + * External helper used by __libeth_xdp_run_prog() and + * __libeth_xsk_run_prog_slow(), do not call directly.   * Reports invalid @act, XDP exception trace event and frees the buffer.   *   * Return: libeth_xdp XDP prog verdict. @@ -300,6 +301,9 @@ u32 __cold libeth_xdp_prog_exception(const struct libeth_xdp_tx_bulk *bq,  	libeth_trace_xdp_exception(bq->dev, bq->prog, act); +	if (xdp->base.rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL) +		return libeth_xsk_prog_exception(xdp, act, ret); +  	libeth_xdp_return_buff_slow(xdp);  	return LIBETH_XDP_DROP; diff --git a/drivers/net/ethernet/intel/libeth/xsk.c b/drivers/net/ethernet/intel/libeth/xsk.c index f09e1940183b..f8f4016d1b25 100644 --- a/drivers/net/ethernet/intel/libeth/xsk.c +++ b/drivers/net/ethernet/intel/libeth/xsk.c @@ -38,3 +38,110 @@ void libeth_xsk_buff_free_slow(struct libeth_xdp_buff *xdp)  	xsk_buff_free(&xdp->base);  }  EXPORT_SYMBOL_GPL(libeth_xsk_buff_free_slow); + +/** + * libeth_xsk_buff_add_frag - add frag to XSk Rx buffer + * @head: head buffer + * @xdp: frag buffer + * + * External helper used by libeth_xsk_process_buff(), do not call directly. + * Frees both main and frag buffers on error. + * + * Return: main buffer with attached frag on success, %NULL on error (no space + * for a new frag). + */ +struct libeth_xdp_buff *libeth_xsk_buff_add_frag(struct libeth_xdp_buff *head, +						 struct libeth_xdp_buff *xdp) +{ +	if (!xsk_buff_add_frag(&head->base, &xdp->base)) +		goto free; + +	return head; + +free: +	libeth_xsk_buff_free_slow(xdp); +	libeth_xsk_buff_free_slow(head); + +	return NULL; +} +EXPORT_SYMBOL_GPL(libeth_xsk_buff_add_frag); + +/** + * libeth_xsk_buff_stats_frags - update onstack RQ stats with XSk frags info + * @rs: onstack stats to update + * @xdp: buffer to account + * + * External helper used by __libeth_xsk_run_pass(), do not call directly. + * Adds buffer's frags count and total len to the onstack stats. + */ +void libeth_xsk_buff_stats_frags(struct libeth_rq_napi_stats *rs, +				 const struct libeth_xdp_buff *xdp) +{ +	libeth_xdp_buff_stats_frags(rs, xdp); +} +EXPORT_SYMBOL_GPL(libeth_xsk_buff_stats_frags); + +/** + * __libeth_xsk_run_prog_slow - process the non-``XDP_REDIRECT`` verdicts + * @xdp: buffer to process + * @bq: Tx bulk for queueing on ``XDP_TX`` + * @act: verdict to process + * @ret: error code if ``XDP_REDIRECT`` failed + * + * External helper used by __libeth_xsk_run_prog(), do not call directly. + * ``XDP_REDIRECT`` is the most common and hottest verdict on XSk, thus + * it is processed inline. The rest goes here for out-of-line processing, + * together with redirect errors. + * + * Return: libeth_xdp XDP prog verdict. + */ +u32 __libeth_xsk_run_prog_slow(struct libeth_xdp_buff *xdp, +			       const struct libeth_xdp_tx_bulk *bq, +			       enum xdp_action act, int ret) +{ +	switch (act) { +	case XDP_DROP: +		xsk_buff_free(&xdp->base); + +		return LIBETH_XDP_DROP; +	case XDP_TX: +		return LIBETH_XDP_TX; +	case XDP_PASS: +		return LIBETH_XDP_PASS; +	default: +		break; +	} + +	return libeth_xdp_prog_exception(bq, xdp, act, ret); +} +EXPORT_SYMBOL_GPL(__libeth_xsk_run_prog_slow); + +/** + * libeth_xsk_prog_exception - handle XDP prog exceptions on XSk + * @xdp: buffer to process + * @act: verdict returned by the prog + * @ret: error code if ``XDP_REDIRECT`` failed + * + * Internal. Frees the buffer and, if the queue uses XSk wakeups, stop the + * current NAPI poll when there are no free buffers left. + * + * Return: libeth_xdp's XDP prog verdict. + */ +u32 __cold libeth_xsk_prog_exception(struct libeth_xdp_buff *xdp, +				     enum xdp_action act, int ret) +{ +	const struct xdp_buff_xsk *xsk; +	u32 __ret = LIBETH_XDP_DROP; + +	if (act != XDP_REDIRECT) +		goto drop; + +	xsk = container_of(&xdp->base, typeof(*xsk), xdp); +	if (xsk_uses_need_wakeup(xsk->pool) && ret == -ENOBUFS) +		__ret = LIBETH_XDP_ABORTED; + +drop: +	libeth_xsk_buff_free_slow(xdp); + +	return __ret; +}  | 
