Skip to content

Commit 642e450

Browse files
magnus-karlssonborkmann
authored andcommitted
xsk: Do not discard packet when NETDEV_TX_BUSY
In the skb Tx path, transmission of a packet is performed with dev_direct_xmit(). When NETDEV_TX_BUSY is set in the drivers, it signifies that it was not possible to send the packet right now, please try later. Unfortunately, the xsk transmit code discarded the packet and returned EBUSY to the application. Fix this unnecessary packet loss, by not discarding the packet in the Tx ring and return EAGAIN. As EAGAIN is returned to the application, it can then retry the send operation later and the packet will then likely be sent as the driver will then likely have space/resources to send the packet. In summary, EAGAIN tells the application that the packet was not discarded from the Tx ring and that it needs to call send() again. EBUSY, on the other hand, signifies that the packet was not sent and discarded from the Tx ring. The application needs to put the packet on the Tx ring again if it wants it to be sent. Fixes: 35fcde7 ("xsk: support for Tx") Reported-by: Arkadiusz Zema <[email protected]> Suggested-by: Arkadiusz Zema <[email protected]> Suggested-by: Daniel Borkmann <[email protected]> Signed-off-by: Magnus Karlsson <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Reviewed-by: Jesse Brandeburg <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent d5d325e commit 642e450

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

net/xdp/xsk.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,15 +377,30 @@ static int xsk_generic_xmit(struct sock *sk)
377377
skb_shinfo(skb)->destructor_arg = (void *)(long)desc.addr;
378378
skb->destructor = xsk_destruct_skb;
379379

380+
/* Hinder dev_direct_xmit from freeing the packet and
381+
* therefore completing it in the destructor
382+
*/
383+
refcount_inc(&skb->users);
380384
err = dev_direct_xmit(skb, xs->queue_id);
385+
if (err == NETDEV_TX_BUSY) {
386+
/* Tell user-space to retry the send */
387+
skb->destructor = sock_wfree;
388+
/* Free skb without triggering the perf drop trace */
389+
consume_skb(skb);
390+
err = -EAGAIN;
391+
goto out;
392+
}
393+
381394
xskq_cons_release(xs->tx);
382395
/* Ignore NET_XMIT_CN as packet might have been sent */
383-
if (err == NET_XMIT_DROP || err == NETDEV_TX_BUSY) {
396+
if (err == NET_XMIT_DROP) {
384397
/* SKB completed but not sent */
398+
kfree_skb(skb);
385399
err = -EBUSY;
386400
goto out;
387401
}
388402

403+
consume_skb(skb);
389404
sent_frame = true;
390405
}
391406

0 commit comments

Comments
 (0)