This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 5059638c547 drivers/net: fix ABBA deadlock in netdev_upper_txavail 
under forwarding
5059638c547 is described below

commit 5059638c5477f68e3584f27e6b70e8964a8d5f54
Author: Sarthak Pandey <[email protected]>
AuthorDate: Mon Oct 12 20:46:33 2026 +0530

    drivers/net: fix ABBA deadlock in netdev_upper_txavail under forwarding
    
    In full-duplex forwarding / NAT scenarios between two network devices
    (e.g. wlan0 and wlan1 in SoftAP + Station mode), both netdev RX worker
    threads could deadlock (ABBA):
    - Thread netdev-wlan0 holds netdev_lock(wlan0) during RX poll. When
      forwarding a packet to wlan1, it invokes netdev_txnotify_dev(wlan1),
      which calls wlan1->d_txavail(). netdev_upper_txavail() was directly
      calling netdev_upper_txavail_work(), which synchronously acquires
      netdev_lock(wlan1).
    - Concurrently, thread netdev-wlan1 holds netdev_lock(wlan1) during
      RX poll and forwards a packet to wlan0, trying to synchronously
      acquire netdev_lock(wlan0).
    
    This resulted in a cross-deadlock where both RX workers waited
    indefinitely on each other's device lock.
    
    Fix this by checking upper->lower->rxtype in netdev_upper_txavail(). If
    rxtype is not NETDEV_RX_DIRECT, delegate via netdev_upper_queue_work(dev)
    to wake the target device's worker thread asynchronously without
    holding peer device locks synchronously.
    
    Fixes: #20619
    Signed-off-by: Sarthak Pandey <[email protected]>
---
 drivers/net/netdev_upperhalf.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/net/netdev_upperhalf.c b/drivers/net/netdev_upperhalf.c
index 7bb5bdaf00d..31939590c1d 100644
--- a/drivers/net/netdev_upperhalf.c
+++ b/drivers/net/netdev_upperhalf.c
@@ -929,7 +929,28 @@ static inline void netdev_upper_queue_work(FAR struct 
net_driver_s *dev)
 
 static int netdev_upper_txavail(FAR struct net_driver_s *dev)
 {
-  netdev_upper_txavail_work(dev->d_private);
+  FAR struct netdev_upperhalf_s *upper = dev->d_private;
+
+  if (upper->lower->rxtype == NETDEV_RX_DIRECT)
+    {
+      netdev_upper_txavail_work(upper);
+    }
+  else if (nxrmutex_trylock(&dev->d_lock) >= 0)
+    {
+      /* Lock free or held by us: transmit now so txq can't overflow.
+       * Drop the extra reference of the recursive lock.
+       */
+
+      netdev_upper_txavail_work(upper);
+      nxrmutex_unlock(&dev->d_lock);
+    }
+  else
+    {
+      /* Locked by another thread: don't wait (ABBA when forwarding) */
+
+      netdev_upper_queue_work(dev);
+    }
+
   return OK;
 }
 

Reply via email to