netlink: spec: add shaper introspection support

Allow the user-space to fine-grain query the shaping features
supported by the NIC on each domain.

Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Link: https://patch.msgid.link/3ddd10e450e3fe7d4b944c0d0b886d4483529ee6.1728460186.git.pabeni@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Paolo Abeni 2024-10-09 10:09:54 +02:00 committed by Jakub Kicinski
parent ff7d4deb1f
commit 14bba9285a
5 changed files with 176 additions and 0 deletions

View File

@ -26,6 +26,11 @@ doc: |
The user can query the running configuration via the @get operation.
Different devices can provide different feature sets, e.g. with no
support for complex scheduling hierarchy, or for some shaping
parameters. The user can introspect the HW capabilities via the
@cap-get operation.
definitions:
-
type: enum
@ -148,6 +153,53 @@ attribute-sets:
name: priority
-
name: weight
-
name: caps
attributes:
-
name: ifindex
type: u32
doc: Interface index queried for shapers capabilities.
-
name: scope
type: u32
enum: scope
doc: The scope to which the queried capabilities apply.
-
name: support-metric-bps
type: flag
doc: The device accepts 'bps' metric for bw-min, bw-max and burst.
-
name: support-metric-pps
type: flag
doc: The device accepts 'pps' metric for bw-min, bw-max and burst.
-
name: support-nesting
type: flag
doc: |
The device supports nesting shaper belonging to this scope
below 'node' scoped shapers. Only 'queue' and 'node'
scope can have flag 'support-nesting'.
-
name: support-bw-min
type: flag
doc: The device supports a minimum guaranteed B/W.
-
name: support-bw-max
type: flag
doc: The device supports maximum B/W shaping.
-
name: support-burst
type: flag
doc: The device supports a maximum burst size.
-
name: support-priority
type: flag
doc: The device supports priority scheduling.
-
name: support-weight
type: flag
doc: The device supports weighted round robin scheduling.
operations:
list:
@ -272,3 +324,39 @@ operations:
- leaves
reply:
attributes: *ns-binding
-
name: cap-get
doc: |
Get the shaper capabilities supported by the given device
for the specified scope.
attribute-set: caps
do:
pre: net-shaper-nl-cap-pre-doit
post: net-shaper-nl-cap-post-doit
request:
attributes:
- ifindex
- scope
reply:
attributes: &cap-attrs
- ifindex
- scope
- support-metric-bps
- support-metric-pps
- support-nesting
- support-bw-min
- support-bw-max
- support-burst
- support-priority
- support-weight
dump:
pre: net-shaper-nl-cap-pre-dumpit
post: net-shaper-nl-cap-post-dumpit
request:
attributes:
- ifindex
reply:
attributes: *cap-attrs

View File

