@@ -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 {
@@ -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
@@ -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;
}
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 <ciara.loftus@intel.com> --- 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(-)