Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netlink: introduce type-checking attribute iteration for nlmsg

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>

authored by

Carolina Jubran and committed by
Jakub Kicinski
42401c42 97b2409f

+32 -31
+4 -9
drivers/net/vxlan/vxlan_vnifilter.c
··· 971 971 if (!(vxlan->cfg.flags & VXLAN_F_VNIFILTER)) 972 972 return -EOPNOTSUPP; 973 973 974 - nlmsg_for_each_attr(attr, nlh, sizeof(*tmsg), rem) { 975 - switch (nla_type(attr)) { 976 - case VXLAN_VNIFILTER_ENTRY: 977 - err = vxlan_process_vni_filter(vxlan, attr, 978 - nlh->nlmsg_type, extack); 979 - break; 980 - default: 981 - continue; 982 - } 974 + nlmsg_for_each_attr_type(attr, VXLAN_VNIFILTER_ENTRY, nlh, 975 + sizeof(*tmsg), rem) { 976 + err = vxlan_process_vni_filter(vxlan, attr, nlh->nlmsg_type, 977 + extack); 983 978 vnis++; 984 979 if (err) 985 980 break;
+14 -22
fs/nfsd/nfsctl.c
··· 1621 1621 return -EINVAL; 1622 1622 1623 1623 /* count number of SERVER_THREADS values */ 1624 - nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 1625 - if (nla_type(attr) == NFSD_A_SERVER_THREADS) 1626 - nrpools++; 1627 - } 1624 + nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_THREADS, info->nlhdr, 1625 + GENL_HDRLEN, rem) 1626 + nrpools++; 1628 1627 1629 1628 mutex_lock(&nfsd_mutex); 1630 1629 ··· 1634 1635 } 1635 1636 1636 1637 i = 0; 1637 - nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 1638 - if (nla_type(attr) == NFSD_A_SERVER_THREADS) { 1639 - nthreads[i++] = nla_get_u32(attr); 1640 - if (i >= nrpools) 1641 - break; 1642 - } 1638 + nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_THREADS, info->nlhdr, 1639 + GENL_HDRLEN, rem) { 1640 + nthreads[i++] = nla_get_u32(attr); 1641 + if (i >= nrpools) 1642 + break; 1643 1643 } 1644 1644 1645 1645 if (info->attrs[NFSD_A_SERVER_GRACETIME] || ··· 1779 1781 for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) 1780 1782 nfsd_minorversion(nn, i, NFSD_CLEAR); 1781 1783 1782 - nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 1784 + nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_PROTO_VERSION, info->nlhdr, 1785 + GENL_HDRLEN, rem) { 1783 1786 struct nlattr *tb[NFSD_A_VERSION_MAX + 1]; 1784 1787 u32 major, minor = 0; 1785 1788 bool enabled; 1786 - 1787 - if (nla_type(attr) != NFSD_A_SERVER_PROTO_VERSION) 1788 - continue; 1789 1789 1790 1790 if (nla_parse_nested(tb, NFSD_A_VERSION_MAX, attr, 1791 1791 nfsd_version_nl_policy, info->extack) < 0) ··· 1935 1939 * Walk the list of server_socks from userland and move any that match 1936 1940 * back to sv_permsocks 1937 1941 */ 1938 - nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 1942 + nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_SOCK_ADDR, info->nlhdr, 1943 + GENL_HDRLEN, rem) { 1939 1944 struct nlattr *tb[NFSD_A_SOCK_MAX + 1]; 1940 1945 const char *xcl_name; 1941 1946 struct sockaddr *sa; 1942 - 1943 - if (nla_type(attr) != NFSD_A_SERVER_SOCK_ADDR) 1944 - continue; 1945 1947 1946 1948 if (nla_parse_nested(tb, NFSD_A_SOCK_MAX, attr, 1947 1949 nfsd_sock_nl_policy, info->extack) < 0) ··· 1995 2001 svc_xprt_destroy_all(serv, net); 1996 2002 1997 2003 /* walk list of addrs again, open any that still don't exist */ 1998 - nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 2004 + nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_SOCK_ADDR, info->nlhdr, 2005 + GENL_HDRLEN, rem) { 1999 2006 struct nlattr *tb[NFSD_A_SOCK_MAX + 1]; 2000 2007 const char *xcl_name; 2001 2008 struct sockaddr *sa; 2002 2009 int ret; 2003 - 2004 - if (nla_type(attr) != NFSD_A_SERVER_SOCK_ADDR) 2005 - continue; 2006 2010 2007 2011 if (nla_parse_nested(tb, NFSD_A_SOCK_MAX, attr, 2008 2012 nfsd_sock_nl_policy, info->extack) < 0)
+14
include/net/netlink.h
··· 68 68 * nlmsg_for_each_msg() loop over all messages 69 69 * nlmsg_validate() validate netlink message incl. attrs 70 70 * nlmsg_for_each_attr() loop over all attributes 71 + * nlmsg_for_each_attr_type() loop over all attributes with the 72 + * given type 71 73 * 72 74 * Misc: 73 75 * nlmsg_report() report back to application? ··· 967 965 #define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \ 968 966 nla_for_each_attr(pos, nlmsg_attrdata(nlh, hdrlen), \ 969 967 nlmsg_attrlen(nlh, hdrlen), rem) 968 + 969 + /** 970 + * nlmsg_for_each_attr_type - iterate over a stream of attributes 971 + * @pos: loop counter, set to the current attribute 972 + * @type: required attribute type for @pos 973 + * @nlh: netlink message header 974 + * @hdrlen: length of the family specific header 975 + * @rem: initialized to len, holds bytes currently remaining in stream 976 + */ 977 + #define nlmsg_for_each_attr_type(pos, type, nlh, hdrlen, rem) \ 978 + nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \ 979 + if (nla_type(pos) == type) 970 980 971 981 /** 972 982 * nlmsg_put - Add a new netlink message to an skb