Skip to content

Commit

Permalink
bpf, devmap: Move drop error path to devmap for XDP_REDIRECT
Browse files Browse the repository at this point in the history
We want to change the current ndo_xdp_xmit drop semantics because it will
allow us to implement better queue overflow handling. This is working
towards the larger goal of a XDP TX queue-hook. Move XDP_REDIRECT error
path handling from each XDP ethernet driver to devmap code. According to
the new APIs, the driver running the ndo_xdp_xmit pointer, will break tx
loop whenever the hw reports a tx error and it will just return to devmap
caller the number of successfully transmitted frames. It will be devmap
responsibility to free dropped frames.

Move each XDP ndo_xdp_xmit capable driver to the new APIs:

- veth
- virtio-net
- mvneta
- mvpp2
- socionext
- amazon ena
- bnxt
- freescale (dpaa2, dpaa)
- xen-frontend
- qede
- ice
- igb
- ixgbe
- i40e
- mlx5
- ti (cpsw, cpsw-new)
- tun
- sfc

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Camelia Groza <camelia.groza@nxp.com>
Acked-by: Edward Cree <ecree.xilinx@gmail.com>
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
Acked-by: Shay Agroskin <shayagr@amazon.com>
Link: https://lore.kernel.org/bpf/ed670de24f951cfd77590decf0229a0ad7fd12f6.1615201152.git.lorenzo@kernel.org
  • Loading branch information
Lorenzo Bianconi authored and Daniel Borkmann committed Mar 18, 2021
1 parent 6b28276 commit fdc1397
Show file tree
Hide file tree
Showing 22 changed files with 153 additions and 200 deletions.
21 changes: 9 additions & 12 deletions drivers/net/ethernet/amazon/ena/ena_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ static int ena_xdp_xmit_frame(struct ena_ring *xdp_ring,

rc = ena_xdp_tx_map_frame(xdp_ring, tx_info, xdpf, &push_hdr, &push_len);
if (unlikely(rc))
goto error_drop_packet;
return rc;

ena_tx_ctx.ena_bufs = tx_info->bufs;
ena_tx_ctx.push_header = push_hdr;
Expand Down Expand Up @@ -330,17 +330,15 @@ static int ena_xdp_xmit_frame(struct ena_ring *xdp_ring,
error_unmap_dma:
ena_unmap_tx_buff(xdp_ring, tx_info);
tx_info->xdpf = NULL;
error_drop_packet:
xdp_return_frame(xdpf);
return rc;
}

static int ena_xdp_xmit(struct net_device *dev, int n,
struct xdp_frame **frames, u32 flags)
{
struct ena_adapter *adapter = netdev_priv(dev);
int qid, i, err, drops = 0;
struct ena_ring *xdp_ring;
int qid, i, nxmit = 0;

if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
return -EINVAL;
Expand All @@ -360,12 +358,9 @@ static int ena_xdp_xmit(struct net_device *dev, int n,
spin_lock(&xdp_ring->xdp_tx_lock);

for (i = 0; i < n; i++) {
err = ena_xdp_xmit_frame(xdp_ring, dev, frames[i], 0);
/* The descriptor is freed by ena_xdp_xmit_frame in case
* of an error.
*/
if (err)
drops++;
if (ena_xdp_xmit_frame(xdp_ring, dev, frames[i], 0))
break;
nxmit++;
}

/* Ring doorbell to make device aware of the packets */
Expand All @@ -378,7 +373,7 @@ static int ena_xdp_xmit(struct net_device *dev, int n,
spin_unlock(&xdp_ring->xdp_tx_lock);

/* Return number of packets sent */
return n - drops;
return nxmit;
}

static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp)
Expand Down Expand Up @@ -415,7 +410,9 @@ static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp)
/* The XDP queues are shared between XDP_TX and XDP_REDIRECT */
spin_lock(&xdp_ring->xdp_tx_lock);

ena_xdp_xmit_frame(xdp_ring, rx_ring->netdev, xdpf, XDP_XMIT_FLUSH);
if (ena_xdp_xmit_frame(xdp_ring, rx_ring->netdev, xdpf,
XDP_XMIT_FLUSH))
xdp_return_frame(xdpf);

spin_unlock(&xdp_ring->xdp_tx_lock);
xdp_stat = &rx_ring->rx_stats.xdp_tx;
Expand Down
20 changes: 8 additions & 12 deletions drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ int bnxt_xdp_xmit(struct net_device *dev, int num_frames,
struct pci_dev *pdev = bp->pdev;
struct bnxt_tx_ring_info *txr;
dma_addr_t mapping;
int drops = 0;
int nxmit = 0;
int ring;
int i;

Expand All @@ -233,21 +233,17 @@ int bnxt_xdp_xmit(struct net_device *dev, int num_frames,
struct xdp_frame *xdp = frames[i];

if (!txr || !bnxt_tx_avail(bp, txr) ||
!(bp->bnapi[ring]->flags & BNXT_NAPI_FLAG_XDP)) {
xdp_return_frame_rx_napi(xdp);
drops++;
continue;
}
!(bp->bnapi[ring]->flags & BNXT_NAPI_FLAG_XDP))
break;

mapping = dma_map_single(&pdev->dev, xdp->data, xdp->len,
DMA_TO_DEVICE);

if (dma_mapping_error(&pdev->dev, mapping)) {
xdp_return_frame_rx_napi(xdp);
drops++;
continue;
}
if (dma_mapping_error(&pdev->dev, mapping))
break;

__bnxt_xmit_xdp_redirect(bp, txr, mapping, xdp->len, xdp);
nxmit++;
}

if (flags & XDP_XMIT_FLUSH) {
Expand All @@ -256,7 +252,7 @@ int bnxt_xdp_xmit(struct net_device *dev, int num_frames,
bnxt_db_write(bp, &txr->tx_db, txr->tx_prod);
}

return num_frames - drops;
return nxmit;
}

/* Under rtnl_lock */
Expand Down
12 changes: 5 additions & 7 deletions drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -3081,7 +3081,7 @@ static int dpaa_xdp_xmit(struct net_device *net_dev, int n,
struct xdp_frame **frames, u32 flags)
{
struct xdp_frame *xdpf;
int i, err, drops = 0;
int i, nxmit = 0;

if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
return -EINVAL;
Expand All @@ -3091,14 +3091,12 @@ static int dpaa_xdp_xmit(struct net_device *net_dev, int n,

for (i = 0; i < n; i++) {
xdpf = frames[i];
err = dpaa_xdp_xmit_frame(net_dev, xdpf);
if (err) {
xdp_return_frame_rx_napi(xdpf);
drops++;
}
if (dpaa_xdp_xmit_frame(net_dev, xdpf))
break;
nxmit++;
}

return n - drops;
return nxmit;
}

static int dpaa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -2431,8 +2431,6 @@ static int dpaa2_eth_xdp_xmit(struct net_device *net_dev, int n,
percpu_stats->tx_packets += enqueued;
for (i = 0; i < enqueued; i++)
percpu_stats->tx_bytes += dpaa2_fd_get_len(&fds[i]);
for (i = enqueued; i < n; i++)
xdp_return_frame_rx_napi(frames[i]);

return enqueued;
}
Expand Down
15 changes: 7 additions & 8 deletions drivers/net/ethernet/intel/i40e/i40e_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -3847,8 +3847,8 @@ netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* @frames: array of XDP buffer pointers
* @flags: XDP extra info
*
* Returns number of frames successfully sent. Frames that fail are
* free'ed via XDP return API.
* Returns number of frames successfully sent. Failed frames
* will be free'ed by XDP core.
*
* For error cases, a negative errno code is returned and no-frames
* are transmitted (caller must handle freeing frames).
Expand All @@ -3861,7 +3861,7 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
struct i40e_vsi *vsi = np->vsi;
struct i40e_pf *pf = vsi->back;
struct i40e_ring *xdp_ring;
int drops = 0;
int nxmit = 0;
int i;

if (test_bit(__I40E_VSI_DOWN, vsi->state))
Expand All @@ -3881,14 +3881,13 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
int err;

err = i40e_xmit_xdp_ring(xdpf, xdp_ring);
if (err != I40E_XDP_TX) {
xdp_return_frame_rx_napi(xdpf);
drops++;
}
if (err != I40E_XDP_TX)
break;
nxmit++;
}

if (unlikely(flags & XDP_XMIT_FLUSH))
i40e_xdp_ring_update_tail(xdp_ring);

return n - drops;
return nxmit;
}
15 changes: 7 additions & 8 deletions drivers/net/ethernet/intel/ice/ice_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@ ice_run_xdp(struct ice_ring *rx_ring, struct xdp_buff *xdp,
* @frames: XDP frames to be transmitted
* @flags: transmit flags
*
* Returns number of frames successfully sent. Frames that fail are
* free'ed via XDP return API.
* Returns number of frames successfully sent. Failed frames
* will be free'ed by XDP core.
* For error cases, a negative errno code is returned and no-frames
* are transmitted (caller must handle freeing frames).
*/
Expand All @@ -584,7 +584,7 @@ ice_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
unsigned int queue_index = smp_processor_id();
struct ice_vsi *vsi = np->vsi;
struct ice_ring *xdp_ring;
int drops = 0, i;
int nxmit = 0, i;

if (test_bit(__ICE_DOWN, vsi->state))
return -ENETDOWN;
Expand All @@ -601,16 +601,15 @@ ice_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
int err;

err = ice_xmit_xdp_ring(xdpf->data, xdpf->len, xdp_ring);
if (err != ICE_XDP_TX) {
xdp_return_frame_rx_napi(xdpf);
drops++;
}
if (err != ICE_XDP_TX)
break;
nxmit++;
}

