]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netlink: introduce type-checking attribute iteration for nlmsg
authorCarolina Jubran <cjubran@nvidia.com>
Sun, 29 Jun 2025 14:21:31 +0000 (17:21 +0300)
committerJakub Kicinski <kuba@kernel.org>
Wed, 2 Jul 2025 22:39:04 +0000 (15:39 -0700)
Add the nlmsg_for_each_attr_type() macro to simplify iteration over
attributes of a specific type in a Netlink message.

Convert existing users in vxlan and nfsd to use the new macro.

Suggested-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250629142138.361537-2-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/vxlan/vxlan_vnifilter.c
fs/nfsd/nfsctl.c
include/net/netlink.h

index 4ff56d9f8f2822be9a28902e201820fd039be3df..adc89e651e27c8f1a7d95ec107415f6e82a0247c 100644 (file)
@@ -971,15 +971,10 @@ static int vxlan_vnifilter_process(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (!(vxlan->cfg.flags & VXLAN_F_VNIFILTER))
                return -EOPNOTSUPP;
 
-       nlmsg_for_each_attr(attr, nlh, sizeof(*tmsg), rem) {
-               switch (nla_type(attr)) {
-               case VXLAN_VNIFILTER_ENTRY:
-                       err = vxlan_process_vni_filter(vxlan, attr,
-                                                      nlh->nlmsg_type, extack);
-                       break;
-               default:
-                       continue;
-               }
+       nlmsg_for_each_attr_type(attr, VXLAN_VNIFILTER_ENTRY, nlh,
+                                sizeof(*tmsg), rem) {
+               err = vxlan_process_vni_filter(vxlan, attr, nlh->nlmsg_type,
+                                              extack);
                vnis++;
                if (err)
                        break;
index 6a42cc7a845a144baf3e84d17e415d5380ccdc57..657d44afc062c1dd1365cb04096ed7ea567d80e5 100644 (file)
@@ -1621,10 +1621,9 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
                return -EINVAL;
 
        /* count number of SERVER_THREADS values */
-       nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) {
-               if (nla_type(attr) == NFSD_A_SERVER_THREADS)
-                       nrpools++;
-       }
+       nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_THREADS, info->nlhdr,
+                                GENL_HDRLEN, rem)
+               nrpools++;
 
        mutex_lock(&nfsd_mutex);
 
@@ -1635,12 +1634,11 @@ int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info)
        }
 
        i = 0;
-       nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) {
-               if (nla_type(attr) == NFSD_A_SERVER_THREADS) {
-                       nthreads[i++] = nla_get_u32(attr);
-                       if (i >= nrpools)
-                               break;
-               }
+       nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_THREADS, info->nlhdr,
+                                GENL_HDRLEN, rem) {
+               nthreads[i++] = nla_get_u32(attr);
+               if (i >= nrpools)
+                       break;
        }
 
        if (info->attrs[NFSD_A_SERVER_GRACETIME] ||
@@ -1781,14 +1779,12 @@ int nfsd_nl_version_set_doit(struct sk_buff *skb, struct genl_info *info)
        for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++)
                nfsd_minorversion(nn, i, NFSD_CLEAR);
 
-       nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) {
+       nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_PROTO_VERSION, info->nlhdr,
+                                GENL_HDRLEN, rem) {
                struct nlattr *tb[NFSD_A_VERSION_MAX + 1];
                u32 major, minor = 0;
                bool enabled;
 
-               if (nla_type(attr) != NFSD_A_SERVER_PROTO_VERSION)
-                       continue;
-
                if (nla_parse_nested(tb, NFSD_A_VERSION_MAX, attr,
                                     nfsd_version_nl_policy, info->extack) < 0)
                        continue;
@@ -1939,14 +1935,12 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, struct genl_info *info)
         * Walk the list of server_socks from userland and move any that match
         * back to sv_permsocks
         */
-       nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) {
+       nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_SOCK_ADDR, info->nlhdr,
+                                GENL_HDRLEN, rem) {
                struct nlattr *tb[NFSD_A_SOCK_MAX + 1];
                const char *xcl_name;
                struct sockaddr *sa;
 
-               if (nla_type(attr) != NFSD_A_SERVER_SOCK_ADDR)
-                       continue;
-
                if (nla_parse_nested(tb, NFSD_A_SOCK_MAX, attr,
                                     nfsd_sock_nl_policy, info->extack) < 0)
                        continue;
@@ -2001,15 +1995,13 @@ int nfsd_nl_listener_set_doit(struct sk_buff *skb, struct genl_info *info)
                svc_xprt_destroy_all(serv, net);
 
        /* walk list of addrs again, open any that still don't exist */
-       nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) {
+       nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_SOCK_ADDR, info->nlhdr,
+                                GENL_HDRLEN, rem) {
                struct nlattr *tb[NFSD_A_SOCK_MAX + 1];
                const char *xcl_name;
                struct sockaddr *sa;
                int ret;
 
-               if (nla_type(attr) != NFSD_A_SERVER_SOCK_ADDR)
-                       continue;
-
                if (nla_parse_nested(tb, NFSD_A_SOCK_MAX, attr,
                                     nfsd_sock_nl_policy, info->extack) < 0)
                        continue;
index 90a560dc167a9c78d2dbc2015fa8cf4debca49c2..1a8356ca4b786fbac95dbfbba4409939d7001dff 100644 (file)
@@ -68,6 +68,8 @@
  *   nlmsg_for_each_msg()              loop over all messages
  *   nlmsg_validate()                  validate netlink message incl. attrs
  *   nlmsg_for_each_attr()             loop over all attributes
+ *   nlmsg_for_each_attr_type()                loop over all attributes with the
+ *                                     given type
  *
  * Misc:
  *   nlmsg_report()                    report back to application?
@@ -966,6 +968,18 @@ static inline u32 nlmsg_seq(const struct nlmsghdr *nlh)
        nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \
                          nlmsg_attrlen(nlh, hdrlen), rem)
 
+/**
+ * nlmsg_for_each_attr_type - iterate over a stream of attributes
+ * @pos: loop counter, set to the current attribute
+ * @type: required attribute type for @pos
+ * @nlh: netlink message header
+ * @hdrlen: length of the family specific header
+ * @rem: initialized to len, holds bytes currently remaining in stream
+ */
+#define nlmsg_for_each_attr_type(pos, type, nlh, hdrlen, rem) \
+       nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \
+               if (nla_type(pos) == type)
+
 /**
  * nlmsg_put - Add a new netlink message to an skb
  * @skb: socket buffer to store message in