]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: ethtool: serialize broadcast notification sequence allocation
authorJakub Kicinski <kuba@kernel.org>
Fri, 5 Jun 2026 00:29:01 +0000 (17:29 -0700)
committerJakub Kicinski <kuba@kernel.org>
Tue, 9 Jun 2026 17:13:04 +0000 (10:13 -0700)
ethnl_bcast_seq is a global counter stamped into the nlmsg_seq field
of every multicast notification, allowing userspace to detect dropped
messages. Today the ordering is achieved by using rtnl_lock().

Moving forward we will want ethtool ops to run under just the netdev
instance lock so to establish ordering we need a separate lock
for notifications. With the netdev instance locks operations on
different devices may bypass each other but the expectation is
that it should not matter. What we need to prevent is:
 - notification IDs getting out of order
 - operations on one device getting out of order

For simplicity defer allocating the ID of the notification right
before the notification is delivered. This removes the need for
special handling in ethnl_rss_create_send_ntf().

Reviewed-by: Eric Dumazet <edumazet@google.com>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20260605002912.3456868-2-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ethtool/netlink.c
net/ethtool/netlink.h
net/ethtool/rss.c

index 25e22c48060a076ea6377e199d41a3c34798d5cf..c4054a9795ffbbd39d3e8fbcdf9211b7d6265d51 100644 (file)
 static struct genl_family ethtool_genl_family;
 
 static bool ethnl_ok __read_mostly;
+
+/* Serializes broadcast notification sequence allocation with the multicast
+ * send, so that userspace observes nlmsg_seq monotonic in receive order
+ * regardless of which lock the caller holds (rtnl or instance lock).
+ */
+static DEFINE_MUTEX(ethnl_bcast_lock);
 static u32 ethnl_bcast_seq;
 
 #define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS |    \
@@ -82,12 +88,6 @@ static void ethnl_sock_priv_destroy(void *priv)
        }
 }
 
-u32 ethnl_bcast_seq_next(void)
-{
-       ASSERT_RTNL();
-       return ++ethnl_bcast_seq;
-}
-
 int ethnl_ops_begin(struct net_device *dev)
 {
        int ret;
@@ -329,8 +329,7 @@ void *ethnl_dump_put(struct sk_buff *skb, struct netlink_callback *cb, u8 cmd)
 
 void *ethnl_bcastmsg_put(struct sk_buff *skb, u8 cmd)
 {
-       return genlmsg_put(skb, 0, ++ethnl_bcast_seq, &ethtool_genl_family, 0,
-                          cmd);
+       return genlmsg_put(skb, 0, 0, &ethtool_genl_family, 0, cmd);
 }
 
 void *ethnl_unicast_put(struct sk_buff *skb, u32 portid, u32 seq, u8 cmd)
@@ -340,8 +339,15 @@ void *ethnl_unicast_put(struct sk_buff *skb, u32 portid, u32 seq, u8 cmd)
 
 int ethnl_multicast(struct sk_buff *skb, struct net_device *dev)
 {
-       return genlmsg_multicast_netns(&ethtool_genl_family, dev_net(dev), skb,
-                                      0, ETHNL_MCGRP_MONITOR, GFP_KERNEL);
+       struct nlmsghdr *nlh = nlmsg_hdr(skb);
+       int ret;
+
+       mutex_lock(&ethnl_bcast_lock);
+       nlh->nlmsg_seq = ++ethnl_bcast_seq;
+       ret = genlmsg_multicast_netns(&ethtool_genl_family, dev_net(dev), skb,
+                                     0, ETHNL_MCGRP_MONITOR, GFP_KERNEL);
+       mutex_unlock(&ethnl_bcast_lock);
+       return ret;
 }
 
 /* GET request helpers */
@@ -1081,7 +1087,7 @@ void ethnl_notify(struct net_device *dev, unsigned int cmd,
 {
        if (unlikely(!ethnl_ok))
                return;
-       ASSERT_RTNL();
+       netdev_assert_locked_ops_compat(dev);
 
        if (likely(cmd < ARRAY_SIZE(ethnl_notify_handlers) &&
                   ethnl_notify_handlers[cmd]))
index 674c9c19529b73071ec488e48dde130799504e69..f94aaa66379cd28ae049535fb59753efea4e364f 100644 (file)
@@ -10,7 +10,6 @@
 
 struct ethnl_req_info;
 
-u32 ethnl_bcast_seq_next(void);
 int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
                               const struct nlattr *nest, struct net *net,
                               struct netlink_ext_ack *extack,
index 53792f53f9229fef855aa81969f837d1307f2ca5..65bad23d5c599eca1795de22321210f1754f2cd5 100644 (file)
@@ -995,7 +995,6 @@ ethnl_rss_create_send_ntf(const struct sk_buff *rsp, struct net_device *dev)
        nlh = nlmsg_hdr(ntf);
        /* Convert the reply into a notification */
        nlh->nlmsg_pid = 0;
-       nlh->nlmsg_seq = ethnl_bcast_seq_next();
 
        genl_hdr = nlmsg_data(nlh);
        genl_hdr->cmd = ETHTOOL_MSG_RSS_CREATE_NTF;