From: Cosmin Ratiu <[email protected]>
Currently, a devlink rate's parent device is assumed to be the same as
the one where the devlink rate is created.
This patch changes that to allow rate commands to accept an additional
argument that specifies the parent dev. This will allow devlink rate
groups with leafs from other devices.
Example of the new usage with ynl:
Creating a group on pci/0000:08:00.1 with a parent to an already
existing pci/0000:08:00.1/group1:
./tools/net/ynl/pyynl/cli.py --spec \
Documentation/netlink/specs/devlink.yaml --do rate-new --json '{
"bus-name": "pci",
"dev-name": "0000:08:00.1",
"rate-node-name": "group2",
"rate-parent-node-name": "group1",
"parent-dev": {
"bus-name": "pci",
"dev-name": "0000:08:00.1"
}
}'
Setting the parent of leaf node pci/0000:08:00.1/65537 to
pci/0000:08:00.0/group1:
./tools/net/ynl/pyynl/cli.py --spec \
Documentation/netlink/specs/devlink.yaml --do rate-set --json '{
"bus-name": "pci",
"dev-name": "0000:08:00.1",
"port-index": 65537,
"parent-dev": {
"bus-name": "pci",
"dev-name": "0000:08:00.0"
},
"rate-parent-node-name": "group1"
}'
Signed-off-by: Cosmin Ratiu <[email protected]>
Reviewed-by: Carolina Jubran <[email protected]>
Reviewed-by: Jiri Pirko <[email protected]>
Signed-off-by: Tariq Toukan <[email protected]>
---
Documentation/netlink/specs/devlink.yaml | 10 +++---
net/devlink/netlink.c | 40 +++++++++++++++++++++++-
net/devlink/netlink_gen.c | 24 +++++++++-----
net/devlink/netlink_gen.h | 8 +++++
net/devlink/rate.c | 4 ++-
5 files changed, 72 insertions(+), 14 deletions(-)
diff --git a/Documentation/netlink/specs/devlink.yaml
b/Documentation/netlink/specs/devlink.yaml
index 43cc0abf7235..7bf5116fad49 100644
--- a/Documentation/netlink/specs/devlink.yaml
+++ b/Documentation/netlink/specs/devlink.yaml
@@ -2271,8 +2271,8 @@ operations:
dont-validate: [strict]
flags: [admin-perm]
do:
- pre: devlink-nl-pre-doit
- post: devlink-nl-post-doit
+ pre: devlink-nl-pre-doit-parent-dev-optional
+ post: devlink-nl-post-doit-parent-dev-optional
request:
attributes:
- bus-name
@@ -2285,6 +2285,7 @@ operations:
- rate-tx-weight
- rate-parent-node-name
- rate-tc-bws
+ - parent-dev
-
name: rate-new
@@ -2293,8 +2294,8 @@ operations:
dont-validate: [strict]
flags: [admin-perm]
do:
- pre: devlink-nl-pre-doit
- post: devlink-nl-post-doit
+ pre: devlink-nl-pre-doit-parent-dev-optional
+ post: devlink-nl-post-doit-parent-dev-optional
request:
attributes:
- bus-name
@@ -2307,6 +2308,7 @@ operations:
- rate-tx-weight
- rate-parent-node-name
- rate-tc-bws
+ - parent-dev
-
name: rate-del
diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c
index 21a34e4d2a49..38a3e46c0be3 100644
--- a/net/devlink/netlink.c
+++ b/net/devlink/netlink.c
@@ -243,7 +243,29 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr
**attrs,
struct devlink *
devlink_get_parent_from_attrs_lock(struct net *net, struct nlattr **attrs)
{
- return ERR_PTR(-EOPNOTSUPP);
+ unsigned int maxtype = ARRAY_SIZE(devlink_dl_parent_dev_nl_policy);
+ struct devlink *devlink;
+ struct nlattr **tb;
+ int err;
+
+ if (!attrs[DEVLINK_ATTR_PARENT_DEV])
+ return ERR_PTR(-EINVAL);
+
+ tb = kcalloc(maxtype + 1, sizeof(*tb), GFP_KERNEL);
+ if (!tb)
+ return ERR_PTR(-ENOMEM);
+
+ err = nla_parse_nested(tb, maxtype, attrs[DEVLINK_ATTR_PARENT_DEV],
+ devlink_dl_parent_dev_nl_policy, NULL);
+ if (err)
+ goto out;
+
+ devlink = devlink_get_from_attrs_lock(net, tb, false);
+ kfree(tb);
+ return devlink;
+out:
+ kfree(tb);
+ return ERR_PTR(err);
}
static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info,
@@ -322,6 +344,14 @@ int devlink_nl_pre_doit_port_optional(const struct
genl_split_ops *ops,
return __devlink_nl_pre_doit(skb, info,
DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT);
}
+int devlink_nl_pre_doit_parent_dev_optional(const struct genl_split_ops *ops,
+ struct sk_buff *skb,
+ struct genl_info *info)
+{
+ return __devlink_nl_pre_doit(skb, info,
+ DEVLINK_NL_FLAG_OPTIONAL_PARENT_DEV);
+}
+
static void __devlink_nl_post_doit(struct sk_buff *skb, struct genl_info *info,
u8 flags)
{
@@ -348,6 +378,14 @@ devlink_nl_post_doit_dev_lock(const struct genl_split_ops
*ops,
__devlink_nl_post_doit(skb, info, DEVLINK_NL_FLAG_NEED_DEV_LOCK);
}
+void
+devlink_nl_post_doit_parent_dev_optional(const struct genl_split_ops *ops,
+ struct sk_buff *skb,
+ struct genl_info *info)
+{
+ __devlink_nl_post_doit(skb, info, DEVLINK_NL_FLAG_OPTIONAL_PARENT_DEV);
+}
+
static int devlink_nl_inst_single_dumpit(struct sk_buff *msg,
struct netlink_callback *cb, int flags,
devlink_nl_dump_one_func_t *dump_one,
diff --git a/net/devlink/netlink_gen.c b/net/devlink/netlink_gen.c
index eb35e80e01d1..f47a965972a0 100644
--- a/net/devlink/netlink_gen.c
+++ b/net/devlink/netlink_gen.c
@@ -44,6 +44,12 @@ devlink_attr_param_type_validate(const struct nlattr *attr,
}
/* Common nested types */
+const struct nla_policy devlink_dl_parent_dev_nl_policy[DEVLINK_ATTR_INDEX +
1] = {
+ [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
+ [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+ [DEVLINK_ATTR_INDEX] = { .type = NLA_UINT, },
+};
+
const struct nla_policy
devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_CAPS + 1] = {
[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NLA_BINARY, },
[DEVLINK_PORT_FN_ATTR_STATE] = NLA_POLICY_MAX(NLA_U8, 1),
@@ -597,7 +603,7 @@ static const struct nla_policy
devlink_rate_get_dump_nl_policy[DEVLINK_ATTR_INDE
};
/* DEVLINK_CMD_RATE_SET - do */
-static const struct nla_policy devlink_rate_set_nl_policy[DEVLINK_ATTR_INDEX +
1] = {
+static const struct nla_policy
devlink_rate_set_nl_policy[DEVLINK_ATTR_PARENT_DEV + 1] = {
[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT,
&devlink_attr_index_range),
@@ -608,10 +614,11 @@ static const struct nla_policy
devlink_rate_set_nl_policy[DEVLINK_ATTR_INDEX + 1
[DEVLINK_ATTR_RATE_TX_WEIGHT] = { .type = NLA_U32, },
[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_RATE_TC_BWS] =
NLA_POLICY_NESTED(devlink_dl_rate_tc_bws_nl_policy),
+ [DEVLINK_ATTR_PARENT_DEV] =
NLA_POLICY_NESTED(devlink_dl_parent_dev_nl_policy),
};
/* DEVLINK_CMD_RATE_NEW - do */
-static const struct nla_policy devlink_rate_new_nl_policy[DEVLINK_ATTR_INDEX +
1] = {
+static const struct nla_policy
devlink_rate_new_nl_policy[DEVLINK_ATTR_PARENT_DEV + 1] = {
[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_INDEX] = NLA_POLICY_FULL_RANGE(NLA_UINT,
&devlink_attr_index_range),
@@ -622,6 +629,7 @@ static const struct nla_policy
devlink_rate_new_nl_policy[DEVLINK_ATTR_INDEX + 1
[DEVLINK_ATTR_RATE_TX_WEIGHT] = { .type = NLA_U32, },
[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_RATE_TC_BWS] =
NLA_POLICY_NESTED(devlink_dl_rate_tc_bws_nl_policy),
+ [DEVLINK_ATTR_PARENT_DEV] =
NLA_POLICY_NESTED(devlink_dl_parent_dev_nl_policy),
};
/* DEVLINK_CMD_RATE_DEL - do */
@@ -1272,21 +1280,21 @@ const struct genl_split_ops devlink_nl_ops[74] = {
{
.cmd = DEVLINK_CMD_RATE_SET,
.validate = GENL_DONT_VALIDATE_STRICT,
- .pre_doit = devlink_nl_pre_doit,
+ .pre_doit = devlink_nl_pre_doit_parent_dev_optional,
.doit = devlink_nl_rate_set_doit,
- .post_doit = devlink_nl_post_doit,
+ .post_doit = devlink_nl_post_doit_parent_dev_optional,
.policy = devlink_rate_set_nl_policy,
- .maxattr = DEVLINK_ATTR_INDEX,
+ .maxattr = DEVLINK_ATTR_PARENT_DEV,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
.cmd = DEVLINK_CMD_RATE_NEW,
.validate = GENL_DONT_VALIDATE_STRICT,
- .pre_doit = devlink_nl_pre_doit,
+ .pre_doit = devlink_nl_pre_doit_parent_dev_optional,
.doit = devlink_nl_rate_new_doit,
- .post_doit = devlink_nl_post_doit,
+ .post_doit = devlink_nl_post_doit_parent_dev_optional,
.policy = devlink_rate_new_nl_policy,
- .maxattr = DEVLINK_ATTR_INDEX,
+ .maxattr = DEVLINK_ATTR_PARENT_DEV,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
diff --git a/net/devlink/netlink_gen.h b/net/devlink/netlink_gen.h
index 2817d53a0eba..e16615aaa03f 100644
--- a/net/devlink/netlink_gen.h
+++ b/net/devlink/netlink_gen.h
@@ -13,6 +13,7 @@
#include <uapi/linux/devlink.h>
/* Common nested types */
+extern const struct nla_policy
devlink_dl_parent_dev_nl_policy[DEVLINK_ATTR_INDEX + 1];
extern const struct nla_policy
devlink_dl_port_function_nl_policy[DEVLINK_PORT_FN_ATTR_CAPS + 1];
extern const struct nla_policy
devlink_dl_rate_tc_bws_nl_policy[DEVLINK_RATE_TC_ATTR_BW + 1];
extern const struct nla_policy
devlink_dl_selftest_id_nl_policy[DEVLINK_ATTR_SELFTEST_ID_FLASH + 1];
@@ -29,12 +30,19 @@ int devlink_nl_pre_doit_dev_lock(const struct
genl_split_ops *ops,
int devlink_nl_pre_doit_port_optional(const struct genl_split_ops *ops,
struct sk_buff *skb,
struct genl_info *info);
+int devlink_nl_pre_doit_parent_dev_optional(const struct genl_split_ops *ops,
+ struct sk_buff *skb,
+ struct genl_info *info);
void
devlink_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
struct genl_info *info);
void
devlink_nl_post_doit_dev_lock(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info);
+void
+devlink_nl_post_doit_parent_dev_optional(const struct genl_split_ops *ops,
+ struct sk_buff *skb,
+ struct genl_info *info);
int devlink_nl_get_doit(struct sk_buff *skb, struct genl_info *info);
int devlink_nl_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
diff --git a/net/devlink/rate.c b/net/devlink/rate.c
index 9ebbc72130c6..1949746fab29 100644
--- a/net/devlink/rate.c
+++ b/net/devlink/rate.c
@@ -655,9 +655,11 @@ int devlink_nl_rate_set_doit(struct sk_buff *skb, struct
genl_info *info)
int devlink_nl_rate_new_doit(struct sk_buff *skb, struct genl_info *info)
{
- struct devlink *rate_devlink, *devlink = devlink_nl_ctx(info)->devlink;
+ struct devlink_nl_ctx *ctx = devlink_nl_ctx(info);
+ struct devlink *devlink = ctx->devlink;
struct devlink_rate *rate_node;
const struct devlink_ops *ops;
+ struct devlink *rate_devlink;
int err;
ops = devlink->ops;
--
2.44.0