if (unlikely(flags & XDP_XMIT_FLUSH))
ice_xdp_ring_update_tail(xdp_ring);

return n - drops;
return nxmit;
}

/**
Expand Down
11 changes: 5 additions & 6 deletions drivers/net/ethernet/intel/igb/igb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2934,7 +2934,7 @@ static int igb_xdp_xmit(struct net_device *dev, int n,
int cpu = smp_processor_id();
struct igb_ring *tx_ring;
struct netdev_queue *nq;
int drops = 0;
int nxmit = 0;
int i;

if (unlikely(test_bit(__IGB_DOWN, &adapter->state)))
Expand All @@ -2961,18 +2961,17 @@ static int igb_xdp_xmit(struct net_device *dev, int n,
int err;

err = igb_xmit_xdp_ring(adapter, tx_ring, xdpf);
if (err != IGB_XDP_TX) {
xdp_return_frame_rx_napi(xdpf);
drops++;
}
if (err != IGB_XDP_TX)
break;
nxmit++;
}

__netif_tx_unlock(nq);

if (unlikely(flags & XDP_XMIT_FLUSH))
igb_xdp_ring_update_tail(tx_ring);

return n - drops;
return nxmit;
}

static const struct net_device_ops igb_netdev_ops = {
Expand Down
11 changes: 5 additions & 6 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -10188,7 +10188,7 @@ static int ixgbe_xdp_xmit(struct net_device *dev, int n,
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_ring *ring;
int drops = 0;
int nxmit = 0;
int i;

if (unlikely(test_bit(__IXGBE_DOWN, &adapter->state)))
Expand All @@ -10212,16 +10212,15 @@ static int ixgbe_xdp_xmit(struct net_device *dev, int n,
int err;

err = ixgbe_xmit_xdp_ring(adapter, xdpf);
if (err != IXGBE_XDP_TX) {
xdp_return_frame_rx_napi(xdpf);
drops++;
}
if (err != IXGBE_XDP_TX)
break;
nxmit++;
}

if (unlikely(flags & XDP_XMIT_FLUSH))
ixgbe_xdp_ring_update_tail(ring);

return n - drops;
return nxmit;
}

static const struct net_device_ops ixgbe_netdev_ops = {
Expand Down
13 changes: 6 additions & 7 deletions drivers/net/ethernet/marvell/mvneta.c
Original file line number Diff line number Diff line change
Expand Up @@ -2137,7 +2137,7 @@ mvneta_xdp_xmit(struct net_device *dev, int num_frame,
{
struct mvneta_port *pp = netdev_priv(dev);
struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
int i, nxmit_byte = 0, nxmit = num_frame;
int i, nxmit_byte = 0, nxmit = 0;
int cpu = smp_processor_id();
struct mvneta_tx_queue *txq;
struct netdev_queue *nq;
Expand All @@ -2155,12 +2155,11 @@ mvneta_xdp_xmit(struct net_device *dev, int num_frame,
__netif_tx_lock(nq, cpu);
for (i = 0; i < num_frame; i++) {
ret = mvneta_xdp_submit_frame(pp, txq, frames[i], true);
if (ret == MVNETA_XDP_TX) {
nxmit_byte += frames[i]->len;
} else {
xdp_return_frame_rx_napi(frames[i]);
nxmit--;
}
if (ret != MVNETA_XDP_TX)
break;

nxmit_byte += frames[i]->len;
nxmit++;
}

if (unlikely(flags & XDP_XMIT_FLUSH))
Expand Down
13 changes: 6 additions & 7 deletions drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3744,7 +3744,7 @@ mvpp2_xdp_xmit(struct net_device *dev, int num_frame,
struct xdp_frame **frames, u32 flags)
{
struct mvpp2_port *port = netdev_priv(dev);
int i, nxmit_byte = 0, nxmit = num_frame;
int i, nxmit_byte = 0, nxmit = 0;
struct mvpp2_pcpu_stats *stats;
u16 txq_id;
u32 ret;
Expand All @@ -3762,12 +3762,11 @@ mvpp2_xdp_xmit(struct net_device *dev, int num_frame,

for (i = 0; i < num_frame; i++) {
ret = mvpp2_xdp_submit_frame(port, txq_id, frames[i], true);
if (ret == MVPP2_XDP_TX) {
nxmit_byte += frames[i]->len;
} else {
xdp_return_frame_rx_napi(frames[i]);
nxmit--;
}
if (ret != MVPP2_XDP_TX)
break;

nxmit_byte += frames[i]->len;
nxmit++;
}

if (likely(nxmit > 0))
Expand Down
15 changes: 6 additions & 9 deletions drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
{
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5e_xdpsq *sq;
int drops = 0;
int nxmit = 0;
int sq_num;
int i;

Expand Down Expand Up @@ -529,11 +529,8 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
xdptxd.dma_addr = dma_map_single(sq->pdev, xdptxd.data,
xdptxd.len, DMA_TO_DEVICE);

if (unlikely(dma_mapping_error(sq->pdev, xdptxd.dma_addr))) {
xdp_return_frame_rx_napi(xdpf);
drops++;
continue;
}
if (unlikely(dma_mapping_error(sq->pdev, xdptxd.dma_addr)))
break;

xdpi.mode = MLX5E_XDP_XMIT_MODE_FRAME;
xdpi.frame.xdpf = xdpf;
Expand All @@ -544,9 +541,9 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
if (unlikely(!ret)) {
dma_unmap_single(sq->pdev, xdptxd.dma_addr,
xdptxd.len, DMA_TO_DEVICE);
xdp_return_frame_rx_napi(xdpf);
drops++;
break;
}
nxmit++;
}

if (flags & XDP_XMIT_FLUSH) {
Expand All @@ -555,7 +552,7 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
mlx5e_xmit_xdp_doorbell(sq);
}

return n - drops;
return nxmit;
}

void mlx5e_xdp_rx_poll_complete(struct mlx5e_rq *rq)
Expand Down
Loading

0 comments on commit fdc1397

Please sign in to comment.