[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <d90fdf8da62da13ce677a248cbf0bb0fe9b29472.1724165948.git.pabeni@redhat.com>
Date: Tue, 20 Aug 2024 17:12:29 +0200
From: Paolo Abeni <pabeni@...hat.com>
To: netdev@...r.kernel.org
Cc: Jakub Kicinski <kuba@...nel.org>,
Jiri Pirko <jiri@...nulli.us>,
Madhu Chittim <madhu.chittim@...el.com>,
Sridhar Samudrala <sridhar.samudrala@...el.com>,
Simon Horman <horms@...nel.org>,
John Fastabend <john.fastabend@...il.com>,
Sunil Kovvuri Goutham <sgoutham@...vell.com>,
Jamal Hadi Salim <jhs@...atatu.com>,
Donald Hunter <donald.hunter@...il.com>
Subject: [PATCH v4 net-next 08/12] net: shaper: implement introspection support
The netlink op is a simple wrapper around the device callback.
Extend the existing fetch_dev() helper adding an attribute argument
for the requested device. Reuse such helper in the newly implemented
operation.
Signed-off-by: Paolo Abeni <pabeni@...hat.com>
---
v3 -> v4:
- another dev_put() -> netdev_put() conversion, missed in previous
iteration
RFC v2 -> v3:
- dev_put() -> netdev_put()
---
include/net/net_shaper.h | 11 ++++
net/shaper/shaper.c | 111 ++++++++++++++++++++++++++++++++++++---
2 files changed, 115 insertions(+), 7 deletions(-)
diff --git a/include/net/net_shaper.h b/include/net/net_shaper.h
index bfb521d31c78..1610bc33d476 100644
--- a/include/net/net_shaper.h
+++ b/include/net/net_shaper.h
@@ -99,6 +99,17 @@ struct net_shaper_ops {
int (*delete)(struct net_device *dev,
const struct net_shaper_handle *handle,
struct netlink_ext_ack *extack);
+
+ /**
+ * @capabilities: get the shaper features supported by the NIC
+ *
+ * Fills the bitmask @cap with the supported cababilites for the
+ * specified @scope and device @dev.
+ *
+ * Returns 0 on success or a negative error value otherwise.
+ */
+ int (*capabilities)(struct net_device *dev,
+ enum net_shaper_scope scope, unsigned long *cap);
};
#endif
diff --git a/net/shaper/shaper.c b/net/shaper/shaper.c
index d3bb0ee1a18a..a119898d4ce0 100644
--- a/net/shaper/shaper.c
+++ b/net/shaper/shaper.c
@@ -117,17 +117,17 @@ net_shaper_fill_one(struct sk_buff *msg,
/* On success sets pdev to the relevant device and acquires a reference
* to it.
*/
-static int net_shaper_fetch_dev(const struct genl_info *info,
+static int net_shaper_fetch_dev(const struct genl_info *info, int type,
struct net_device **pdev)
{
struct net *ns = genl_info_net(info);
struct net_device *dev;
int ifindex;
- if (GENL_REQ_ATTR_CHECK(info, NET_SHAPER_A_IFINDEX))
+ if (GENL_REQ_ATTR_CHECK(info, type))
return -EINVAL;
- ifindex = nla_get_u32(info->attrs[NET_SHAPER_A_IFINDEX]);
+ ifindex = nla_get_u32(info->attrs[type]);
dev = dev_get_by_index(ns, ifindex);
if (!dev) {
GENL_SET_ERR_MSG_FMT(info, "device %d not found", ifindex);
@@ -485,7 +485,7 @@ int net_shaper_nl_pre_doit(const struct genl_split_ops *ops,
struct net_device *dev;
int ret;
- ret = net_shaper_fetch_dev(info, &dev);
+ ret = net_shaper_fetch_dev(info, NET_SHAPER_A_IFINDEX, &dev);
if (ret)
return ret;
@@ -504,12 +504,23 @@ void net_shaper_nl_post_doit(const struct genl_split_ops *ops,
int net_shaper_nl_cap_pre_doit(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info)
{
- return -EOPNOTSUPP;
+ struct net_device *dev;
+ int ret;
+
+ ret = net_shaper_fetch_dev(info, NET_SHAPER_A_CAPABILITIES_IFINDEX, &dev);
+ if (ret)
+ return ret;
+
+ info->user_ptr[0] = dev;
+ return 0;
}
void net_shaper_nl_cap_post_doit(const struct genl_split_ops *ops,
struct sk_buff *skb, struct genl_info *info)
{
+ struct net_device *dev = info->user_ptr[0];
+
+ netdev_put(dev, NULL);
}
int net_shaper_nl_get_doit(struct sk_buff *skb, struct genl_info *info)
@@ -565,7 +576,7 @@ int net_shaper_nl_get_dumpit(struct sk_buff *skb,
unsigned long index;
int ret;
- ret = net_shaper_fetch_dev(info, &dev);
+ ret = net_shaper_fetch_dev(info, NET_SHAPER_A_IFINDEX, &dev);
if (ret)
return ret;
@@ -1063,15 +1074,101 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info)
return ret;
}
+static int
+net_shaper_cap_fill_one(struct sk_buff *msg, int ifindex,
+ enum net_shaper_scope scope, unsigned long flags,
+ const struct genl_info *info)
+{
+ unsigned long cur;
+ void *hdr;
+
+ hdr = genlmsg_iput(msg, info);
+ if (!hdr)
+ return -EMSGSIZE;
+
+ if (nla_put_u32(msg, NET_SHAPER_A_CAPABILITIES_IFINDEX, ifindex) ||
+ nla_put_u32(msg, NET_SHAPER_A_CAPABILITIES_SCOPE, scope))
+ goto nla_put_failure;
+
+ for (cur = NET_SHAPER_A_CAPABILITIES_SUPPORT_METRIC_BPS;
+ cur <= NET_SHAPER_A_CAPABILITIES_MAX; ++cur) {
+ if (flags & BIT(cur) && nla_put_flag(msg, cur))
+ goto nla_put_failure;
+ }
+
+ genlmsg_end(msg, hdr);
+
+ return 0;
+
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ return -EMSGSIZE;
+}
+
int net_shaper_nl_cap_get_doit(struct sk_buff *skb, struct genl_info *info)
{
+ struct net_device *dev = info->user_ptr[0];
+ const struct net_shaper_ops *ops;
+ enum net_shaper_scope scope;
+ struct sk_buff *msg;
+ unsigned long flags;
+ int ret;
+
+ if (GENL_REQ_ATTR_CHECK(info, NET_SHAPER_A_CAPABILITIES_SCOPE))
+ return -EINVAL;
+
+ scope = nla_get_u32(info->attrs[NET_SHAPER_A_CAPABILITIES_SCOPE]);
+ ops = dev->netdev_ops->net_shaper_ops;
+ ret = ops->capabilities(dev, scope, &flags);
+ if (ret)
+ return ret;
+
+ msg = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ ret = net_shaper_cap_fill_one(msg, dev->ifindex, scope, flags, info);
+ if (ret)
+ goto free_msg;
+
+ ret = genlmsg_reply(msg, info);
+ if (ret)
+ goto free_msg;
return 0;
+
+free_msg:
+ nlmsg_free(msg);
+ return ret;
}
int net_shaper_nl_cap_get_dumpit(struct sk_buff *skb,
struct netlink_callback *cb)
{
- return 0;
+ const struct genl_info *info = genl_info_dump(cb);
+ const struct net_shaper_ops *ops;
+ enum net_shaper_scope scope;
+ struct net_device *dev;
+ unsigned long flags;
+ int ret;
+
+ ret = net_shaper_fetch_dev(info, NET_SHAPER_A_CAPABILITIES_IFINDEX, &dev);
+ if (ret)
+ return ret;
+
+ ops = dev->netdev_ops->net_shaper_ops;
+ for (scope = 0; scope <= NET_SHAPER_SCOPE_MAX; ++scope) {
+ if (ops->capabilities(dev, scope, &flags))
+ continue;
+
+ ret = net_shaper_cap_fill_one(skb, dev->ifindex, scope, flags,
+ info);
+ if (ret)
+ goto put;
+ }
+
+put:
+ netdev_put(dev, NULL);
+ return ret;
}
void net_shaper_flush(struct net_device *dev)
--
2.45.2
Powered by blists - more mailing lists