[RFC PATCH bpf-next 4/8] i40e: handle the XDP_REDIRECT_XSK action
From: Ciara Loftus <hidden>
Date: 2021-11-16 07:38:40
Also in:
bpf
Subsystem:
intel ethernet drivers, networking drivers, the rest · Maintainers:
Tony Nguyen, Przemek Kitszel, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
If the BPF program returns XDP_REDIRECT_XSK, obtain the pointer to the socket from the netdev_rx_queue struct and call the newly exposed xsk_rcv function to push the XDP descriptor to the Rx ring. Then use xsk_flush to flush the socket. Signed-off-by: Ciara Loftus <redacted> --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 +++++++++++- .../ethernet/intel/i40e/i40e_txrx_common.h | 1 + drivers/net/ethernet/intel/i40e/i40e_xsk.c | 21 +++++++++++++------ 3 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 10a83e5385c7..b6a883a8d088 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c@@ -4,6 +4,7 @@ #include <linux/prefetch.h> #include <linux/bpf_trace.h> #include <net/xdp.h> +#include <net/xdp_sock_drv.h> #include "i40e.h" #include "i40e_trace.h" #include "i40e_prototype.h"
@@ -2296,6 +2297,7 @@ static int i40e_run_xdp(struct i40e_ring *rx_ring, struct xdp_buff *xdp) int err, result = I40E_XDP_PASS; struct i40e_ring *xdp_ring; struct bpf_prog *xdp_prog; + struct xdp_sock *xs; u32 act; xdp_prog = READ_ONCE(rx_ring->xdp_prog);
@@ -2315,6 +2317,12 @@ static int i40e_run_xdp(struct i40e_ring *rx_ring, struct xdp_buff *xdp) if (result == I40E_XDP_CONSUMED) goto out_failure; break; + case XDP_REDIRECT_XSK: + xs = xsk_get_redirect_xsk(&rx_ring->netdev->_rx[xdp->rxq->queue_index]); + err = xsk_rcv(xs, xdp); + if (err) + goto out_failure; + return I40E_XDP_REDIR_XSK; case XDP_REDIRECT: err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); if (err)
@@ -2401,6 +2409,9 @@ void i40e_update_rx_stats(struct i40e_ring *rx_ring, **/ void i40e_finalize_xdp_rx(struct i40e_ring *rx_ring, unsigned int xdp_res) { + if (xdp_res & I40E_XDP_REDIR_XSK) + xsk_flush(xsk_get_redirect_xsk(&rx_ring->netdev->_rx[rx_ring->queue_index])); + if (xdp_res & I40E_XDP_REDIR) xdp_do_flush_map();
@@ -2516,7 +2527,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) } if (xdp_res) { - if (xdp_res & (I40E_XDP_TX | I40E_XDP_REDIR)) { + if (xdp_res & (I40E_XDP_TX | I40E_XDP_REDIR | I40E_XDP_REDIR_XSK)) { xdp_xmit |= xdp_res; i40e_rx_buffer_flip(rx_ring, rx_buffer, size); } else {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
index 19da3b22160f..17e521a71201 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h@@ -20,6 +20,7 @@ void i40e_release_rx_desc(struct i40e_ring *rx_ring, u32 val); #define I40E_XDP_CONSUMED BIT(0) #define I40E_XDP_TX BIT(1) #define I40E_XDP_REDIR BIT(2) +#define I40E_XDP_REDIR_XSK BIT(3) /* * build_ctob - Builds the Tx descriptor (cmd, offset and type) qword
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index ea06e957393e..31b794672ea5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c@@ -144,13 +144,14 @@ int i40e_xsk_pool_setup(struct i40e_vsi *vsi, struct xsk_buff_pool *pool, * @rx_ring: Rx ring * @xdp: xdp_buff used as input to the XDP program * - * Returns any of I40E_XDP_{PASS, CONSUMED, TX, REDIR} + * Returns any of I40E_XDP_{PASS, CONSUMED, TX, REDIR, REDIR_XSK} **/ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp) { int err, result = I40E_XDP_PASS; struct i40e_ring *xdp_ring; struct bpf_prog *xdp_prog; + struct xdp_sock *xs; u32 act; /* NB! xdp_prog will always be !NULL, due to the fact that
@@ -159,14 +160,21 @@ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp) xdp_prog = READ_ONCE(rx_ring->xdp_prog); act = bpf_prog_run_xdp(xdp_prog, xdp); - if (likely(act == XDP_REDIRECT)) { - err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); + if (likely(act == XDP_REDIRECT_XSK)) { + xs = xsk_get_redirect_xsk(&rx_ring->netdev->_rx[xdp->rxq->queue_index]); + err = xsk_rcv(xs, xdp); if (err) goto out_failure; - return I40E_XDP_REDIR; + return I40E_XDP_REDIR_XSK; } switch (act) { + case XDP_REDIRECT: + err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); + if (err) + goto out_failure; + result = I40E_XDP_REDIR; + break; case XDP_PASS: break; case XDP_TX:
@@ -275,7 +283,8 @@ static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring, *rx_packets = 1; *rx_bytes = size; - if (likely(xdp_res == I40E_XDP_REDIR) || xdp_res == I40E_XDP_TX) + if (likely(xdp_res == I40E_XDP_REDIR_XSK) || xdp_res == I40E_XDP_REDIR || + xdp_res == I40E_XDP_TX) return; if (xdp_res == I40E_XDP_CONSUMED) {
@@ -371,7 +380,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget) &rx_bytes, size, xdp_res); total_rx_packets += rx_packets; total_rx_bytes += rx_bytes; - xdp_xmit |= xdp_res & (I40E_XDP_TX | I40E_XDP_REDIR); + xdp_xmit |= xdp_res & (I40E_XDP_TX | I40E_XDP_REDIR | I40E_XDP_REDIR_XSK); next_to_clean = (next_to_clean + 1) & count_mask; }
--
2.17.1