@ -65,11 +65,28 @@ enum {
NET_SHAPER_A_HANDLE_MAX = (__NET_SHAPER_A_HANDLE_MAX - 1)
};
enum {
NET_SHAPER_A_CAPS_IFINDEX = 1,
NET_SHAPER_A_CAPS_SCOPE,
NET_SHAPER_A_CAPS_SUPPORT_METRIC_BPS,
NET_SHAPER_A_CAPS_SUPPORT_METRIC_PPS,
NET_SHAPER_A_CAPS_SUPPORT_NESTING,
NET_SHAPER_A_CAPS_SUPPORT_BW_MIN,
NET_SHAPER_A_CAPS_SUPPORT_BW_MAX,
NET_SHAPER_A_CAPS_SUPPORT_BURST,
NET_SHAPER_A_CAPS_SUPPORT_PRIORITY,
NET_SHAPER_A_CAPS_SUPPORT_WEIGHT,
__NET_SHAPER_A_CAPS_MAX,
NET_SHAPER_A_CAPS_MAX = (__NET_SHAPER_A_CAPS_MAX - 1)
};
enum {
NET_SHAPER_CMD_GET = 1,
NET_SHAPER_CMD_SET,
NET_SHAPER_CMD_DELETE,
NET_SHAPER_CMD_GROUP,
NET_SHAPER_CMD_CAP_GET,
__NET_SHAPER_CMD_MAX,
NET_SHAPER_CMD_MAX = (__NET_SHAPER_CMD_MAX - 1)

View File

@ -598,6 +598,27 @@ int net_shaper_nl_post_dumpit(struct netlink_callback *cb)
return 0;
}
int net_shaper_nl_cap_pre_doit(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info)
{
return -EOPNOTSUPP;
}
void net_shaper_nl_cap_post_doit(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info)
{
}
int net_shaper_nl_cap_pre_dumpit(struct netlink_callback *cb)
{
return -EOPNOTSUPP;
}
int net_shaper_nl_cap_post_dumpit(struct netlink_callback *cb)
{
return -EOPNOTSUPP;
}
int net_shaper_nl_get_doit(struct sk_buff *skb, struct genl_info *info)
{
struct net_shaper_binding *binding;
@ -1126,6 +1147,17 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info)
goto free_leaves;
}
int net_shaper_nl_cap_get_doit(struct sk_buff *skb, struct genl_info *info)
{
return 0;
}
int net_shaper_nl_cap_get_dumpit(struct sk_buff *skb,
struct netlink_callback *cb)
{
return 0;
}
static void net_shaper_flush(struct net_shaper_binding *binding)
{
struct net_shaper_hierarchy *hierarchy = net_shaper_hierarchy(binding);

View File

@ -65,6 +65,17 @@ static const struct nla_policy net_shaper_group_nl_policy[NET_SHAPER_A_LEAVES +
[NET_SHAPER_A_LEAVES] = NLA_POLICY_NESTED(net_shaper_leaf_info_nl_policy),
};
/* NET_SHAPER_CMD_CAP_GET - do */
static const struct nla_policy net_shaper_cap_get_do_nl_policy[NET_SHAPER_A_CAPS_SCOPE + 1] = {
[NET_SHAPER_A_CAPS_IFINDEX] = { .type = NLA_U32, },
[NET_SHAPER_A_CAPS_SCOPE] = NLA_POLICY_MAX(NLA_U32, 3),
};
/* NET_SHAPER_CMD_CAP_GET - dump */
static const struct nla_policy net_shaper_cap_get_dump_nl_policy[NET_SHAPER_A_CAPS_IFINDEX + 1] = {
[NET_SHAPER_A_CAPS_IFINDEX] = { .type = NLA_U32, },
};
/* Ops table for net_shaper */
static const struct genl_split_ops net_shaper_nl_ops[] = {
{
@ -112,6 +123,24 @@ static const struct genl_split_ops net_shaper_nl_ops[] = {
.maxattr = NET_SHAPER_A_LEAVES,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{
.cmd = NET_SHAPER_CMD_CAP_GET,
.pre_doit = net_shaper_nl_cap_pre_doit,
.doit = net_shaper_nl_cap_get_doit,
.post_doit = net_shaper_nl_cap_post_doit,
.policy = net_shaper_cap_get_do_nl_policy,
.maxattr = NET_SHAPER_A_CAPS_SCOPE,
.flags = GENL_CMD_CAP_DO,
},
{
.cmd = NET_SHAPER_CMD_CAP_GET,
.start = net_shaper_nl_cap_pre_dumpit,
.dumpit = net_shaper_nl_cap_get_dumpit,
.done = net_shaper_nl_cap_post_dumpit,
.policy = net_shaper_cap_get_dump_nl_policy,
.maxattr = NET_SHAPER_A_CAPS_IFINDEX,
.flags = GENL_CMD_CAP_DUMP,
},
};
struct genl_family net_shaper_nl_family __ro_after_init = {

View File

@ -17,17 +17,27 @@ extern const struct nla_policy net_shaper_leaf_info_nl_policy[NET_SHAPER_A_WEIGH
int net_shaper_nl_pre_doit(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info);
int net_shaper_nl_cap_pre_doit(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info);
void
net_shaper_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
struct genl_info *info);
void
net_shaper_nl_cap_post_doit(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info);
int net_shaper_nl_pre_dumpit(struct netlink_callback *cb);
int net_shaper_nl_cap_pre_dumpit(struct netlink_callback *cb);
int net_shaper_nl_post_dumpit(struct netlink_callback *cb);
int net_shaper_nl_cap_post_dumpit(struct netlink_callback *cb);
int net_shaper_nl_get_doit(struct sk_buff *skb, struct genl_info *info);
int net_shaper_nl_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
int net_shaper_nl_set_doit(struct sk_buff *skb, struct genl_info *info);
int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info);
int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info);
int net_shaper_nl_cap_get_doit(struct sk_buff *skb, struct genl_info *info);
int net_shaper_nl_cap_get_dumpit(struct sk_buff *skb,
struct netlink_callback *cb);
extern struct genl_family net_shaper_nl_family;