linux-rdma.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jason Gunthorpe <jgg@nvidia.com>
To: Mark Zhang <markzhang@nvidia.com>
Cc: dledford@redhat.com, saeedm@nvidia.com,
	linux-rdma@vger.kernel.org, netdev@vger.kernel.org,
	aharonl@nvidia.com, netao@nvidia.com, leonro@nvidia.com
Subject: Re: [PATCH rdma-next 06/10] RDMA/nldev: Add support to add and remove optional counters
Date: Mon, 23 Aug 2021 16:42:30 -0300	[thread overview]
Message-ID: <20210823194230.GB1006065@nvidia.com> (raw)
In-Reply-To: <20210818112428.209111-7-markzhang@nvidia.com>

On Wed, Aug 18, 2021 at 02:24:24PM +0300, Mark Zhang wrote:
> From: Aharon Landau <aharonl@nvidia.com>
> 
> This patch adds the ability to add/remove optional counter to a link
> through RDMA netlink. Limit it to users with ADMIN capability only.
> 
> Examples:
> $ sudo rdma statistic add link rocep8s0f0/1 optional-set cc_rx_ce_pkts
> $ sudo rdma statistic remove link rocep8s0f0/1 optional-set cc_rx_ce_pkts
> 
> Signed-off-by: Aharon Landau <aharonl@nvidia.com>
> Signed-off-by: Neta Ostrovsky <netao@nvidia.com>
> Signed-off-by: Mark Zhang <markzhang@nvidia.com>
>  drivers/infiniband/core/counters.c | 50 ++++++++++++++++
>  drivers/infiniband/core/device.c   |  2 +
>  drivers/infiniband/core/nldev.c    | 93 ++++++++++++++++++++++++++++++
>  include/rdma/ib_verbs.h            |  7 +++
>  include/rdma/rdma_counter.h        |  4 ++
>  include/rdma/rdma_netlink.h        |  1 +
>  include/uapi/rdma/rdma_netlink.h   |  9 +++
>  7 files changed, 166 insertions(+)
> 
> diff --git a/drivers/infiniband/core/counters.c b/drivers/infiniband/core/counters.c
> index b8b6db98bfdf..fa04178aa0eb 100644
> +++ b/drivers/infiniband/core/counters.c
> @@ -106,6 +106,56 @@ static int __rdma_counter_bind_qp(struct rdma_counter *counter,
>  	return ret;
>  }
>  
> +static struct rdma_op_counter *get_opcounter(struct rdma_op_stats *opstats,
> +					     const char *name)
> +{
> +	int i;
> +
> +	for (i = 0; i < opstats->num_opcounters; i++)
> +		if (!strcmp(opstats->opcounters[i].name, name))
> +			return opstats->opcounters + i;
> +
> +	return NULL;
> +}

Export this and have the netlink code call it instead of working with
strings.

> +static int rdma_opcounter_set(struct ib_device *dev, u32 port,
> +			      const char *name, bool is_add)
> +{
> +	struct rdma_port_counter *port_counter;
> +	struct rdma_op_counter *opc;
> +	int ret;
> +
> +	if (!dev->ops.add_op_stat || !dev->ops.remove_op_stat)
> +		return -EOPNOTSUPP;
> +
> +	port_counter = &dev->port_data[port].port_counter;
> +	opc = get_opcounter(port_counter->opstats, name);
> +	if (!opc)
> +		return -EINVAL;
> +
> +	mutex_lock(&port_counter->opstats->lock);
> +	ret = is_add ? dev->ops.add_op_stat(dev, port, opc->type) :
> +		dev->ops.remove_op_stat(dev, port, opc->type);

Drivers should work by indexes not types, that is how the counter API
is designed

> +int rdma_opcounter_add(struct ib_device *dev, u32 port, const char *name)
> +{
> +	return rdma_opcounter_set(dev, port, name, true);
> +}
> +
> +int rdma_opcounter_remove(struct ib_device *dev, u32 port,
> +			  const char *name)
> +{
> +	return rdma_opcounter_set(dev, port, name, false);
> +}

Just pass in the add/remove flag - all this switching between wrappers
adding the flag is ugly. Do it all the way to the driver.

> +static int nldev_stat_set_op_stat(struct sk_buff *skb,
> +				  struct nlmsghdr *nlh,
> +				  struct netlink_ext_ack *extack,
> +				  bool cmd_add)
> +{
> +	char opcounter[RDMA_NLDEV_ATTR_OPCOUNTER_NAME_SIZE] = {};
> +	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
> +	struct ib_device *device;
> +	struct sk_buff *msg;
> +	u32 index, port;
> +	int ret;
> +
> +	ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
> +			  nldev_policy, extack);
> +
> +	if (ret || !tb[RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENTRY_NAME] ||
> +	    !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
> +	    !tb[RDMA_NLDEV_ATTR_PORT_INDEX])
> +		return -EINVAL;
> +
> +	index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
> +	device = ib_device_get_by_index(sock_net(skb->sk), index);
> +	if (!device)
> +		return -EINVAL;
> +
> +	port = nla_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
> +	if (!rdma_is_port_valid(device, port)) {
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +
> +	nla_strscpy(opcounter, tb[RDMA_NLDEV_ATTR_STAT_OPCOUNTER_ENTRY_NAME],
> +		    sizeof(opcounter));
> +
> +	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
> +	if (!msg) {
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
> +			RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,
> +					 (cmd_add ?
> +					  RDMA_NLDEV_CMD_STAT_ADD_OPCOUNTER :
> +					  RDMA_NLDEV_CMD_STAT_REMOVE_OPCOUNTER)),
> +			0, 0);
> +
> +	if (cmd_add)
> +		ret = rdma_opcounter_add(device, port, opcounter);
> +	else
> +		ret = rdma_opcounter_remove(device, port, opcounter);
> +	if (ret)
> +		goto err_msg;
> +
> +	nlmsg_end(msg, nlh);

Shouldn't the netlink message for a 'set' always return the current
value of the thing being set on return? Eg the same output that GET
would generate?

> +static int nldev_stat_add_op_stat_doit(struct sk_buff *skb,
> +				       struct nlmsghdr *nlh,
> +				       struct netlink_ext_ack *extack)
> +{
> +	return nldev_stat_set_op_stat(skb, nlh, extack, true);
> +}
> +
> +static int nldev_stat_remove_op_stat_doit(struct sk_buff *skb,
> +					  struct nlmsghdr *nlh,
> +					  struct netlink_ext_ack *extack)
> +{
> +	return nldev_stat_set_op_stat(skb, nlh, extack, false);
> +}
> +
>  static int nldev_stat_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
>  			       struct netlink_ext_ack *extack)
>  {
> @@ -2342,6 +2427,14 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
>  		.dump = nldev_res_get_mr_raw_dumpit,
>  		.flags = RDMA_NL_ADMIN_PERM,
>  	},
> +	[RDMA_NLDEV_CMD_STAT_ADD_OPCOUNTER] = {
> +		.doit = nldev_stat_add_op_stat_doit,
> +		.flags = RDMA_NL_ADMIN_PERM,
> +	},
> +	[RDMA_NLDEV_CMD_STAT_REMOVE_OPCOUNTER] = {
> +		.doit = nldev_stat_remove_op_stat_doit,
> +		.flags = RDMA_NL_ADMIN_PERM,
> +	},
>  };

And here I wonder if this is the cannonical way to manipulate lists of
strings in netlink? I'm trying to think of another case like this, did
you reference something?

Are you sure this shouldn't be done via some set on some counter
object?

Jason

  reply	other threads:[~2021-08-23 19:42 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-18 11:24 [PATCH rdma-next 00/10] Optional counter statistics support Mark Zhang
2021-08-18 11:24 ` [PATCH rdma-next 01/10] net/mlx5: Add support in bth_opcode as a match criteria Mark Zhang
2021-08-18 11:24 ` [PATCH rdma-next 02/10] net/mlx5: Add priorities for counters in RDMA namespaces Mark Zhang
2021-08-18 11:24 ` [PATCH rdma-next 03/10] RDMA/counters: Support to allocate per-port optional counter statistics Mark Zhang
2021-08-23 19:30   ` Jason Gunthorpe
2021-08-24  6:22     ` Mark Zhang
2021-08-24 13:14       ` Jason Gunthorpe
2021-08-18 11:24 ` [PATCH rdma-next 04/10] RDMA/mlx5: Add alloc_op_port_stats() support Mark Zhang
2021-08-23 19:19   ` Jason Gunthorpe
2021-08-18 11:24 ` [PATCH rdma-next 05/10] RDMA/mlx5: Add steering support in optional flow counters Mark Zhang
2021-08-18 11:24 ` [PATCH rdma-next 06/10] RDMA/nldev: Add support to add and remove optional counters Mark Zhang
2021-08-23 19:42   ` Jason Gunthorpe [this message]
2021-08-24  2:09     ` Mark Zhang
2021-08-18 11:24 ` [PATCH rdma-next 07/10] RDMA/mlx5: Add add_op_stat() and remove_op_stat() support Mark Zhang
2021-08-18 11:24 ` [PATCH rdma-next 08/10] RDMA/nldev: Add support to get optional counters statistics Mark Zhang
2021-08-18 11:24 ` [PATCH rdma-next 09/10] RDMA/mlx5: Add get_op_stats() support Mark Zhang
2021-08-18 11:24 ` [PATCH rdma-next 10/10] RDMA/nldev: Add support to get current enabled optional counters Mark Zhang
2021-08-23 19:44   ` Jason Gunthorpe
2021-08-24  2:13     ` Mark Zhang
2021-08-24 13:13       ` Jason Gunthorpe
2021-08-23 19:33 ` [PATCH rdma-next 00/10] Optional counter statistics support Jason Gunthorpe
2021-08-24  1:44   ` Mark Zhang
2021-08-24 13:11     ` Jason Gunthorpe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210823194230.GB1006065@nvidia.com \
    --to=jgg@nvidia.com \
    --cc=aharonl@nvidia.com \
    --cc=dledford@redhat.com \
    --cc=leonro@nvidia.com \
    --cc=linux-rdma@vger.kernel.org \
    --cc=markzhang@nvidia.com \
    --cc=netao@nvidia.com \
    --cc=netdev@vger.kernel.org \
    --cc=saeedm@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).