diff --git a/man/man8/rdma-statistic.8 b/man/man8/rdma-statistic.8 index dea6ff24..541b5d63 100644 --- a/man/man8/rdma-statistic.8 +++ b/man/man8/rdma-statistic.8 @@ -1,4 +1,4 @@ -.TH RDMA\-STATISTIC 8 "17 Mar 2019" "iproute2" "Linux" +.TH RDMA\-STATISTIC 8 "27 June 2019" "iproute2" "Linux" .SH NAME rdma-statistic \- RDMA statistic counter configuration .SH SYNOPSIS @@ -15,7 +15,7 @@ rdma-statistic \- RDMA statistic counter configuration .ti -8 .B rdma statistic -.RI "[ " OBJECT " ]" +.RI "{ " OBJECT " }" .B show .ti -8 @@ -63,7 +63,7 @@ rdma-statistic \- RDMA statistic counter configuration .ti -8 .IR OBJECT " := " -.RB "{ " qp " }" +.RB "{ " qp " | " mr " }" .ti -8 .IR CRITERIA " := " @@ -80,13 +80,13 @@ rdma-statistic \- RDMA statistic counter configuration - specifies counters on this RDMA port to show. .SS rdma statistic set - configure counter statistic auto-mode for a specific device/port -In auto mode all objects belong to one category are bind automatically to a single counter set. +In auto mode all objects belong to one category are bind automatically to a single counter set. Not applicable for MR's. .SS rdma statistic bind - manually bind an object (e.g., a qp) with a counter -When bound the statistics of this object are available in this counter. +When bound the statistics of this object are available in this counter. Not applicable for MR's. .SS rdma statistic unbind - manually unbind an object (e.g., a qp) from the counter previously bound -When unbound the statistics of this object are no longer available in this counter; And if object id is not specified then all objects on this counter will be unbound. +When unbound the statistics of this object are no longer available in this counter; And if object id is not specified then all objects on this counter will be unbound. Not applicable for MR's. .I "COUNTER-ID" - specifies the id of the counter to be bound. @@ -152,9 +152,16 @@ On device mlx5_2 port 1, bind the specified qp on the specified counter rdma statistic qp unbind link mlx5_2/1 cntn 4 .RS 4 On device mlx5_2 port 1, unbind all QPs on the specified counter. After that this counter will be released automatically by the kernel. - .RE .PP +rdma statistic show mr +.RS 4 +List all currently allocated MR's and their counters. +.RE +.PP +rdma statistic show mr mrn 6 +.RS 4 +Dump a specific MR statistics with mrn 6. Dumps nothing if does not exists. .SH SEE ALSO .BR rdma (8), @@ -163,5 +170,7 @@ On device mlx5_2 port 1, unbind all QPs on the specified counter. After that thi .BR rdma-resource (8), .br -.SH AUTHOR +.SH AUTHORS Mark Zhang +.br +Erez Alfasi diff --git a/rdma/Makefile b/rdma/Makefile index e3f550bf..aa5ce822 100644 --- a/rdma/Makefile +++ b/rdma/Makefile @@ -7,7 +7,7 @@ ifeq ($(HAVE_MNL),y) CFLAGS += -I./include/uapi/ RDMA_OBJ = rdma.o utils.o dev.o link.o res.o res-pd.o res-mr.o res-cq.o \ - res-cmid.o res-qp.o sys.o stat.o + res-cmid.o res-qp.o sys.o stat.o stat-mr.o TARGETS += rdma endif diff --git a/rdma/res.c b/rdma/res.c index e8607808..7cd05721 100644 --- a/rdma/res.c +++ b/rdma/res.c @@ -103,6 +103,10 @@ int _res_send_idx_msg(struct rd *rd, uint32_t command, mnl_cb_t callback, mnl_attr_put_u32(rd->nlh, id, idx); + if (command == RDMA_NLDEV_CMD_STAT_GET) + mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_STAT_RES, + RDMA_NLDEV_ATTR_RES_MR); + ret = rd_send_msg(rd); if (ret) return ret; @@ -130,6 +134,10 @@ int _res_send_msg(struct rd *rd, uint32_t command, mnl_cb_t callback) mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_PORT_INDEX, rd->port_idx); + if (command == RDMA_NLDEV_CMD_STAT_GET) + mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_STAT_RES, + RDMA_NLDEV_ATTR_RES_MR); + ret = rd_send_msg(rd); if (ret) return ret; diff --git a/rdma/stat-mr.c b/rdma/stat-mr.c new file mode 100644 index 00000000..11f042d4 --- /dev/null +++ b/rdma/stat-mr.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* + * stat-mr.c RDMA tool + * Authors: Erez Alfasi + */ + +#include "res.h" +#include "stat.h" +#include + +static int stat_mr_line(struct rd *rd, const char *name, int idx, + struct nlattr **nla_line) +{ + uint32_t mrn = 0; + int ret; + + if (nla_line[RDMA_NLDEV_ATTR_RES_MRN]) + mrn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_MRN]); + if (rd_is_filtered_attr(rd, "mrn", mrn, + nla_line[RDMA_NLDEV_ATTR_RES_MRN])) + goto out; + + if (rd->json_output) + jsonw_start_array(rd->jw); + + print_dev(rd, idx, name); + res_print_uint(rd, "mrn", mrn, nla_line[RDMA_NLDEV_ATTR_RES_MRN]); + + if (nla_line[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS]) { + ret = res_get_hwcounters( + rd, nla_line[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS], true); + if (ret != MNL_CB_OK) + return ret; + } + + newline(rd); +out: + return MNL_CB_OK; +} + +int stat_mr_idx_parse_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; + struct rd *rd = data; + const char *name; + uint32_t idx; + + mnl_attr_parse(nlh, 0, rd_attr_cb, tb); + if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME]) + return MNL_CB_ERROR; + + name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); + idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); + + return stat_mr_line(rd, name, idx, tb); +} + +int stat_mr_parse_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; + struct nlattr *nla_table, *nla_entry; + struct rd *rd = data; + int ret = MNL_CB_OK; + const char *name; + uint32_t idx; + + mnl_attr_parse(nlh, 0, rd_attr_cb, tb); + if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || + !tb[RDMA_NLDEV_ATTR_RES_MR]) + return MNL_CB_ERROR; + + name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); + idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); + nla_table = tb[RDMA_NLDEV_ATTR_RES_MR]; + + mnl_attr_for_each_nested(nla_entry, nla_table) { + struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; + + ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); + if (ret != MNL_CB_OK) + break; + + ret = stat_mr_line(rd, name, idx, nla_line); + if (ret != MNL_CB_OK) + break; + } + return ret; +} diff --git a/rdma/stat.c b/rdma/stat.c index ef0bbcf1..c5641522 100644 --- a/rdma/stat.c +++ b/rdma/stat.c @@ -6,6 +6,7 @@ #include "rdma.h" #include "res.h" +#include "stat.h" #include static int stat_help(struct rd *rd) @@ -174,7 +175,7 @@ static int stat_qp_get_mode(struct rd *rd) return rd_exec_cmd(rd, cmds, "parameter"); } -static int res_get_hwcounters(struct rd *rd, struct nlattr *hwc_table, bool print) +int res_get_hwcounters(struct rd *rd, struct nlattr *hwc_table, bool print) { struct nlattr *nla_entry; const char *nm; @@ -737,6 +738,7 @@ static int stat_show(struct rd *rd) const struct rd_cmd cmds[] = { { NULL, stat_show_link }, { "link", stat_show_link }, + { "mr", stat_mr }, { "help", stat_help }, { 0 } }; @@ -752,6 +754,7 @@ int cmd_stat(struct rd *rd) { "list", stat_show }, { "help", stat_help }, { "qp", stat_qp }, + { "mr", stat_mr }, { 0 } }; diff --git a/rdma/stat.h b/rdma/stat.h new file mode 100644 index 00000000..b03a10c9 --- /dev/null +++ b/rdma/stat.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* + * stat.h RDMA tool + * Authors: Mark Zhang + * Erez Alfasi + */ +#ifndef _RDMA_TOOL_STAT_H_ +#define _RDMA_TOOL_STAT_H_ + +#include "rdma.h" + +int res_get_hwcounters(struct rd *rd, struct nlattr *hwc_table, + bool print); + +int stat_mr_parse_cb(const struct nlmsghdr *nlh, void *data); +int stat_mr_idx_parse_cb(const struct nlmsghdr *nlh, void *data); + +static const +struct filters stat_mr_valid_filters[MAX_NUMBER_OF_FILTERS] = { + { .name = "mrn", .is_number = true, .is_doit = true }, +}; + +RES_FUNC(stat_mr, RDMA_NLDEV_CMD_STAT_GET, stat_mr_valid_filters, true, + RDMA_NLDEV_ATTR_RES_MRN); + +#endif /* _RDMA_TOOL_STAT_H_ */