net: avoid nested UP notifier events
Subsystems (5)
Jakub Kicinski
maintainercover net: avoid nested UP notifier events
syzbot reported that recent ethtool rework leads to deadlock on stacked devices. VLANs create nested notifications, confusing execution context. Bringing up dummy causes vlan to bring itself up as well. Which in turn causes bond to ask for link state - a call chain traveling in the opposite direction.
bond (3) bond_update_speed_duplex(vlan)
| ^ v
vlan (2) UP(vlan) (4) vlan_ethtool_get_link_ksettings()
| ^ v
dummy (1) UP(dummy) (5) __ethtool_get_link_ksettings()
We locked the instance lock of dummy at (1) and will will try to lock it again at (5) - which of course deadlocks.
For non-nested notifications this is avoided because NETDEV_UP is always run ops-locked (so that bond asks for link using the netif_ API which assumes instance lock already held). The nesting, however, makes this problematic, we cannot carry the state of the whole chain back in the opposite direction.
AFAICT vlan is the only driver which causes such issues. So let's try a localized fix of deferring vlan auto-open to a workqueue.
Jakub Kicinski (4):
net: turn the rx_mode work into a generic netdev_work facility
net: add the driver-facing netdev_work scheduling API
vlan: defer real device state propagation to netdev_work
selftests: bonding: add a test for VLAN propagation over a bonded real
device
Documentation/networking/netdevices.rst | 2 + net/core/Makefile | 2 +- .../selftests/drivers/net/bonding/Makefile | 1 + include/linux/netdevice.h | 21 +- net/8021q/vlan.h | 11 ++ net/core/dev.h | 11 +- net/8021q/vlan.c | 76 +------- net/8021q/vlan_dev.c | 60 ++++++ net/core/dev.c | 2 + net/core/dev_addr_lists.c | 77 +------- net/core/netdev_work.c | 162 ++++++++++++++++ .../drivers/net/bonding/bond_vlan_real_dev.sh | 180 ++++++++++++++++++ 12 files changed, 457 insertions(+), 148 deletions(-) create mode 100644 net/core/netdev_work.c create mode 100755 tools/testing/selftests/drivers/net/bonding/bond_vlan_real_dev.sh
Signature · 1 line
2.54.0
Jakub Kicinski
maintainerPATCH 1/4 net: turn the rx_mode work into a generic netdev_work facility
The rx_mode update runs from a workqueue: drivers have their ndo_set_rx_mode_async() callback executed by a single global work item under RTNL and ops lock. This is a useful pattern.
Support multiple "events" that need to be serviced and make RX_MODE sync the first one. Call the events "core" because later on we will let drivers define and schedule their own.
--- net/core/Makefile | 2 +- include/linux/netdevice.h | 10 ++-- net/core/dev.h | 11 +++- net/core/dev.c | 1 + net/core/dev_addr_lists.c | 77 +------------------------ net/core/netdev_work.c | 117 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 138 insertions(+), 80 deletions(-) create mode 100644 net/core/netdev_work.c
net/core/Makefile +1 -1
@@ -13,7 +13,7 @@ obj-y += dev.o dev_api.o dev_addr_lists.o dst.o netevent.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ fib_notifier.o xdp.o flow_offload.o gro.o \ - netdev-genl.o netdev-genl-gen.o gso.o + netdev-genl.o netdev-genl-gen.o netdev_work.o gso.o obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o
include/linux/netdevice.h +6 -4
@@ -1930,8 +1930,9 @@ enum netdev_reg_state {* has been enabled due to the need to listen to * additional unicast addresses in a device that * does not implement ndo_set_rx_mode() -* @rx_mode_node: List entry for rx_mode work processing -* @rx_mode_tracker: Refcount tracker for rx_mode work +* @work_node: List entry for async netdev_work processing +* @work_tracker: Refcount tracker for async netdev_work +* @work_core_pending: Core-defined pending netdev_work (NETDEV_WORK_*) * @rx_mode_addr_cache: Recycled snapshot entries for rx_mode work * @rx_mode_retry_timer: Timer that re-queues rx_mode work after failure * @rx_mode_retry_count: Number of consecutive retries already scheduled
@@ -2326,8 +2327,9 @@ struct net_device {unsigned int promiscuity;unsigned int allmulti;bool uc_promisc; -struct list_head rx_mode_node; -netdevice_tracker rx_mode_tracker; +struct list_head work_node; +netdevice_tracker work_tracker; +unsigned long work_core_pending;struct netdev_hw_addr_list rx_mode_addr_cache;struct timer_list rx_mode_retry_timer;unsigned int rx_mode_retry_count;
net/core/dev.h +10 -1
@@ -167,10 +167,19 @@ int dev_change_carrier(struct net_device *dev, bool new_carrier);void __dev_set_rx_mode (struct net_device *dev);int __dev_set_promiscuity (struct net_device *dev,int inc,bool notify);void netif_rx_mode_init (struct net_device *dev); -bool netif_rx_mode_clean (struct net_device *dev); +void netif_rx_mode_run (struct net_device *dev);void netif_rx_mode_sync (struct net_device *dev);void netif_rx_mode_cancel_retry (struct net_device *dev); +/* Events for the async netdev work, tracked in netdev->work_core_pending. */ +enum netdev_work_core { +NETDEV_WORK_RX_MODE =BIT (0 ),/* run the rx_mode update */ +}; + +void __netdev_work_core_sched (struct net_device *dev,unsigned long event); +unsigned long +__netdev_work_core_cancel (struct net_device *dev,unsigned long mask); +void __dev_notify_flags (struct net_device *dev,unsigned int old_flags,unsigned int gchanges,u32 portid,const struct nlmsghdr *nlh);
net/core/dev.c +1 -0
@@ -12093,6 +12093,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,INIT_LIST_HEAD (&dev->ptype_all);INIT_LIST_HEAD (&dev->ptype_specific);INIT_LIST_HEAD (&dev->net_notifier_list); +INIT_LIST_HEAD (&dev->work_node);#ifdef CONFIG_NET_SCHED hash_init (dev->qdisc_hash);#endif
net/core/dev_addr_lists.c +3 -74
118 lines not on this page · raw message
net/core/netdev_work.c new file +117 -0
117 lines not on this page · raw message
Signature · 1 line
2.54.0
Re: [PATCH net 1/4] net: turn the rx_mode work into a generic netdev_work facility
Quoted 10 lines · Jakub Kicinski
The
rx_modeupdate runs from a workqueue: drivers have theirndo_set_rx_mode_async()callback executed by a single global work item under RTNL and ops lock. This is a useful pattern.Support multiple "events" that need to be serviced and make
RX_MODEsync the first one. Call the events "core" because later on we will let drivers define and schedule their own.Signed-off-by Jakub Kicinski <[email protected]>
Oh very nice !
I was drafting almost the same change for dev_set_rx_mode() in mcast path and some ipvlan changes.
Jakub Kicinski
maintainerRe: [PATCH net 1/4] net: turn the rx_mode work into a generic netdev_work facility
Quoted 4 lines · On Wed, 24 Jun 2026 22:55:06 -0700 Kuniyuki Iwashima wrote:
Oh very nice !
I was drafting almost the same change for
dev_set_rx_mode()in mcast path and some ipvlan changes.
Glad to hear! I wasn't 100% convinced by the added complexity in the core :S
Re: [PATCH net 1/4] net: turn the rx_mode work into a generic netdev_work facility
In reply to Jakub KicinskiQuoted 9 lines · Jakub Kicinski
The
rx_modeupdate runs from a workqueue: drivers have theirndo_set_rx_mode_async()callback executed by a single global work item under RTNL and ops lock. This is a useful pattern.Support multiple "events" that need to be serviced and make
RX_MODEsync the first one. Call the events "core" because later on we will let drivers define and schedule their own.Signed-off-by Jakub Kicinski <[email protected]>
Jakub Kicinski
maintainerPATCH 2/4 net: add the driver-facing netdev_work scheduling API
In reply to Jakub KicinskiWith an extra event mask we can easily extend the netdev work to also service driver-defined events. For advanced drivers this is probably not a perfect match, but it makes running deferred work easier in simple cases.
Expose the netdev_work facility to drivers. Add helpers to schedule work and a dedicated ndo to perform the driver- -scheduled actions.
--- include/linux/netdevice.h | 11 ++++++ net/core/netdev_work.c | 81 ++++++++++++++++++++++++++++++--------- 2 files changed, 74 insertions(+), 18 deletions(-)
include/linux/netdevice.h +11 -0
@@ -1131,6 +1131,9 @@ struct netdev_net_notifier {* netdev_hw_addr_list_for_each(ha, uc). Return 0 on success or a * negative errno to request a retry via the core backoff. * +* void (*ndo_work)(struct net_device *dev, unsigned long events); +* Run deferred work scheduled with netdev_work_sched(@events). +* * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); * This function is called when the Media Access Control address * needs to be changed. If this interface is not defined, the
@@ -1460,6 +1463,8 @@ struct net_device_ops {struct net_device *dev, struct netdev_hw_addr_list *uc, struct netdev_hw_addr_list *mc); +void (*ndo_work)(struct net_device *dev, +unsigned long events);int (*ndo_set_mac_address)(struct net_device *dev,void *addr);int (*ndo_validate_addr)(struct net_device *dev);
@@ -1932,6 +1937,8 @@ enum netdev_reg_state {* does not implement ndo_set_rx_mode() * @work_node: List entry for async netdev_work processing * @work_tracker: Refcount tracker for async netdev_work +* @work_pending: Driver-defined pending netdev_work, passed to +* ndo_work() (see netdev_work_sched()) * @work_core_pending: Core-defined pending netdev_work (NETDEV_WORK_*) * @rx_mode_addr_cache: Recycled snapshot entries for rx_mode work * @rx_mode_retry_timer: Timer that re-queues rx_mode work after failure
@@ -2329,6 +2336,7 @@ struct net_device {bool uc_promisc;struct list_head work_node;netdevice_tracker work_tracker; +unsigned long work_pending;unsigned long work_core_pending;struct netdev_hw_addr_list rx_mode_addr_cache;struct timer_list rx_mode_retry_timer;
@@ -5178,6 +5186,9 @@ void dev_fetch_sw_netstats(struct rtnl_link_stats64 *s, const struct pcpu_sw_netstats __percpu *netstats);void dev_get_tstats64 (struct net_device *dev,struct rtnl_link_stats64 *s); +void netdev_work_sched (struct net_device *dev,unsigned long events); +unsigned long netdev_work_cancel (struct net_device *dev,unsigned long mask); +enum {NESTED_SYNC_IMM_BIT ,NESTED_SYNC_TODO_BIT ,
net/core/netdev_work.c +63 -18
146 lines not on this page · raw message
Signature · 1 line
2.54.0
Re: [PATCH net 2/4] net: add the driver-facing netdev_work scheduling API
Quoted 11 lines · Jakub Kicinski
With an extra event mask we can easily extend the netdev work to also service driver-defined events. For advanced drivers this is probably not a perfect match, but it makes running deferred work easier in simple cases.
Expose the
netdev_workfacility to drivers. Add helpers to schedule work and a dedicated ndo to perform the driver- -scheduled actions.Signed-off-by Jakub Kicinski <[email protected]>
Re: [PATCH net 2/4] net: add the driver-facing netdev_work scheduling API
In reply to Jakub KicinskiQuoted 10 lines · Jakub Kicinski
With an extra event mask we can easily extend the netdev work to also service driver-defined events. For advanced drivers this is probably not a perfect match, but it makes running deferred work easier in simple cases.
Expose the
netdev_workfacility to drivers. Add helpers to schedule work and a dedicated ndo to perform the driver- -scheduled actions.Signed-off-by Jakub Kicinski <[email protected]>
Jakub Kicinski
maintainerPATCH 3/4 vlan: defer real device state propagation to netdev_work
In reply to Jakub Kicinskivlan_device_event() generates nested UP/DOWN, MTU and feature change events. It executes an event for the VLAN device directly from the notifier - while the locks of the lower device are held.
This causes deadlocks, for example:
bond (3) bond_update_speed_duplex(vlan)
| ^ v
vlan (2) UP(vlan) (4) vlan_ethtool_get_link_ksettings()
| ^ v
dummy (1) UP(dummy) (5) __ethtool_get_link_ksettings()
The dummy device is ops locked, vlan creates a nested event (2), then bond wants to ask vlan for link state (3). bond uses the "I'm already holding the instance lock" flavor of API. But in this case the lock held refers to vlan itself. We hit vlan's link settings trampoline (4) and call __ethtool_get_link_ksettings() which tries to lock dummy. Deadlock. There's no clean way for us to tell the vlan_ethtool_get_link_ksettings() that the caller is already in lower device's critical section.
Defer the propagation to the per-netdev work facility instead:
the notifier only schedules netdev_work_sched(vlandev, VLAN_WORK_*), and ndo_work (vlan_dev_work) applies the change later. Hopefully nobody expects the VLAN state changes to be instantaneous.
If someone does expect the changes to be instantaneous we will have to do the same thing Stan did for rx_mode and "strategically" place sync calls, to make sure such delayed works are executed after we drop the ops lock but before we drop rtnl_lock.
Stan suggests that if we need that down the line we may consider reshaping the mechanism into "async notifications". AFAICT only vlan does this sort of netdev open chaining, so as a first try I think that sticking the complexity into the vlan code makes sense.
One corner case is that we need to cancel the event if user explicitly changes the state before work could run. Consider the following operations with vlan0 on top of dummy0:
ip link set dev dummy0 up # queues work to up vlan0 ip link set dev vlan0 down # user explicitly downs the vlan ndo_work # acts on the stale event
--- Documentation/networking/netdevices.rst | 2 + net/8021q/vlan.h | 11 ++++ net/8021q/vlan.c | 76 +++---------------------- net/8021q/vlan_dev.c | 60 +++++++++++++++++++ net/core/dev.c | 1 + 5 files changed, 82 insertions(+), 68 deletions(-)
Documentation/networking/netdevices.rst +2 -0
@@ -433,6 +433,8 @@ exceptions) notifiers run under the instance lock. Please extend this documentation whenever you make explicit assumption about lock being held from a notifier. +Drivers **must not** generate nested notifications of the ops-locked types. + NETDEV_INTERNAL symbol namespace ================================
net/8021q/vlan.h +11 -0
@@ -125,6 +125,17 @@ static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)int vlan_filter_push_vids (struct vlan_info *vlan_info,__be16 proto);void vlan_filter_drop_vids (struct vlan_info *vlan_info,__be16 proto); +/* netdev_work events propagated from the real device, see vlan_dev_work(). */ +enum { +VLAN_WORK_LINK_STATE =BIT (0 ),/* sync up/down with real_dev */ +VLAN_WORK_MTU =BIT (1 ),/* clamp mtu to real_dev's */ +VLAN_WORK_FEATURES =BIT (2 ),/* re-inherit real_dev features */ +}; + +void vlan_stacked_transfer_operstate (const struct net_device *rootdev, +struct net_device *dev, +struct vlan_dev_priv *vlan); +/* found in vlan_dev.c */ void vlan_dev_set_ingress_priority (const struct net_device *dev,u32 skb_prio,u16 vlan_prio);
net/8021q/vlan.c +8 -68
113 lines not on this page · raw message
net/8021q/vlan_dev.c +60 -0
84 lines not on this page · raw message
net/core/dev.c +1 -0
@@ -9822,6 +9822,7 @@ int netif_change_flags(struct net_device *dev, unsigned int flags,__dev_notify_flags (dev, old_flags, changes,0 ,NULL );return ret; } +EXPORT_SYMBOL (netif_change_flags);int __netif_set_mtu (struct net_device *dev,int new_mtu) {
Signature · 1 line
2.54.0
Re: [PATCH net 3/4] vlan: defer real device state propagation to netdev_work
Quoted 46 lines · Jakub Kicinski
vlan_device_event()generates nested UP/DOWN, MTU and feature change events. It executes an event for the VLAN device directly from the notifier - while the locks of the lower device are held.This causes deadlocks, for example:
bond (3)
bond_update_speed_duplex(vlan)
| ^ v
vlan (2) UP(vlan) (4)vlan_ethtool_get_link_ksettings()
| ^ v
dummy (1) UP(dummy) (5)__ethtool_get_link_ksettings()The dummy device is ops locked, vlan creates a nested event (2), then bond wants to ask vlan for link state (3). bond uses the "I'm already holding the instance lock" flavor of API. But in this case the lock held refers to vlan itself. We hit vlan's link settings trampoline (4) and call
__ethtool_get_link_ksettings()which tries to lock dummy. Deadlock. There's no clean way for us to tell thevlan_ethtool_get_link_ksettings()that the caller is already in lower device's critical section.Defer the propagation to the per-netdev work facility instead:
the notifier only schedulesnetdev_work_sched(vlandev, VLAN_WORK_*), andndo_work(vlan_dev_work) applies the change later. Hopefully nobody expects the VLAN state changes to be instantaneous.If someone does expect the changes to be instantaneous we will have to do the same thing Stan did for
rx_modeand "strategically" place sync calls, to make sure such delayed works are executed after we drop the ops lock but before we droprtnl_lock.Stan suggests that if we need that down the line we may consider reshaping the mechanism into "async notifications". AFAICT only vlan does this sort of netdev open chaining, so as a first try I think that sticking the complexity into the vlan code makes sense.
One corner case is that we need to cancel the event if user explicitly changes the state before work could run. Consider the following operations with vlan0 on top of dummy0:
ip link set dev dummy0 up # queues work to up vlan0 ip link set dev vlan0 down # user explicitly downs the vlan ndo_work # acts on the stale event
Quoted 5 lines
Reported-by [email protected]Reported-by [email protected]Reported-by [email protected]Fixes 9f275c2e9020 ("net: ethtool: make sure __ethtool_get_link_ksettings() is ops-locked")Signed-off-by Jakub Kicinski <[email protected]>
Thanks !
Re: [PATCH net 3/4] vlan: defer real device state propagation to netdev_work
In reply to Jakub KicinskiQuoted 45 lines · Jakub Kicinski
vlan_device_event()generates nested UP/DOWN, MTU and feature change events. It executes an event for the VLAN device directly from the notifier - while the locks of the lower device are held.This causes deadlocks, for example:
bond (3)
bond_update_speed_duplex(vlan)
| ^ v
vlan (2) UP(vlan) (4)vlan_ethtool_get_link_ksettings()
| ^ v
dummy (1) UP(dummy) (5)__ethtool_get_link_ksettings()The dummy device is ops locked, vlan creates a nested event (2), then bond wants to ask vlan for link state (3). bond uses the "I'm already holding the instance lock" flavor of API. But in this case the lock held refers to vlan itself. We hit vlan's link settings trampoline (4) and call
__ethtool_get_link_ksettings()which tries to lock dummy. Deadlock. There's no clean way for us to tell thevlan_ethtool_get_link_ksettings()that the caller is already in lower device's critical section.Defer the propagation to the per-netdev work facility instead:
the notifier only schedulesnetdev_work_sched(vlandev, VLAN_WORK_*), andndo_work(vlan_dev_work) applies the change later. Hopefully nobody expects the VLAN state changes to be instantaneous.If someone does expect the changes to be instantaneous we will have to do the same thing Stan did for
rx_modeand "strategically" place sync calls, to make sure such delayed works are executed after we drop the ops lock but before we droprtnl_lock.Stan suggests that if we need that down the line we may consider reshaping the mechanism into "async notifications". AFAICT only vlan does this sort of netdev open chaining, so as a first try I think that sticking the complexity into the vlan code makes sense.
One corner case is that we need to cancel the event if user explicitly changes the state before work could run. Consider the following operations with vlan0 on top of dummy0:
ip link set dev dummy0 up # queues work to up vlan0 ip link set dev vlan0 down # user explicitly downs the vlan ndo_work # acts on the stale event
Quoted 8 lines
Reported-by [email protected]Reported-by [email protected]Reported-by [email protected]Fixes 9f275c2e9020 ("net: ethtool: make sure __ethtool_get_link_ksettings() is ops-locked")Signed-off-by Jakub Kicinski <[email protected]>---
[...]
Thanks
Nicolai
Re: [PATCH net 3/4] vlan: defer real device state propagation to netdev_work
In reply to Jakub KicinskiQuoted 45 lines · Jakub Kicinski
vlan_device_event()generates nested UP/DOWN, MTU and feature change events. It executes an event for the VLAN device directly from the notifier - while the locks of the lower device are held.This causes deadlocks, for example:
bond (3)
bond_update_speed_duplex(vlan)
| ^ v
vlan (2) UP(vlan) (4)vlan_ethtool_get_link_ksettings()
| ^ v
dummy (1) UP(dummy) (5)__ethtool_get_link_ksettings()The dummy device is ops locked, vlan creates a nested event (2), then bond wants to ask vlan for link state (3). bond uses the "I'm already holding the instance lock" flavor of API. But in this case the lock held refers to vlan itself. We hit vlan's link settings trampoline (4) and call
__ethtool_get_link_ksettings()which tries to lock dummy. Deadlock. There's no clean way for us to tell thevlan_ethtool_get_link_ksettings()that the caller is already in lower device's critical section.Defer the propagation to the per-netdev work facility instead:
the notifier only schedulesnetdev_work_sched(vlandev, VLAN_WORK_*), andndo_work(vlan_dev_work) applies the change later. Hopefully nobody expects the VLAN state changes to be instantaneous.If someone does expect the changes to be instantaneous we will have to do the same thing Stan did for
rx_modeand "strategically" place sync calls, to make sure such delayed works are executed after we drop the ops lock but before we droprtnl_lock.Stan suggests that if we need that down the line we may consider reshaping the mechanism into "async notifications". AFAICT only vlan does this sort of netdev open chaining, so as a first try I think that sticking the complexity into the vlan code makes sense.
One corner case is that we need to cancel the event if user explicitly changes the state before work could run. Consider the following operations with vlan0 on top of dummy0:
ip link set dev dummy0 up # queues work to up vlan0 ip link set dev vlan0 down # user explicitly downs the vlan ndo_work # acts on the stale event
Quoted 5 lines
Reported-by [email protected]Reported-by [email protected]Reported-by [email protected]Fixes 9f275c2e9020 ("net: ethtool: make sure __ethtool_get_link_ksettings() is ops-locked")Signed-off-by Jakub Kicinski <[email protected]>
Jakub Kicinski
maintainerPATCH 4/4 selftests: bonding: add a test for VLAN propagation over a bonded real device
In reply to Jakub KicinskiAdd a regression test for the VLAN notifier handling that the netdev_work deferral fixed.
A VLAN's real device propagates its UP/DOWN, MTU and feature changes onto the VLANs stacked on top of it. This used to be done synchronously from the real device's notifier and deadlocked when the real device was brought up while enslaved to a bond (instance lock held across NETDEV_UP) and the VLAN on top was itself a bond member: the synchronous propagation re-entered the stack and took the same instance lock again.
The test covers both halves:
- that the deferred UP/DOWN, MTU and feature propagation actually lands on the VLAN (link state and MTU use an ops-locked dummy, i.e. the deferral path; features use veth, which exports vlan_features to inherit), and
- that the deadlock-prone topology - a VLAN on a dummy, with the VLAN and the dummy each enslaved to a different bond - can be built without hanging.
--- .../selftests/drivers/net/bonding/Makefile | 1 + .../drivers/net/bonding/bond_vlan_real_dev.sh | 180 ++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100755 tools/testing/selftests/drivers/net/bonding/bond_vlan_real_dev.sh
tools/testing/selftests/drivers/net/bonding/Makefile +1 -0
@@ -13,6 +13,7 @@ TEST_PROGS := \ bond_options.sh \ bond_passive_lacp.sh \ bond_stacked_header_parse.sh \ + bond_vlan_real_dev.sh \ dev_addr_lists.sh \ mode-1-recovery-updelay.sh \ mode-2-recovery-updelay.sh \
tools/testing/selftests/drivers/net/bonding/bond_vlan_real_dev.sh new file +180 -0
180 lines not on this page · raw message
Signature · 1 line
2.54.0
RE: [PATCH net 4/4] selftests: bonding: add a test for VLAN propagation over a bonded real device
Quoted 69 lines
-----Original Message-----
From: Jakub Kicinski <[email protected]>
Sent: Wednesday, June 24, 2026 8:20 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; nb@tipi- net.de; Loktionov, Aleksandr <[email protected]>; [email protected]; Jakub Kicinski <[email protected]>
Subject: [PATCH net 4/4] selftests: bonding: add a test for VLAN propagation over a bonded real deviceAdd a regression test for the VLAN notifier handling that the
netdev_workdeferral fixed.A VLAN's real device propagates its UP/DOWN, MTU and feature changes onto the VLANs stacked on top of it. This used to be done synchronously from the real device's notifier and deadlocked when the real device was brought up while enslaved to a bond (instance lock held across
NETDEV_UP) and the VLAN on top was itself a bond member:
the synchronous propagation re-entered the stack and took the same instance lock again.The test covers both halves:
- that the deferred UP/DOWN, MTU and feature propagation actually
lands on
the VLAN (link state and MTU use an ops-locked dummy, i.e. the
deferral
path; features use veth, which exportsvlan_featuresto inherit),
and
- that the deadlock-prone topology - a VLAN on a dummy, with the VLAN
and
the dummy each enslaved to a different bond - can be built without hanging.Signed-off-by Jakub Kicinski <[email protected]>--- .../selftests/drivers/net/bonding/Makefile | 1 + .../drivers/net/bonding/bond_vlan_real_dev.sh | 180 ++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100755
tools/testing/selftests/drivers/net/bonding/bond_vlan_real_dev.shtools/testing/selftests/drivers/net/bonding/Makefile +1
-0@@ -13,6 +13,7 @@ TEST_PROGS := \ bond_options.sh \ bond_passive_lacp.sh \ bond_stacked_header_parse.sh \ + bond_vlan_real_dev.sh \ dev_addr_lists.sh \ mode-1-recovery-updelay.sh \ mode-2-recovery-updelay.sh \diff --git
a/tools/testing/selftests/drivers/net/bonding/bond_vlan_real_dev.shb/tools/testing/selftests/drivers/net/bonding/bond_vlan_real_dev.shnew file mode 100755
index 000000000000..542d9ffc4819
---/dev/null
+++b/tools/testing/selftests/drivers/net/bonding/bond_vlan_real_dev.shtools/testing/selftests/drivers/net/bonding/Makefile +0
-0@@ -0,0 +1,180 @@
...
Quoted 3 lines
+exit "$EXIT_STATUS"
--
2.54.0
Re: [PATCH net 4/4] selftests: bonding: add a test for VLAN propagation over a bonded real device
In reply to Jakub KicinskiQuoted 18 lines · Jakub Kicinski
Add a regression test for the VLAN notifier handling that the
netdev_workdeferral fixed.A VLAN's real device propagates its UP/DOWN, MTU and feature changes onto the VLANs stacked on top of it. This used to be done synchronously from the real device's notifier and deadlocked when the real device was brought up while enslaved to a bond (instance lock held across
NETDEV_UP) and the VLAN on top was itself a bond member: the synchronous propagation re-entered the stack and took the same instance lock again.The test covers both halves:
- that the deferred UP/DOWN, MTU and feature propagation actually lands on the VLAN (link state and MTU use an ops-locked dummy, i.e. the deferral path; features use veth, which exportsvlan_featuresto inherit), and
- that the deadlock-prone topology - a VLAN on a dummy, with the VLAN and the dummy each enslaved to a different bond - can be built without hanging.
Quoted 1 line
Signed-off-by Jakub Kicinski <[email protected]>