From: sdf.kernel@gmail.com
To: Jakub Kicinski <kuba@kernel.org>
Cc: Jakub Kicinski <kuba@kernel.org>,
netdev@vger.kernel.org, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com, jiri@resnulli.us, jv@jvosburgh.net
Subject: Re: [PATCH net-next v5 02/14] net: introduce ndo_set_rx_mode_async and netdev_rx_mode_work (61d75e67dcd2)
Date: Mon, 06 Apr 2026 15:29:22 -0700 [thread overview]
Message-ID: <cb163dc696c885556acea5f6fe2879ac.sdf.kernel@gmail.com> (raw)
In-Reply-To: <20260404000604.2413879-1-kuba@kernel.org>
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> Subject: net: introduce ndo_set_rx_mode_async and netdev_rx_mode_work
>
> This commit introduces an async variant of ndo_set_rx_mode that runs from a
> workqueue, allowing drivers to sleep during RX mode changes. It also adds
> netif_rx_mode_sync() to opportunistically flush pending updates before
> returning to userspace.
>
> > --- a/net/core/dev.c
> > +++ b/net/core/dev.c
> [ ... ]
> > @@ -12217,6 +12178,9 @@ void free_netdev(struct net_device *dev)
> >
> > kfree(rcu_dereference_protected(dev->ingress_queue, 1));
> >
> > + if (netif_rx_mode_clean(dev))
> > + dev_put(dev);
> > +
> > /* Flush device addresses */
> > dev_addr_flush(dev);
>
> Is this cleanup reachable during normal shutdown?
>
> When a device is queued to rx_mode_list, netif_rx_mode_queue() elevates its
> reference count via dev_hold(). During unregistration, netdev_wait_allrefs()
> blocks the system until all references are dropped.
>
> Because of this wait, the system shouldn't be able to reach free_netdev()
> until the worker thread has already dequeued the device and called
> dev_put(). It seems the device is guaranteed to not be on the list by the
> time this code executes.
I guess, yeah, we can drop this. netdev_wait_allrefs waits for all refs
to go away, so this is not needed.
>
> > --- a/net/core/dev_addr_lists.c
> > +++ b/net/core/dev_addr_lists.c
> [ ... ]
> > +static void netdev_rx_mode_work(struct work_struct *work)
> > +{
> > + struct net_device *dev;
> > +
> > + rtnl_lock();
> > +
> > + while (true) {
> > + spin_lock_bh(&rx_mode_lock);
> > + if (list_empty(&rx_mode_list)) {
> > + spin_unlock_bh(&rx_mode_lock);
> > + break;
> > + }
> > + dev = list_first_entry(&rx_mode_list, struct net_device,
> > + rx_mode_node);
> > + list_del_init(&dev->rx_mode_node);
> > + spin_unlock_bh(&rx_mode_lock);
> > +
> > + netdev_lock_ops(dev);
>
> Can this while loop starve the system of the rtnl lock?
>
> Since userspace can trigger RX mode updates via ioctls like SIOCADDMULTI
> while holding only netdev_lock_ops() and not the rtnl lock, a continuous
> stream of these operations could repeatedly add devices to rx_mode_list.
>
> Because the loop releases rx_mode_lock while processing but retains the rtnl
> lock, could it run indefinitely if the list is continually replenished?
Idk, this seems overly paranoid, the same work would happen under rtnl
on the main thread if we don't do a async callback.
> Additionally, does the order of list_del_init() and netdev_lock_ops() create
> a race condition with netif_rx_mode_sync()?
>
> If the worker thread dequeues the device and drops the spinlock, it might
> then block waiting for netdev_lock_ops(). Meanwhile, an ioctl thread
> holding netdev_lock_ops() might call netif_rx_mode_sync().
>
> The ioctl thread would call netif_rx_mode_clean(), which checks
> list_empty(). Since the worker already removed the device from the list,
> clean returns false. This causes netif_rx_mode_sync() to act as a no-op,
> allowing the ioctl to return to userspace before the hardware update
> actually completes.
The worst thing that can happen is we re-queue empty work. I don't see
how we can return to userspace without having a sync update.
>
> > --- a/net/core/dev_api.c
> > +++ b/net/core/dev_api.c
> [ ... ]
> > @@ -311,6 +313,7 @@ int dev_set_allmulti(struct net_device *dev, int inc)
> >
> > netdev_lock_ops(dev);
> > ret = netif_set_allmulti(dev, inc, true);
> > + netif_rx_mode_sync(dev);
> > netdev_unlock_ops(dev);
> >
> > return ret;
>
> Does this correctly handle cascaded updates for stacked devices?
>
> When operating on a stacked device like a VLAN, the RX mode update cascades
> to the underlying physical device, queuing the physical device to the
> rx_mode_list via __dev_set_rx_mode().
>
> Since netif_rx_mode_sync() is only called on the stacked device here, and
> the stacked device itself is not on the rx_mode_list, will the physical
> device's update be left on the workqueue? This seems to bypass the
> synchronous update guarantee.
Yes, this assessment is correct in general. Not sure we want some new
netif_rx_mode_deep_sync or (probably better?) add some netif_rx_mode_sync
calls where appropriate. For now, leaving netif_rx_mode_sync in a few
places and planning to add more netif_rx_mode_sync if/when issues with
deep hierarchy syncing arise.
next prev parent reply other threads:[~2026-04-06 22:29 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-02 22:55 [PATCH net-next v5 00/14] net: sleepable ndo_set_rx_mode Stanislav Fomichev
2026-04-02 22:55 ` [PATCH net-next v5 01/14] net: add address list snapshot and reconciliation infrastructure Stanislav Fomichev
2026-04-04 0:06 ` Jakub Kicinski
2026-04-06 22:29 ` [PATCH net-next v5 01/14] net: add address list snapshot and reconciliation infrastructure (123ac7a76378) sdf.kernel
2026-04-02 22:55 ` [PATCH net-next v5 02/14] net: introduce ndo_set_rx_mode_async and netdev_rx_mode_work Stanislav Fomichev
2026-04-04 0:06 ` Jakub Kicinski
2026-04-06 22:29 ` sdf.kernel [this message]
2026-04-04 0:27 ` Jakub Kicinski
2026-04-06 22:29 ` [PATCH net-next v5 02/14] net: introduce ndo_set_rx_mode_async and netdev_rx_mode_work (61d75e67dcd2) sdf.kernel
2026-04-02 22:55 ` [PATCH net-next v5 03/14] net: move promiscuity handling into netdev_rx_mode_work Stanislav Fomichev
2026-04-04 0:06 ` Jakub Kicinski
2026-04-06 22:29 ` [PATCH net-next v5 03/14] net: move promiscuity handling into netdev_rx_mode_work (ddeab417d841) sdf.kernel
2026-04-02 22:55 ` [PATCH net-next v5 04/14] net: cache snapshot entries for ndo_set_rx_mode_async Stanislav Fomichev
2026-04-02 22:55 ` [PATCH net-next v5 05/14] fbnic: convert to ndo_set_rx_mode_async Stanislav Fomichev
2026-04-04 0:06 ` Jakub Kicinski
2026-04-06 22:29 ` [PATCH net-next v5 05/14] fbnic: convert to ndo_set_rx_mode_async (1d5e76c60ed0) sdf.kernel
2026-04-02 22:55 ` [PATCH net-next v5 06/14] mlx5: convert to ndo_set_rx_mode_async Stanislav Fomichev
2026-04-04 0:06 ` Jakub Kicinski
2026-04-06 22:29 ` [PATCH net-next v5 06/14] mlx5: convert to ndo_set_rx_mode_async (3691f90f6593) sdf.kernel
2026-04-02 22:55 ` [PATCH net-next v5 07/14] bnxt: convert to ndo_set_rx_mode_async Stanislav Fomichev
2026-04-04 0:06 ` Jakub Kicinski
2026-04-06 22:29 ` [PATCH net-next v5 07/14] bnxt: convert to ndo_set_rx_mode_async (c1776bbe53ec) sdf.kernel
2026-04-02 22:55 ` [PATCH net-next v5 08/14] bnxt: use snapshot in bnxt_cfg_rx_mode Stanislav Fomichev
2026-04-04 0:06 ` Jakub Kicinski
2026-04-06 22:29 ` [PATCH net-next v5 08/14] bnxt: use snapshot in bnxt_cfg_rx_mode (74e346419df6) sdf.kernel
2026-04-02 22:55 ` [PATCH net-next v5 09/14] iavf: convert to ndo_set_rx_mode_async Stanislav Fomichev
2026-04-04 0:06 ` Jakub Kicinski
2026-04-06 22:29 ` [PATCH net-next v5 09/14] iavf: convert to ndo_set_rx_mode_async (b1dc10d5dff2) sdf.kernel
2026-04-02 22:55 ` [PATCH net-next v5 10/14] netdevsim: convert to ndo_set_rx_mode_async Stanislav Fomichev
2026-04-02 22:55 ` [PATCH net-next v5 11/14] dummy: " Stanislav Fomichev
2026-04-02 22:55 ` [PATCH net-next v5 12/14] net: warn ops-locked drivers still using ndo_set_rx_mode Stanislav Fomichev
2026-04-02 22:55 ` [PATCH net-next v5 13/14] selftests: net: add team_bridge_macvlan rx_mode test Stanislav Fomichev
2026-04-02 22:55 ` [PATCH net-next v5 14/14] selftests: net: use ip commands instead of teamd in team " Stanislav Fomichev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cb163dc696c885556acea5f6fe2879ac.sdf.kernel@gmail.com \
--to=sdf.kernel@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jiri@resnulli.us \
--cc=jv@jvosburgh.net \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.