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>
This commit is contained in:
parent
97b2409f28
commit
42401c4238
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue