Merge branch 'bpf-xsk-fixes'
Maciej Fijalkowski says: ==================== Cameron reported [0] that on fresh bpf-next he could not run multiple xdpsock instances in Tx-only mode on single network interface with i40e driver. Turns out that Maxim's series [1] which was adding RCU protection around ndo_xsk_wakeup added check against the __I40E_CONFIG_BUSY being set on pf->state within i40e_xsk_wakeup() - if it's set, return -ENETDOWN. Since this bit is set per PF when UMEM is being enabled/disabled, the situation Cameron stumbled upon was that when he launched second xdpsock instance, second UMEM was being registered, hence set __I40E_CONFIG_BUSY which is now observed by first xdpsock and therefore xdpsock's kick_tx() gets -ENETDOWN as errno. -ENETDOWN currently is not allowed in kick_tx(), so we were exiting the first application. Such exit means also XDP program being unloaded and its dedicated resources, which caused an -ENXIO being return in the second xdpsock instance. Let's fix the issue from both sides - protect ourselves from future xdpsock crashes by allowing for -ENETDOWN errno being set in kick_tx() (patch 3) and from driver side, return -EAGAIN for the case where PF is busy (patch 1). Remove also doubled variable from xdpsock_user.c (patch 2). Note that ixgbe seems not to be affected since UMEM registration sets the busy/disable bit per ring, not per PF. [0]: https://www.spinics.net/lists/xdp-newbies/msg01558.html [1]: https://lore.kernel.org/netdev/20191217162023.16011-1-maximmi@mellanox.com/ ==================== Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
commit
b9e4272488
|
@ -791,7 +791,7 @@ int i40e_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
|
||||||
struct i40e_ring *ring;
|
struct i40e_ring *ring;
|
||||||
|
|
||||||
if (test_bit(__I40E_CONFIG_BUSY, pf->state))
|
if (test_bit(__I40E_CONFIG_BUSY, pf->state))
|
||||||
return -ENETDOWN;
|
return -EAGAIN;
|
||||||
|
|
||||||
if (test_bit(__I40E_VSI_DOWN, vsi->state))
|
if (test_bit(__I40E_VSI_DOWN, vsi->state))
|
||||||
return -ENETDOWN;
|
return -ENETDOWN;
|
||||||
|
|
|
@ -83,7 +83,6 @@ static u32 opt_xdp_bind_flags = XDP_USE_NEED_WAKEUP;
|
||||||
static u32 opt_umem_flags;
|
static u32 opt_umem_flags;
|
||||||
static int opt_unaligned_chunks;
|
static int opt_unaligned_chunks;
|
||||||
static int opt_mmap_flags;
|
static int opt_mmap_flags;
|
||||||
static u32 opt_xdp_bind_flags;
|
|
||||||
static int opt_xsk_frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
|
static int opt_xsk_frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
|
||||||
static int opt_timeout = 1000;
|
static int opt_timeout = 1000;
|
||||||
static bool opt_need_wakeup = true;
|
static bool opt_need_wakeup = true;
|
||||||
|
@ -789,7 +788,8 @@ static void kick_tx(struct xsk_socket_info *xsk)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);
|
ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);
|
||||||
if (ret >= 0 || errno == ENOBUFS || errno == EAGAIN || errno == EBUSY)
|
if (ret >= 0 || errno == ENOBUFS || errno == EAGAIN ||
|
||||||
|
errno == EBUSY || errno == ENETDOWN)
|
||||||
return;
|
return;
|
||||||
exit_with_error(errno);
|
exit_with_error(errno);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue