Skip to content

Commit 7b7e05d

Browse files
netoptimizerNipaLocal
authored andcommitted
veth: enable dev_watchdog for detecting stalled TXQs
The changes introduced in commit dc82a33 ("veth: apply qdisc backpressure on full ptr_ring to reduce TX drops") have been found to cause a race condition in production environments. Under specific circumstances, observed exclusively on ARM64 (aarch64) systems with Ampere Altra Max CPUs, a transmit queue (TXQ) can become permanently stalled. This happens when the race condition leads to the TXQ entering the QUEUE_STATE_DRV_XOFF state without a corresponding queue wake-up, preventing the attached qdisc from dequeueing packets and causing the network link to halt. As a first step towards resolving this issue, this patch introduces a failsafe mechanism. It enables the net device watchdog by setting a timeout value and implements the .ndo_tx_timeout callback. If a TXQ stalls, the watchdog will trigger the veth_tx_timeout() function, which logs a warning and calls netif_tx_wake_queue() to unstall the queue and allow traffic to resume. The log message will look like this: veth42: NETDEV WATCHDOG: CPU: 34: transmit queue 0 timed out 5393 ms veth42: veth backpressure stalled(n:1) TXQ(0) re-enable This provides a necessary recovery mechanism while the underlying race condition is investigated further. Subsequent patches will address the root cause and add more robust state handling. Fixes: dc82a33 ("veth: apply qdisc backpressure on full ptr_ring to reduce TX drops") Signed-off-by: Jesper Dangaard Brouer <hawk@kernel.org> Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com> Signed-off-by: NipaLocal <nipa@local>
1 parent abe6f6d commit 7b7e05d

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

drivers/net/veth.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,10 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget,
959959
rq->stats.vs.xdp_packets += done;
960960
u64_stats_update_end(&rq->stats.syncp);
961961

962-
if (peer_txq && unlikely(netif_tx_queue_stopped(peer_txq)))
962+
if (peer_txq && unlikely(netif_tx_queue_stopped(peer_txq))) {
963+
txq_trans_cond_update(peer_txq);
963964
netif_tx_wake_queue(peer_txq);
965+
}
964966

965967
return done;
966968
}
@@ -1373,6 +1375,16 @@ static int veth_set_channels(struct net_device *dev,
13731375
goto out;
13741376
}
13751377

1378+
static void veth_tx_timeout(struct net_device *dev, unsigned int txqueue)
1379+
{
1380+
struct netdev_queue *txq = netdev_get_tx_queue(dev, txqueue);
1381+
1382+
netdev_err(dev, "veth backpressure stalled(n:%ld) TXQ(%u) re-enable\n",
1383+
atomic_long_read(&txq->trans_timeout), txqueue);
1384+
1385+
netif_tx_wake_queue(txq);
1386+
}
1387+
13761388
static int veth_open(struct net_device *dev)
13771389
{
13781390
struct veth_priv *priv = netdev_priv(dev);
@@ -1711,6 +1723,7 @@ static const struct net_device_ops veth_netdev_ops = {
17111723
.ndo_bpf = veth_xdp,
17121724
.ndo_xdp_xmit = veth_ndo_xdp_xmit,
17131725
.ndo_get_peer_dev = veth_peer_dev,
1726+
.ndo_tx_timeout = veth_tx_timeout,
17141727
};
17151728

17161729
static const struct xdp_metadata_ops veth_xdp_metadata_ops = {
@@ -1749,6 +1762,7 @@ static void veth_setup(struct net_device *dev)
17491762
dev->priv_destructor = veth_dev_free;
17501763
dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
17511764
dev->max_mtu = ETH_MAX_MTU;
1765+
dev->watchdog_timeo = msecs_to_jiffies(5000);
17521766

17531767
dev->hw_features = VETH_FEATURES;
17541768
dev->hw_enc_features = VETH_FEATURES;

0 commit comments

Comments
 (0)