aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c26
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c21
-rw-r--r--drivers/net/tun.c37
-rw-r--r--drivers/net/virtio_net.c66
-rw-r--r--include/linux/netdevice.h14
-rw-r--r--kernel/bpf/devmap.c29
-rw-r--r--net/core/filter.c8
8 files changed, 139 insertions, 64 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 5efa68de935b..9b698c5acd05 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -3664,14 +3664,19 @@ netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
3664 * @dev: netdev 3664 * @dev: netdev
3665 * @xdp: XDP buffer 3665 * @xdp: XDP buffer
3666 * 3666 *
3667 * Returns Zero if sent, else an error code 3667 * Returns number of frames successfully sent. Frames that fail are
3668 * free'ed via XDP return API.
3669 *
3670 * For error cases, a negative errno code is returned and no-frames
3671 * are transmitted (caller must handle freeing frames).
3668 **/ 3672 **/
3669int i40e_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf) 3673int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames)
3670{ 3674{
3671 struct i40e_netdev_priv *np = netdev_priv(dev); 3675 struct i40e_netdev_priv *np = netdev_priv(dev);
3672 unsigned int queue_index = smp_processor_id(); 3676 unsigned int queue_index = smp_processor_id();
3673 struct i40e_vsi *vsi = np->vsi; 3677 struct i40e_vsi *vsi = np->vsi;
3674 int err; 3678 int drops = 0;
3679 int i;
3675 3680
3676 if (test_bit(__I40E_VSI_DOWN, vsi->state)) 3681 if (test_bit(__I40E_VSI_DOWN, vsi->state))
3677 return -ENETDOWN; 3682 return -ENETDOWN;
@@ -3679,11 +3684,18 @@ int i40e_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf)
3679 if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs) 3684 if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs)
3680 return -ENXIO; 3685 return -ENXIO;
3681 3686
3682 err = i40e_xmit_xdp_ring(xdpf, vsi->xdp_rings[queue_index]); 3687 for (i = 0; i < n; i++) {
3683 if (err != I40E_XDP_TX) 3688 struct xdp_frame *xdpf = frames[i];
3684 return -ENOSPC; 3689 int err;
3685 3690
3686 return 0; 3691 err = i40e_xmit_xdp_ring(xdpf, vsi->xdp_rings[queue_index]);
3692 if (err != I40E_XDP_TX) {
3693 xdp_return_frame_rx_napi(xdpf);
3694 drops++;
3695 }
3696 }
3697
3698 return n - drops;
3687} 3699}
3688 3700
3689/** 3701/**
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
index fdd2c55f03a6..eb8804b3d7b6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -487,7 +487,7 @@ u32 i40e_get_tx_pending(struct i40e_ring *ring, bool in_sw);
487void i40e_detect_recover_hung(struct i40e_vsi *vsi); 487void i40e_detect_recover_hung(struct i40e_vsi *vsi);
488int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size); 488int __i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
489bool __i40e_chk_linearize(struct sk_buff *skb); 489bool __i40e_chk_linearize(struct sk_buff *skb);
490int i40e_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf); 490int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames);
491void i40e_xdp_flush(struct net_device *dev); 491void i40e_xdp_flush(struct net_device *dev);
492 492
493/** 493/**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 6652b201df5b..9645619f7729 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -10017,11 +10017,13 @@ static int ixgbe_xdp(struct net_device *dev, struct netdev_bpf *xdp)
10017 } 10017 }
10018} 10018}
10019 10019
10020static int ixgbe_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf) 10020static int ixgbe_xdp_xmit(struct net_device *dev, int n,
10021 struct xdp_frame **frames)
10021{ 10022{
10022 struct ixgbe_adapter *adapter = netdev_priv(dev); 10023 struct ixgbe_adapter *adapter = netdev_priv(dev);
10023 struct ixgbe_ring *ring; 10024 struct ixgbe_ring *ring;
10024 int err; 10025 int drops = 0;
10026 int i;
10025 10027
10026 if (unlikely(test_bit(__IXGBE_DOWN, &adapter->state))) 10028 if (unlikely(test_bit(__IXGBE_DOWN, &adapter->state)))
10027 return -ENETDOWN; 10029 return -ENETDOWN;
@@ -10033,11 +10035,18 @@ static int ixgbe_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf)
10033 if (unlikely(!ring)) 10035 if (unlikely(!ring))
10034 return -ENXIO; 10036 return -ENXIO;
10035 10037
10036 err = ixgbe_xmit_xdp_ring(adapter, xdpf); 10038 for (i = 0; i < n; i++) {
10037 if (err != IXGBE_XDP_TX) 10039 struct xdp_frame *xdpf = frames[i];
10038 return -ENOSPC; 10040 int err;
10039 10041
10040 return 0; 10042 err = ixgbe_xmit_xdp_ring(adapter, xdpf);
10043 if (err != IXGBE_XDP_TX) {
10044 xdp_return_frame_rx_napi(xdpf);
10045 drops++;
10046 }
10047 }
10048
10049 return n - drops;
10041} 10050}
10042 10051
10043static void ixgbe_xdp_flush(struct net_device *dev) 10052static void ixgbe_xdp_flush(struct net_device *dev)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 44d4f3d25350..d3dcfcb1c4b3 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -70,6 +70,7 @@
70#include <net/netns/generic.h> 70#include <net/netns/generic.h>
71#include <net/rtnetlink.h> 71#include <net/rtnetlink.h>
72#include <net/sock.h> 72#include <net/sock.h>
73#include <net/xdp.h>
73#include <linux/seq_file.h> 74#include <linux/seq_file.h>
74#include <linux/uio.h> 75#include <linux/uio.h>
75#include <linux/skb_array.h> 76#include <linux/skb_array.h>
@@ -1290,34 +1291,44 @@ static const struct net_device_ops tun_netdev_ops = {
1290 .ndo_get_stats64 = tun_net_get_stats64, 1291 .ndo_get_stats64 = tun_net_get_stats64,
1291}; 1292};
1292 1293
1293static int tun_xdp_xmit(struct net_device *dev, struct xdp_frame *frame) 1294static int tun_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames)
1294{ 1295{
1295 struct tun_struct *tun = netdev_priv(dev); 1296 struct tun_struct *tun = netdev_priv(dev);
1296 struct tun_file *tfile; 1297 struct tun_file *tfile;
1297 u32 numqueues; 1298 u32 numqueues;
1298 int ret = 0; 1299 int drops = 0;
1300 int cnt = n;
1301 int i;
1299 1302
1300 rcu_read_lock(); 1303 rcu_read_lock();
1301 1304
1302 numqueues = READ_ONCE(tun->numqueues); 1305 numqueues = READ_ONCE(tun->numqueues);
1303 if (!numqueues) { 1306 if (!numqueues) {
1304 ret = -ENOSPC; 1307 rcu_read_unlock();
1305 goto out; 1308 return -ENXIO; /* Caller will free/return all frames */
1306 } 1309 }
1307 1310
1308 tfile = rcu_dereference(tun->tfiles[smp_processor_id() % 1311 tfile = rcu_dereference(tun->tfiles[smp_processor_id() %
1309 numqueues]); 1312 numqueues]);
1310 /* Encode the XDP flag into lowest bit for consumer to differ 1313
1311 * XDP buffer from sk_buff. 1314 spin_lock(&tfile->tx_ring.producer_lock);
1312 */ 1315 for (i = 0; i < n; i++) {
1313 if (ptr_ring_produce(&tfile->tx_ring, tun_xdp_to_ptr(frame))) { 1316 struct xdp_frame *xdp = frames[i];
1314 this_cpu_inc(tun->pcpu_stats->tx_dropped); 1317 /* Encode the XDP flag into lowest bit for consumer to differ
1315 ret = -ENOSPC; 1318 * XDP buffer from sk_buff.
1319 */
1320 void *frame = tun_xdp_to_ptr(xdp);
1321
1322 if (__ptr_ring_produce(&tfile->tx_ring, frame)) {
1323 this_cpu_inc(tun->pcpu_stats->tx_dropped);
1324 xdp_return_frame_rx_napi(xdp);
1325 drops++;
1326 }
1316 } 1327 }
1328 spin_unlock(&tfile->tx_ring.producer_lock);
1317 1329
1318out:
1319 rcu_read_unlock(); 1330 rcu_read_unlock();
1320 return ret; 1331 return cnt - drops;
1321} 1332}
1322 1333
1323static int tun_xdp_tx(struct net_device *dev, struct xdp_buff *xdp) 1334static int tun_xdp_tx(struct net_device *dev, struct xdp_buff *xdp)
@@ -1327,7 +1338,7 @@ static int tun_xdp_tx(struct net_device *dev, struct xdp_buff *xdp)
1327 if (unlikely(!frame)) 1338 if (unlikely(!frame))
1328 return -EOVERFLOW; 1339 return -EOVERFLOW;
1329 1340
1330 return tun_xdp_xmit(dev, frame); 1341 return tun_xdp_xmit(dev, 1, &frame);
1331} 1342}
1332 1343
1333static void tun_xdp_flush(struct net_device *dev) 1344static void tun_xdp_flush(struct net_device *dev)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f34794a76c4d..39a0783d1cde 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -419,23 +419,13 @@ static void virtnet_xdp_flush(struct net_device *dev)
419 virtqueue_kick(sq->vq); 419 virtqueue_kick(sq->vq);
420} 420}
421 421
422static int __virtnet_xdp_xmit(struct virtnet_info *vi, 422static int __virtnet_xdp_xmit_one(struct virtnet_info *vi,
423 struct xdp_frame *xdpf) 423 struct send_queue *sq,
424 struct xdp_frame *xdpf)
424{ 425{
425 struct virtio_net_hdr_mrg_rxbuf *hdr; 426 struct virtio_net_hdr_mrg_rxbuf *hdr;
426 struct xdp_frame *xdpf_sent;
427 struct send_queue *sq;
428 unsigned int len;
429 unsigned int qp;
430 int err; 427 int err;
431 428
432 qp = vi->curr_queue_pairs - vi->xdp_queue_pairs + smp_processor_id();
433 sq = &vi->sq[qp];
434
435 /* Free up any pending old buffers before queueing new ones. */
436 while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL)
437 xdp_return_frame(xdpf_sent);
438
439 /* virtqueue want to use data area in-front of packet */ 429 /* virtqueue want to use data area in-front of packet */
440 if (unlikely(xdpf->metasize > 0)) 430 if (unlikely(xdpf->metasize > 0))
441 return -EOPNOTSUPP; 431 return -EOPNOTSUPP;
@@ -459,11 +449,40 @@ static int __virtnet_xdp_xmit(struct virtnet_info *vi,
459 return 0; 449 return 0;
460} 450}
461 451
462static int virtnet_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf) 452static int __virtnet_xdp_tx_xmit(struct virtnet_info *vi,
453 struct xdp_frame *xdpf)
454{
455 struct xdp_frame *xdpf_sent;
456 struct send_queue *sq;
457 unsigned int len;
458 unsigned int qp;
459
460 qp = vi->curr_queue_pairs - vi->xdp_queue_pairs + smp_processor_id();
461 sq = &vi->sq[qp];
462
463 /* Free up any pending old buffers before queueing new ones. */
464 while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL)
465 xdp_return_frame(xdpf_sent);
466
467 return __virtnet_xdp_xmit_one(vi, sq, xdpf);
468}
469
470static int virtnet_xdp_xmit(struct net_device *dev,
471 int n, struct xdp_frame **frames)
463{ 472{
464 struct virtnet_info *vi = netdev_priv(dev); 473 struct virtnet_info *vi = netdev_priv(dev);
465 struct receive_queue *rq = vi->rq; 474 struct receive_queue *rq = vi->rq;
475 struct xdp_frame *xdpf_sent;
466 struct bpf_prog *xdp_prog; 476 struct bpf_prog *xdp_prog;
477 struct send_queue *sq;
478 unsigned int len;
479 unsigned int qp;
480 int drops = 0;
481 int err;
482 int i;
483
484 qp = vi->curr_queue_pairs - vi->xdp_queue_pairs + smp_processor_id();
485 sq = &vi->sq[qp];
467 486
468 /* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this 487 /* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this
469 * indicate XDP resources have been successfully allocated. 488 * indicate XDP resources have been successfully allocated.
@@ -472,7 +491,20 @@ static int virtnet_xdp_xmit(struct net_device *dev, struct xdp_frame *xdpf)
472 if (!xdp_prog) 491 if (!xdp_prog)
473 return -ENXIO; 492 return -ENXIO;
474 493
475 return __virtnet_xdp_xmit(vi, xdpf); 494 /* Free up any pending old buffers before queueing new ones. */
495 while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL)
496 xdp_return_frame(xdpf_sent);
497
498 for (i = 0; i < n; i++) {
499 struct xdp_frame *xdpf = frames[i];
500
501 err = __virtnet_xdp_xmit_one(vi, sq, xdpf);
502 if (err) {
503 xdp_return_frame_rx_napi(xdpf);
504 drops++;
505 }
506 }
507 return n - drops;
476} 508}
477 509
478static unsigned int virtnet_get_headroom(struct virtnet_info *vi) 510static unsigned int virtnet_get_headroom(struct virtnet_info *vi)
@@ -616,7 +648,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
616 xdpf = convert_to_xdp_frame(&xdp); 648 xdpf = convert_to_xdp_frame(&xdp);
617 if (unlikely(!xdpf)) 649 if (unlikely(!xdpf))
618 goto err_xdp; 650 goto err_xdp;
619 err = __virtnet_xdp_xmit(vi, xdpf); 651 err = __virtnet_xdp_tx_xmit(vi, xdpf);
620 if (unlikely(err)) { 652 if (unlikely(err)) {
621 trace_xdp_exception(vi->dev, xdp_prog, act); 653 trace_xdp_exception(vi->dev, xdp_prog, act);
622 goto err_xdp; 654 goto err_xdp;
@@ -779,7 +811,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
779 xdpf = convert_to_xdp_frame(&xdp); 811 xdpf = convert_to_xdp_frame(&xdp);
780 if (unlikely(!xdpf)) 812 if (unlikely(!xdpf))
781 goto err_xdp; 813 goto err_xdp;
782 err = __virtnet_xdp_xmit(vi, xdpf); 814 err = __virtnet_xdp_tx_xmit(vi, xdpf);
783 if (unlikely(err)) { 815 if (unlikely(err)) {
784 trace_xdp_exception(vi->dev, xdp_prog, act); 816 trace_xdp_exception(vi->dev, xdp_prog, act);
785 if (unlikely(xdp_page != page)) 817 if (unlikely(xdp_page != page))
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 03ed492c4e14..debdb6286170 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1185,9 +1185,13 @@ struct dev_ifalias {
1185 * This function is used to set or query state related to XDP on the 1185 * This function is used to set or query state related to XDP on the
1186 * netdevice and manage BPF offload. See definition of 1186 * netdevice and manage BPF offload. See definition of
1187 * enum bpf_netdev_command for details. 1187 * enum bpf_netdev_command for details.
1188 * int (*ndo_xdp_xmit)(struct net_device *dev, struct xdp_frame *xdp); 1188 * int (*ndo_xdp_xmit)(struct net_device *dev, int n, struct xdp_frame **xdp);
1189 * This function is used to submit a XDP packet for transmit on a 1189 * This function is used to submit @n XDP packets for transmit on a
1190 * netdevice. 1190 * netdevice. Returns number of frames successfully transmitted, frames
1191 * that got dropped are freed/returned via xdp_return_frame().
1192 * Returns negative number, means general error invoking ndo, meaning
1193 * no frames were xmit'ed and core-caller will free all frames.
1194 * TODO: Consider add flag to allow sending flush operation.
1191 * void (*ndo_xdp_flush)(struct net_device *dev); 1195 * void (*ndo_xdp_flush)(struct net_device *dev);
1192 * This function is used to inform the driver to flush a particular 1196 * This function is used to inform the driver to flush a particular
1193 * xdp tx queue. Must be called on same CPU as xdp_xmit. 1197 * xdp tx queue. Must be called on same CPU as xdp_xmit.
@@ -1375,8 +1379,8 @@ struct net_device_ops {
1375 int needed_headroom); 1379 int needed_headroom);
1376 int (*ndo_bpf)(struct net_device *dev, 1380 int (*ndo_bpf)(struct net_device *dev,
1377 struct netdev_bpf *bpf); 1381 struct netdev_bpf *bpf);
1378 int (*ndo_xdp_xmit)(struct net_device *dev, 1382 int (*ndo_xdp_xmit)(struct net_device *dev, int n,
1379 struct xdp_frame *xdp); 1383 struct xdp_frame **xdp);
1380 void (*ndo_xdp_flush)(struct net_device *dev); 1384 void (*ndo_xdp_flush)(struct net_device *dev);
1381}; 1385};
1382 1386
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index a9cd5c93dd2b..77908311ec98 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -232,24 +232,31 @@ static int bq_xmit_all(struct bpf_dtab_netdev *obj,
232 prefetch(xdpf); 232 prefetch(xdpf);
233 } 233 }
234 234
235 for (i = 0; i < bq->count; i++) { 235 sent = dev->netdev_ops->ndo_xdp_xmit(dev, bq->count, bq->q);
236 struct xdp_frame *xdpf = bq->q[i]; 236 if (sent < 0) {
237 int err; 237 sent = 0;
238 238 goto error;
239 err = dev->netdev_ops->ndo_xdp_xmit(dev, xdpf);
240 if (err) {
241 drops++;
242 xdp_return_frame_rx_napi(xdpf);
243 } else {
244 sent++;
245 }
246 } 239 }
240 drops = bq->count - sent;
241out:
247 bq->count = 0; 242 bq->count = 0;
248 243
249 trace_xdp_devmap_xmit(&obj->dtab->map, obj->bit, 244 trace_xdp_devmap_xmit(&obj->dtab->map, obj->bit,
250 sent, drops, bq->dev_rx, dev); 245 sent, drops, bq->dev_rx, dev);
251 bq->dev_rx = NULL; 246 bq->dev_rx = NULL;
252 return 0; 247 return 0;
248error:
249 /* If ndo_xdp_xmit fails with an errno, no frames have been
250 * xmit'ed and it's our responsibility to them free all.
251 */
252 for (i = 0; i < bq->count; i++) {
253 struct xdp_frame *xdpf = bq->q[i];
254
255 /* RX path under NAPI protection, can return frames faster */
256 xdp_return_frame_rx_napi(xdpf);
257 drops++;
258 }
259 goto out;
253} 260}
254 261
255/* __dev_map_flush is called from xdp_do_flush_map() which _must_ be signaled 262/* __dev_map_flush is called from xdp_do_flush_map() which _must_ be signaled
diff --git a/net/core/filter.c b/net/core/filter.c
index 36cf2f87d742..1d75f9322275 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3039,7 +3039,7 @@ static int __bpf_tx_xdp(struct net_device *dev,
3039 u32 index) 3039 u32 index)
3040{ 3040{
3041 struct xdp_frame *xdpf; 3041 struct xdp_frame *xdpf;
3042 int err; 3042 int sent;
3043 3043
3044 if (!dev->netdev_ops->ndo_xdp_xmit) { 3044 if (!dev->netdev_ops->ndo_xdp_xmit) {
3045 return -EOPNOTSUPP; 3045 return -EOPNOTSUPP;
@@ -3049,9 +3049,9 @@ static int __bpf_tx_xdp(struct net_device *dev,
3049 if (unlikely(!xdpf)) 3049 if (unlikely(!xdpf))
3050 return -EOVERFLOW; 3050 return -EOVERFLOW;
3051 3051
3052 err = dev->netdev_ops->ndo_xdp_xmit(dev, xdpf); 3052 sent = dev->netdev_ops->ndo_xdp_xmit(dev, 1, &xdpf);
3053 if (err) 3053 if (sent <= 0)
3054 return err; 3054 return sent;
3055 dev->netdev_ops->ndo_xdp_flush(dev); 3055 dev->netdev_ops->ndo_xdp_flush(dev);
3056 return 0; 3056 return 0;
3057} 3057}