Commit 8dcc5b0a authored by Jesper Dangaard Brouer's avatar Jesper Dangaard Brouer Committed by David S. Miller

virtio_net: fix ndo_xdp_xmit crash towards dev not ready for XDP

When a driver implements the ndo_xdp_xmit() function, there is
(currently) no generic way to determine whether it is safe to call.

It is e.g. unsafe to call the drivers ndo_xdp_xmit, if it have not
allocated the needed XDP TX queues yet.  This is the case for
virtio_net, which first allocates the XDP TX queues once an XDP/bpf
prog is attached (in virtnet_xdp_set()).

Thus, a crash will occur for virtio_net when redirecting to another
virtio_net device's ndo_xdp_xmit, which have not attached a XDP prog.
The sample xdp_redirect_map tries to attach a dummy XDP prog to take
this into account, but it can also easily fail if the virtio_net (or
actually underlying vhost driver) have not allocated enough extra
queues for the device.

Allocating more queue this is currently a manual config.
Hint for libvirt XML add:

  <driver name='vhost' queues='16'>
    <host mrg_rxbuf='off'/>
    <guest tso4='off' tso6='off' ecn='off' ufo='off'/>
  </driver>

The solution in this patch is to check that the device have loaded an
XDP/bpf prog before proceeding.  This is similar to the check
performed in driver ixgbe.
Signed-off-by: default avatarJesper Dangaard Brouer <brouer@redhat.com>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 11b7d897
...@@ -452,8 +452,18 @@ static bool __virtnet_xdp_xmit(struct virtnet_info *vi, ...@@ -452,8 +452,18 @@ static bool __virtnet_xdp_xmit(struct virtnet_info *vi,
static int virtnet_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp) static int virtnet_xdp_xmit(struct net_device *dev, struct xdp_buff *xdp)
{ {
struct virtnet_info *vi = netdev_priv(dev); struct virtnet_info *vi = netdev_priv(dev);
bool sent = __virtnet_xdp_xmit(vi, xdp); struct receive_queue *rq = vi->rq;
struct bpf_prog *xdp_prog;
bool sent;
/* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this
* indicate XDP resources have been successfully allocated.
*/
xdp_prog = rcu_dereference(rq->xdp_prog);
if (!xdp_prog)
return -ENXIO;
sent = __virtnet_xdp_xmit(vi, xdp);
if (!sent) if (!sent)
return -ENOSPC; return -ENOSPC;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment