aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c58
1 files changed, 34 insertions, 24 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 626c27352ae2..9bb9e562b893 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -443,12 +443,8 @@ static bool __virtnet_xdp_xmit(struct virtnet_info *vi,
443 sg_init_one(sq->sg, xdp->data, xdp->data_end - xdp->data); 443 sg_init_one(sq->sg, xdp->data, xdp->data_end - xdp->data);
444 444
445 err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdp->data, GFP_ATOMIC); 445 err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdp->data, GFP_ATOMIC);
446 if (unlikely(err)) { 446 if (unlikely(err))
447 struct page *page = virt_to_head_page(xdp->data); 447 return false; /* Caller handle free/refcnt */
448
449 put_page(page);
450 return false;
451 }
452 448
453 return true; 449 return true;
454} 450}
@@ -456,8 +452,18 @@ static bool __virtnet_xdp_xmit(struct virtnet_info *vi,
456static int virtnet_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp) 452static int virtnet_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
457{ 453{
458 struct virtnet_info *vi = netdev_priv(dev); 454 struct virtnet_info *vi = netdev_priv(dev);
459 bool sent = __virtnet_xdp_xmit(vi, xdp); 455 struct receive_queue *rq = vi->rq;
456 struct bpf_prog *xdp_prog;
457 bool sent;
460 458
459 /* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this
460 * indicate XDP resources have been successfully allocated.
461 */
462 xdp_prog = rcu_dereference(rq->xdp_prog);
463 if (!xdp_prog)
464 return -ENXIO;
465
466 sent = __virtnet_xdp_xmit(vi, xdp);
461 if (!sent) 467 if (!sent)
462 return -ENOSPC; 468 return -ENOSPC;
463 return 0; 469 return 0;
@@ -546,8 +552,11 @@ static struct sk_buff *receive_small(struct net_device *dev,
546 unsigned int buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) + 552 unsigned int buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
547 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); 553 SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
548 struct page *page = virt_to_head_page(buf); 554 struct page *page = virt_to_head_page(buf);
549 unsigned int delta = 0, err; 555 unsigned int delta = 0;
550 struct page *xdp_page; 556 struct page *xdp_page;
557 bool sent;
558 int err;
559
551 len -= vi->hdr_len; 560 len -= vi->hdr_len;
552 561
553 rcu_read_lock(); 562 rcu_read_lock();
@@ -558,7 +567,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
558 void *orig_data; 567 void *orig_data;
559 u32 act; 568 u32 act;
560 569
561 if (unlikely(hdr->hdr.gso_type || hdr->hdr.flags)) 570 if (unlikely(hdr->hdr.gso_type))
562 goto err_xdp; 571 goto err_xdp;
563 572
564 if (unlikely(xdp_headroom < virtnet_get_headroom(vi))) { 573 if (unlikely(xdp_headroom < virtnet_get_headroom(vi))) {
@@ -596,16 +605,19 @@ static struct sk_buff *receive_small(struct net_device *dev,
596 delta = orig_data - xdp.data; 605 delta = orig_data - xdp.data;
597 break; 606 break;
598 case XDP_TX: 607 case XDP_TX:
599 if (unlikely(!__virtnet_xdp_xmit(vi, &xdp))) 608 sent = __virtnet_xdp_xmit(vi, &xdp);
609 if (unlikely(!sent)) {
600 trace_xdp_exception(vi->dev, xdp_prog, act); 610 trace_xdp_exception(vi->dev, xdp_prog, act);
601 else 611 goto err_xdp;
602 *xdp_xmit = true; 612 }
613 *xdp_xmit = true;
603 rcu_read_unlock(); 614 rcu_read_unlock();
604 goto xdp_xmit; 615 goto xdp_xmit;
605 case XDP_REDIRECT: 616 case XDP_REDIRECT:
606 err = xdp_do_redirect(dev, &xdp, xdp_prog); 617 err = xdp_do_redirect(dev, &xdp, xdp_prog);
607 if (!err) 618 if (err)
608 *xdp_xmit = true; 619 goto err_xdp;
620 *xdp_xmit = true;
609 rcu_read_unlock(); 621 rcu_read_unlock();
610 goto xdp_xmit; 622 goto xdp_xmit;
611 default: 623 default:
@@ -677,7 +689,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
677 struct bpf_prog *xdp_prog; 689 struct bpf_prog *xdp_prog;
678 unsigned int truesize; 690 unsigned int truesize;
679 unsigned int headroom = mergeable_ctx_to_headroom(ctx); 691 unsigned int headroom = mergeable_ctx_to_headroom(ctx);
680 int err; 692 bool sent;
681 693
682 head_skb = NULL; 694 head_skb = NULL;
683 695
@@ -746,20 +758,18 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
746 } 758 }
747 break; 759 break;
748 case XDP_TX: 760 case XDP_TX:
749 if (unlikely(!__virtnet_xdp_xmit(vi, &xdp))) 761 sent = __virtnet_xdp_xmit(vi, &xdp);
762 if (unlikely(!sent)) {
750 trace_xdp_exception(vi->dev, xdp_prog, act); 763 trace_xdp_exception(vi->dev, xdp_prog, act);
751 else 764 if (unlikely(xdp_page != page))
752 *xdp_xmit = true; 765 put_page(xdp_page);
766 goto err_xdp;
767 }
768 *xdp_xmit = true;
753 if (unlikely(xdp_page != page)) 769 if (unlikely(xdp_page != page))
754 goto err_xdp; 770 goto err_xdp;
755 rcu_read_unlock(); 771 rcu_read_unlock();
756 goto xdp_xmit; 772 goto xdp_xmit;
757 case XDP_REDIRECT:
758 err = xdp_do_redirect(dev, &xdp, xdp_prog);
759 if (!err)
760 *xdp_xmit = true;
761 rcu_read_unlock();
762 goto xdp_xmit;
763 default: 773 default:
764 bpf_warn_invalid_xdp_action(act); 774 bpf_warn_invalid_xdp_action(act);
765 case XDP_ABORTED: 775 case XDP_ABORTED: