summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-06-10 04:15:50 +0300
committerJakub Kicinski <kuba@kernel.org>2026-06-10 04:15:51 +0300
commit61abe5db23f0799e602352c796de6fcf76d23b41 (patch)
treeaab135dbf5fccc712bd89df915408c28e2da7a55 /include/linux
parent41d3e102edc2a6de73f0a32de6ce9a11243c14fa (diff)
parenta96c84126dc38e8d09aa93d165b30dc50c628562 (diff)
downloadlinux-61abe5db23f0799e602352c796de6fcf76d23b41.tar.xz
Merge branch 'net-add-retry-mechanism-to-ndo_set_rx_mode_async'
Stanislav Fomichev says: ==================== net: add retry mechanism to ndo_set_rx_mode_async Original async ndo_set_rx_mode work left one place where we do netdev_WARN in response to a ENOMEM. The intent was to see whether actual real users can hit that (adding uc/mc under memory pressure seems like a very unlikely thing to do). However, it was quickly triggered by syzbot's failslab. Add a retry mechanism and downgrade netdev_WARN to netdev_err. The retry logic is a typical exponential backoff: 1, 2, 4, 8 seconds, 15 in total, hopefully enough for a system to resolve memory pressure. ==================== Link: https://patch.msgid.link/20260608154014.227538-1-sdf@fomichev.me Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/netdevice.h16
1 files changed, 11 insertions, 5 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9b876cd930d7..7f4f0837c09f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1122,13 +1122,14 @@ struct netdev_net_notifier {
* Cannot sleep, called with netif_addr_lock_bh held.
* Deprecated in favor of ndo_set_rx_mode_async.
*
- * void (*ndo_set_rx_mode_async)(struct net_device *dev,
- * struct netdev_hw_addr_list *uc,
- * struct netdev_hw_addr_list *mc);
+ * int (*ndo_set_rx_mode_async)(struct net_device *dev,
+ * struct netdev_hw_addr_list *uc,
+ * struct netdev_hw_addr_list *mc);
* Async version of ndo_set_rx_mode which runs in process context
* with rtnl_lock and netdev_lock_ops(dev) held. The uc/mc parameters
* are snapshots of the address lists - iterate with
- * netdev_hw_addr_list_for_each(ha, uc).
+ * netdev_hw_addr_list_for_each(ha, uc). Return 0 on success or a
+ * negative errno to request a retry via the core backoff.
*
* int (*ndo_set_mac_address)(struct net_device *dev, void *addr);
* This function is called when the Media Access Control address
@@ -1455,7 +1456,7 @@ struct net_device_ops {
void (*ndo_change_rx_flags)(struct net_device *dev,
int flags);
void (*ndo_set_rx_mode)(struct net_device *dev);
- void (*ndo_set_rx_mode_async)(
+ int (*ndo_set_rx_mode_async)(
struct net_device *dev,
struct netdev_hw_addr_list *uc,
struct netdev_hw_addr_list *mc);
@@ -1932,6 +1933,8 @@ enum netdev_reg_state {
* @rx_mode_node: List entry for rx_mode work processing
* @rx_mode_tracker: Refcount tracker for rx_mode 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
* @uc: unicast mac addresses
* @mc: multicast mac addresses
* @dev_addrs: list of device hw addresses
@@ -2325,6 +2328,8 @@ struct net_device {
struct list_head rx_mode_node;
netdevice_tracker rx_mode_tracker;
struct netdev_hw_addr_list rx_mode_addr_cache;
+ struct timer_list rx_mode_retry_timer;
+ unsigned int rx_mode_retry_count;
#ifdef CONFIG_LOCKDEP
unsigned char nested_level;
#endif
@@ -5151,6 +5156,7 @@ static inline void __dev_mc_unsync(struct net_device *dev,
/* Functions used for secondary unicast and multicast support */
void dev_set_rx_mode(struct net_device *dev);
+void netif_rx_mode_schedule_retry(struct net_device *dev);
int netif_set_promiscuity(struct net_device *dev, int inc);
int dev_set_promiscuity(struct net_device *dev, int inc);
int netif_set_allmulti(struct net_device *dev, int inc, bool notify);