netlink: introduce type-checking attribute iteration
There are, especially with multi-attr arrays, many cases of needing to iterate all attributes of a specific type in a netlink message or a nested attribute. Add specific macros to support that case. Also convert many instances using this spatch: @@ iterator nla_for_each_attr; iterator name nla_for_each_attr_type; identifier nla; expression head, len, rem; expression ATTR; type T; identifier x; @@ -nla_for_each_attr(nla, head, len, rem) +nla_for_each_attr_type(nla, ATTR, head, len, rem) { <... T x; ...> -if (nla_type(nla) == ATTR) { ... -} } @@ identifier nla; iterator nla_for_each_nested; iterator name nla_for_each_nested_type; expression attr, rem; expression ATTR; type T; identifier x; @@ -nla_for_each_nested(nla, attr, rem) +nla_for_each_nested_type(nla, ATTR, attr, rem) { <... T x; ...> -if (nla_type(nla) == ATTR) { ... -} } @@ iterator nla_for_each_attr; iterator name nla_for_each_attr_type; identifier nla; expression head, len, rem; expression ATTR; type T; identifier x; @@ -nla_for_each_attr(nla, head, len, rem) +nla_for_each_attr_type(nla, ATTR, head, len, rem) { <... T x; ...> -if (nla_type(nla) != ATTR) continue; ... } @@ identifier nla; iterator nla_for_each_nested; iterator name nla_for_each_nested_type; expression attr, rem; expression ATTR; type T; identifier x; @@ -nla_for_each_nested(nla, attr, rem) +nla_for_each_nested_type(nla, ATTR, attr, rem) { <... T x; ...> -if (nla_type(nla) != ATTR) continue; ... } Although I had to undo one bad change this made, and I also adjusted some other code for whitespace and to use direct variable initialization now. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Link: https://lore.kernel.org/r/20240328203144.b5a6c895fb80.I1869b44767379f204998ff44dd239803f39c23e0@changeid Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
9494dc0b08
commit
e8058a49e6
@ -14581,12 +14581,9 @@ static int bnxt_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
|
|||||||
if (!br_spec)
|
if (!br_spec)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
nla_for_each_nested(attr, br_spec, rem) {
|
nla_for_each_nested_type(attr, IFLA_BRIDGE_MODE, br_spec, rem) {
|
||||||
u16 mode;
|
u16 mode;
|
||||||
|
|
||||||
if (nla_type(attr) != IFLA_BRIDGE_MODE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mode = nla_get_u16(attr);
|
mode = nla_get_u16(attr);
|
||||||
if (mode == bp->br_mode)
|
if (mode == bp->br_mode)
|
||||||
break;
|
break;
|
||||||
|
@ -4982,10 +4982,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
|
|||||||
if (!br_spec)
|
if (!br_spec)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
nla_for_each_nested(attr, br_spec, rem) {
|
nla_for_each_nested_type(attr, IFLA_BRIDGE_MODE, br_spec, rem) {
|
||||||
if (nla_type(attr) != IFLA_BRIDGE_MODE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mode = nla_get_u16(attr);
|
mode = nla_get_u16(attr);
|
||||||
if (BE3_chip(adapter) && mode == BRIDGE_MODE_VEPA)
|
if (BE3_chip(adapter) && mode == BRIDGE_MODE_VEPA)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
@ -13108,13 +13108,9 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
|
|||||||
if (!br_spec)
|
if (!br_spec)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
nla_for_each_nested(attr, br_spec, rem) {
|
nla_for_each_nested_type(attr, IFLA_BRIDGE_MODE, br_spec, rem) {
|
||||||
__u16 mode;
|
__u16 mode = nla_get_u16(attr);
|
||||||
|
|
||||||
if (nla_type(attr) != IFLA_BRIDGE_MODE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mode = nla_get_u16(attr);
|
|
||||||
if ((mode != BRIDGE_MODE_VEPA) &&
|
if ((mode != BRIDGE_MODE_VEPA) &&
|
||||||
(mode != BRIDGE_MODE_VEB))
|
(mode != BRIDGE_MODE_VEB))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -7993,12 +7993,9 @@ ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
|
|||||||
if (!br_spec)
|
if (!br_spec)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
nla_for_each_nested(attr, br_spec, rem) {
|
nla_for_each_nested_type(attr, IFLA_BRIDGE_MODE, br_spec, rem) {
|
||||||
__u16 mode;
|
__u16 mode = nla_get_u16(attr);
|
||||||
|
|
||||||
if (nla_type(attr) != IFLA_BRIDGE_MODE)
|
|
||||||
continue;
|
|
||||||
mode = nla_get_u16(attr);
|
|
||||||
if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB)
|
if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
/* Continue if bridge mode is not being flipped */
|
/* Continue if bridge mode is not being flipped */
|
||||||
|
@ -10061,15 +10061,10 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
|
|||||||
if (!br_spec)
|
if (!br_spec)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
nla_for_each_nested(attr, br_spec, rem) {
|
nla_for_each_nested_type(attr, IFLA_BRIDGE_MODE, br_spec, rem) {
|
||||||
int status;
|
__u16 mode = nla_get_u16(attr);
|
||||||
__u16 mode;
|
int status = ixgbe_configure_bridge_mode(adapter, mode);
|
||||||
|
|
||||||
if (nla_type(attr) != IFLA_BRIDGE_MODE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mode = nla_get_u16(attr);
|
|
||||||
status = ixgbe_configure_bridge_mode(adapter, mode);
|
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -4950,10 +4950,7 @@ static int mlx5e_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
|
|||||||
if (!br_spec)
|
if (!br_spec)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
nla_for_each_nested(attr, br_spec, rem) {
|
nla_for_each_nested_type(attr, IFLA_BRIDGE_MODE, br_spec, rem) {
|
||||||
if (nla_type(attr) != IFLA_BRIDGE_MODE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mode = nla_get_u16(attr);
|
mode = nla_get_u16(attr);
|
||||||
if (mode > BRIDGE_MODE_VEPA)
|
if (mode > BRIDGE_MODE_VEPA)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -2289,10 +2289,7 @@ static int nfp_net_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
|
|||||||
if (!br_spec)
|
if (!br_spec)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
nla_for_each_nested(attr, br_spec, rem) {
|
nla_for_each_nested_type(attr, IFLA_BRIDGE_MODE, br_spec, rem) {
|
||||||
if (nla_type(attr) != IFLA_BRIDGE_MODE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
new_ctrl = nn->dp.ctrl;
|
new_ctrl = nn->dp.ctrl;
|
||||||
mode = nla_get_u16(attr);
|
mode = nla_get_u16(attr);
|
||||||
if (mode == BRIDGE_MODE_VEPA)
|
if (mode == BRIDGE_MODE_VEPA)
|
||||||
|
@ -157,7 +157,11 @@
|
|||||||
* nla_parse() parse and validate stream of attrs
|
* nla_parse() parse and validate stream of attrs
|
||||||
* nla_parse_nested() parse nested attributes
|
* nla_parse_nested() parse nested attributes
|
||||||
* nla_for_each_attr() loop over all attributes
|
* nla_for_each_attr() loop over all attributes
|
||||||
|
* nla_for_each_attr_type() loop over all attributes with the
|
||||||
|
* given type
|
||||||
* nla_for_each_nested() loop over the nested attributes
|
* nla_for_each_nested() loop over the nested attributes
|
||||||
|
* nla_for_each_nested_type() loop over the nested attributes with
|
||||||
|
* the given type
|
||||||
*=========================================================================
|
*=========================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -2070,6 +2074,18 @@ static inline int nla_total_size_64bit(int payload)
|
|||||||
nla_ok(pos, rem); \
|
nla_ok(pos, rem); \
|
||||||
pos = nla_next(pos, &(rem)))
|
pos = nla_next(pos, &(rem)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nla_for_each_attr_type - iterate over a stream of attributes
|
||||||
|
* @pos: loop counter, set to current attribute
|
||||||
|
* @type: required attribute type for @pos
|
||||||
|
* @head: head of attribute stream
|
||||||
|
* @len: length of attribute stream
|
||||||
|
* @rem: initialized to len, holds bytes currently remaining in stream
|
||||||
|
*/
|
||||||
|
#define nla_for_each_attr_type(pos, type, head, len, rem) \
|
||||||
|
nla_for_each_attr(pos, head, len, rem) \
|
||||||
|
if (nla_type(pos) == type)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nla_for_each_nested - iterate over nested attributes
|
* nla_for_each_nested - iterate over nested attributes
|
||||||
* @pos: loop counter, set to current attribute
|
* @pos: loop counter, set to current attribute
|
||||||
@ -2079,6 +2095,17 @@ static inline int nla_total_size_64bit(int payload)
|
|||||||
#define nla_for_each_nested(pos, nla, rem) \
|
#define nla_for_each_nested(pos, nla, rem) \
|
||||||
nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem)
|
nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nla_for_each_nested_type - iterate over nested attributes
|
||||||
|
* @pos: loop counter, set to current attribute
|
||||||
|
* @type: required attribute type for @pos
|
||||||
|
* @nla: attribute containing the nested attributes
|
||||||
|
* @rem: initialized to len, holds bytes currently remaining in stream
|
||||||
|
*/
|
||||||
|
#define nla_for_each_nested_type(pos, type, nla, rem) \
|
||||||
|
nla_for_each_nested(pos, nla, rem) \
|
||||||
|
if (nla_type(pos) == type)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nla_is_last - Test if attribute is last in stream
|
* nla_is_last - Test if attribute is last in stream
|
||||||
* @nla: attribute to test
|
* @nla: attribute to test
|
||||||
|
@ -117,17 +117,15 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (data[IFLA_VLAN_INGRESS_QOS]) {
|
if (data[IFLA_VLAN_INGRESS_QOS]) {
|
||||||
nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
|
nla_for_each_nested_type(attr, IFLA_VLAN_QOS_MAPPING,
|
||||||
if (nla_type(attr) != IFLA_VLAN_QOS_MAPPING)
|
data[IFLA_VLAN_INGRESS_QOS], rem) {
|
||||||
continue;
|
|
||||||
m = nla_data(attr);
|
m = nla_data(attr);
|
||||||
vlan_dev_set_ingress_priority(dev, m->to, m->from);
|
vlan_dev_set_ingress_priority(dev, m->to, m->from);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data[IFLA_VLAN_EGRESS_QOS]) {
|
if (data[IFLA_VLAN_EGRESS_QOS]) {
|
||||||
nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
|
nla_for_each_nested_type(attr, IFLA_VLAN_QOS_MAPPING,
|
||||||
if (nla_type(attr) != IFLA_VLAN_QOS_MAPPING)
|
data[IFLA_VLAN_EGRESS_QOS], rem) {
|
||||||
continue;
|
|
||||||
m = nla_data(attr);
|
m = nla_data(attr);
|
||||||
err = vlan_dev_set_egress_priority(dev, m->from, m->to);
|
err = vlan_dev_set_egress_priority(dev, m->from, m->to);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -496,27 +496,22 @@ bpf_sk_storage_diag_alloc(const struct nlattr *nla_stgs)
|
|||||||
if (!bpf_capable())
|
if (!bpf_capable())
|
||||||
return ERR_PTR(-EPERM);
|
return ERR_PTR(-EPERM);
|
||||||
|
|
||||||
nla_for_each_nested(nla, nla_stgs, rem) {
|
nla_for_each_nested_type(nla, SK_DIAG_BPF_STORAGE_REQ_MAP_FD,
|
||||||
if (nla_type(nla) == SK_DIAG_BPF_STORAGE_REQ_MAP_FD) {
|
nla_stgs, rem) {
|
||||||
if (nla_len(nla) != sizeof(u32))
|
if (nla_len(nla) != sizeof(u32))
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
nr_maps++;
|
nr_maps++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
diag = kzalloc(struct_size(diag, maps, nr_maps), GFP_KERNEL);
|
diag = kzalloc(struct_size(diag, maps, nr_maps), GFP_KERNEL);
|
||||||
if (!diag)
|
if (!diag)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
nla_for_each_nested(nla, nla_stgs, rem) {
|
nla_for_each_nested_type(nla, SK_DIAG_BPF_STORAGE_REQ_MAP_FD,
|
||||||
struct bpf_map *map;
|
nla_stgs, rem) {
|
||||||
int map_fd;
|
int map_fd = nla_get_u32(nla);
|
||||||
|
struct bpf_map *map = bpf_map_get(map_fd);
|
||||||
|
|
||||||
if (nla_type(nla) != SK_DIAG_BPF_STORAGE_REQ_MAP_FD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
map_fd = nla_get_u32(nla);
|
|
||||||
map = bpf_map_get(map_fd);
|
|
||||||
if (IS_ERR(map)) {
|
if (IS_ERR(map)) {
|
||||||
err = PTR_ERR(map);
|
err = PTR_ERR(map);
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
@ -5245,15 +5245,14 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||||||
|
|
||||||
br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
|
br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
|
||||||
if (br_spec) {
|
if (br_spec) {
|
||||||
nla_for_each_nested(attr, br_spec, rem) {
|
nla_for_each_nested_type(attr, IFLA_BRIDGE_FLAGS, br_spec,
|
||||||
if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
|
rem) {
|
||||||
if (nla_len(attr) < sizeof(flags))
|
if (nla_len(attr) < sizeof(flags))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
have_flags = true;
|
have_flags = true;
|
||||||
flags = nla_get_u16(attr);
|
flags = nla_get_u16(attr);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1202,17 +1202,13 @@ static void __devlink_compat_running_version(struct devlink *devlink,
|
|||||||
if (err)
|
if (err)
|
||||||
goto free_msg;
|
goto free_msg;
|
||||||
|
|
||||||
nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
|
nla_for_each_attr_type(nlattr, DEVLINK_ATTR_INFO_VERSION_RUNNING,
|
||||||
|
(void *)msg->data, msg->len, rem) {
|
||||||
const struct nlattr *kv;
|
const struct nlattr *kv;
|
||||||
int rem_kv;
|
int rem_kv;
|
||||||
|
|
||||||
if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
|
nla_for_each_nested_type(kv, DEVLINK_ATTR_INFO_VERSION_VALUE,
|
||||||
continue;
|
nlattr, rem_kv) {
|
||||||
|
|
||||||
nla_for_each_nested(kv, nlattr, rem_kv) {
|
|
||||||
if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
strlcat(buf, nla_data(kv), len);
|
strlcat(buf, nla_data(kv), len);
|
||||||
strlcat(buf, " ", len);
|
strlcat(buf, " ", len);
|
||||||
}
|
}
|
||||||
|
@ -215,10 +215,8 @@ static int mqprio_parse_tc_entries(struct Qdisc *sch, struct nlattr *nlattr_opt,
|
|||||||
for (tc = 0; tc < TC_QOPT_MAX_QUEUE; tc++)
|
for (tc = 0; tc < TC_QOPT_MAX_QUEUE; tc++)
|
||||||
fp[tc] = priv->fp[tc];
|
fp[tc] = priv->fp[tc];
|
||||||
|
|
||||||
nla_for_each_attr(n, nlattr_opt, nlattr_opt_len, rem) {
|
nla_for_each_attr_type(n, TCA_MQPRIO_TC_ENTRY, nlattr_opt,
|
||||||
if (nla_type(n) != TCA_MQPRIO_TC_ENTRY)
|
nlattr_opt_len, rem) {
|
||||||
continue;
|
|
||||||
|
|
||||||
err = mqprio_parse_tc_entry(fp, n, &seen_tcs, extack);
|
err = mqprio_parse_tc_entry(fp, n, &seen_tcs, extack);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1752,10 +1752,7 @@ static int taprio_parse_tc_entries(struct Qdisc *sch,
|
|||||||
fp[tc] = q->fp[tc];
|
fp[tc] = q->fp[tc];
|
||||||
}
|
}
|
||||||
|
|
||||||
nla_for_each_nested(n, opt, rem) {
|
nla_for_each_nested_type(n, TCA_TAPRIO_ATTR_TC_ENTRY, opt, rem) {
|
||||||
if (nla_type(n) != TCA_TAPRIO_ATTR_TC_ENTRY)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
err = taprio_parse_tc_entry(sch, n, max_sdu, fp, &seen_tcs,
|
err = taprio_parse_tc_entry(sch, n, max_sdu, fp, &seen_tcs,
|
||||||
extack);
|
extack);
|
||||||
if (err)
|
if (err)
|
||||||
|
Loading…
Reference in New Issue
Block a user