Netdev List
 help / color / mirror / Atom feed
* [PATCH net] amt: handle all upper amt devices in amt_device_event()
@ 2026-11-11  6:15 Wenbo Sun
  2026-11-12 18:51 ` Jakub Kicinski
  0 siblings, 1 reply; 2+ messages in thread
From: Wenbo Sun @ 2026-11-11  6:15 UTC (permalink / raw)
  To: Taehee Yoo, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: netdev, linux-kernel, sunwenbo, 1342116488

When multiple AMT interfaces are created over the same lower stream
device, each AMT interface links to the stream device as an upper
device and takes a reference to it via dev_get_by_index().

However, amt_device_event() uses amt_lookup_upper_dev(), which only
retrieves the first matching AMT device.

Consequently, when the lower stream device is unregistered
(NETDEV_UNREGISTER), only the first AMT device is detached and
unregistered. The remaining AMT interfaces remain attached to the
lower device, triggering WARN_ON(netdev_has_any_upper_dev(dev)) in
unregister_netdevice_many_notify(). Similarly, when the lower device
MTU changes (NETDEV_CHANGEMTU), only the first AMT device has its MTU
updated.

Fix this by iterating over all AMT interfaces associated with the
stream device in amt_device_event() for both NETDEV_UNREGISTER and
NETDEV_CHANGEMTU, and remove the now-redundant amt_lookup_upper_dev()
helper.

This issue was identified with the assistance of an LLM-based code
review tool, confirmed by reproducing the MTU update failure and kernel
WARNING on lower device unregistration in a User-Mode Linux (UML)
environment, and verified in UML that all upper AMT devices are cleanly
handled and unregistered without warnings.

Fixes: b9022b53adad ("amt: add control plane of amt interface")
Signed-off-by: Wenbo Sun <sunwenbo@cmss.chinamobile.com>
---
 drivers/net/amt.c | 48 +++++++++++++++++++++--------------------------
 1 file changed, 21 insertions(+), 27 deletions(-)

diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index 81d26ef82cf5..568ff4f77be6 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -3404,22 +3404,6 @@ static struct rtnl_link_ops amt_link_ops __read_mostly = {
 	.fill_info      = amt_fill_info,
 };
 
-static struct net_device *amt_lookup_upper_dev(struct net_device *dev)
-{
-	struct net_device *upper_dev;
-	struct amt_dev *amt;
-
-	for_each_netdev(dev_net(dev), upper_dev) {
-		if (netif_is_amt(upper_dev)) {
-			amt = netdev_priv(upper_dev);
-			if (amt->stream_dev == dev)
-				return upper_dev;
-		}
-	}
-
-	return NULL;
-}
-
 static int amt_device_event(struct notifier_block *unused,
 			    unsigned long event, void *ptr)
 {
@@ -3429,23 +3413,33 @@ static int amt_device_event(struct notifier_block *unused,
 	LIST_HEAD(list);
 	int new_mtu;
 
-	upper_dev = amt_lookup_upper_dev(dev);
-	if (!upper_dev)
-		return NOTIFY_DONE;
-	amt = netdev_priv(upper_dev);
-
 	switch (event) {
 	case NETDEV_UNREGISTER:
-		amt_dellink(amt->dev, &list);
+		for_each_netdev(dev_net(dev), upper_dev) {
+			if (netif_is_amt(upper_dev)) {
+				amt = netdev_priv(upper_dev);
+				if (amt->stream_dev == dev)
+					amt_dellink(amt->dev, &list);
+			}
+		}
 		unregister_netdevice_many(&list);
 		break;
 	case NETDEV_CHANGEMTU:
-		if (amt->mode == AMT_MODE_RELAY)
-			new_mtu = dev->mtu - AMT_RELAY_HLEN;
-		else
-			new_mtu = dev->mtu - AMT_GW_HLEN;
+		for_each_netdev(dev_net(dev), upper_dev) {
+			if (netif_is_amt(upper_dev)) {
+				amt = netdev_priv(upper_dev);
+				if (amt->stream_dev == dev) {
+					if (amt->mode == AMT_MODE_RELAY)
+						new_mtu = dev->mtu -
+							  AMT_RELAY_HLEN;
+					else
+						new_mtu = dev->mtu -
+							  AMT_GW_HLEN;
 
-		dev_set_mtu(amt->dev, new_mtu);
+					dev_set_mtu(amt->dev, new_mtu);
+				}
+			}
+		}
 		break;
 	}
 
-- 
2.33.0




^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-12 18:51 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-11  6:15 [PATCH net] amt: handle all upper amt devices in amt_device_event() Wenbo Sun
2026-11-12 18:51 ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox