Commit 42401c42 authored by Carolina Jubran's avatar Carolina Jubran Committed by Jakub Kicinski
Browse files

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: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarCarolina Jubran <cjubran@nvidia.com>
Signed-off-by: default avatarMark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250629142138.361537-2-mbloch@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 97b2409f
Loading
Loading
Loading
Loading
+4 −9
Original line number Diff line number Diff line
@@ -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;
+14 −22
Original line number Diff line number Diff line
@@ -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)
	nlmsg_for_each_attr_type(attr, NFSD_A_SERVER_THREADS, info->nlhdr,
				 GENL_HDRLEN, rem)
		nrpools++;
	}

	mutex_lock(&nfsd_mutex);

@@ -1635,13 +1634,12 @@ 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) {
	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] ||
	    info->attrs[NFSD_A_SERVER_LEASETIME] ||
@@ -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;
+14 −0
Original line number Diff line number Diff line
@@ -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