aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesper Dangaard Brouer <brouer@redhat.com>2018-02-20 08:32:04 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-21 15:09:29 -0500
commit7324f5399b06cdbbd1520b8fde8024035953179d (patch)
tree42c49bc8277746b0cea5acec0384744252bfc2d0
parent9c4ff2a9ec37ffd66b1233bf1481fadbbdb3cb0f (diff)
virtio_net: disable XDP_REDIRECT in receive_mergeable() case
The virtio_net code have three different RX code-paths in receive_buf(). Two of these code paths can handle XDP, but one of them is broken for at least XDP_REDIRECT. Function(1): receive_big() does not support XDP. Function(2): receive_small() support XDP fully and uses build_skb(). Function(3): receive_mergeable() broken XDP_REDIRECT uses napi_alloc_skb(). The simple explanation is that receive_mergeable() is broken because it uses napi_alloc_skb(), which violates XDP given XDP assumes packet header+data in single page and enough tail room for skb_shared_info. The longer explaination is that receive_mergeable() tries to work-around and satisfy these XDP requiresments e.g. by having a function xdp_linearize_page() that allocates and memcpy RX buffers around (in case packet is scattered across multiple rx buffers). This does currently satisfy XDP_PASS, XDP_DROP and XDP_TX (but only because we have not implemented bpf_xdp_adjust_tail yet). The XDP_REDIRECT action combined with cpumap is broken, and cause hard to debug crashes. The main issue is that the RX packet does not have the needed tail-room (SKB_DATA_ALIGN(skb_shared_info)), causing skb_shared_info to overlap the next packets head-room (in which cpumap stores info). Reproducing depend on the packet payload length and if RX-buffer size happened to have tail-room for skb_shared_info or not. But to make this even harder to troubleshoot, the RX-buffer size is runtime dynamically change based on an Exponentially Weighted Moving Average (EWMA) over the packet length, when refilling RX rings. This patch only disable XDP_REDIRECT support in receive_mergeable() case, because it can cause a real crash. IMHO we should consider NOT supporting XDP in receive_mergeable() at all, because the principles behind XDP are to gain speed by (1) code simplicity, (2) sacrificing memory and (3) where possible moving runtime checks to setup time. These principles are clearly being violated in receive_mergeable(), that e.g. runtime track average buffer size to save memory consumption. In the longer run, we should consider introducing a separate receive function when attaching an XDP program, and also change the memory model to be compatible with XDP when attaching an XDP prog. Fixes: 186b3c998c50 ("virtio-net: support XDP_REDIRECT") Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com> Acked-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/virtio_net.c7
1 files changed, 0 insertions, 7 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 626c27352ae2..0ca91942a884 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -677,7 +677,6 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
677 struct bpf_prog *xdp_prog; 677 struct bpf_prog *xdp_prog;
678 unsigned int truesize; 678 unsigned int truesize;
679 unsigned int headroom = mergeable_ctx_to_headroom(ctx); 679 unsigned int headroom = mergeable_ctx_to_headroom(ctx);
680 int err;
681 680
682 head_skb = NULL; 681 head_skb = NULL;
683 682
@@ -754,12 +753,6 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
754 goto err_xdp; 753 goto err_xdp;
755 rcu_read_unlock(); 754 rcu_read_unlock();
756 goto xdp_xmit; 755 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: 756 default:
764 bpf_warn_invalid_xdp_action(act); 757 bpf_warn_invalid_xdp_action(act);
765 case XDP_ABORTED: 758 case XDP_ABORTED: