1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
4 * Authors: Mark Zhang <markz@mellanox.com>
12 static int stat_help(struct rd
*rd
)
14 pr_out("Usage: %s [ OPTIONS ] statistic { COMMAND | help }\n", rd
->filename
);
15 pr_out(" %s statistic OBJECT show\n", rd
->filename
);
16 pr_out(" %s statistic OBJECT show link [ DEV/PORT_INDEX ] [ FILTER-NAME FILTER-VALUE ]\n", rd
->filename
);
17 pr_out(" %s statistic OBJECT mode\n", rd
->filename
);
18 pr_out(" %s statistic OBJECT set COUNTER_SCOPE [DEV/PORT_INDEX] auto {CRITERIA | off}\n", rd
->filename
);
19 pr_out(" %s statistic OBJECT bind COUNTER_SCOPE [DEV/PORT_INDEX] [OBJECT-ID] [COUNTER-ID]\n", rd
->filename
);
20 pr_out(" %s statistic OBJECT unbind COUNTER_SCOPE [DEV/PORT_INDEX] [COUNTER-ID]\n", rd
->filename
);
21 pr_out(" %s statistic show\n", rd
->filename
);
22 pr_out(" %s statistic show link [ DEV/PORT_INDEX ]\n", rd
->filename
);
23 pr_out("where OBJECT: = { qp }\n");
24 pr_out(" CRITERIA : = { type }\n");
25 pr_out(" COUNTER_SCOPE: = { link | dev }\n");
26 pr_out(" FILTER_NAME: = { cntn | lqpn | pid }\n");
27 pr_out("Examples:\n");
28 pr_out(" %s statistic qp show\n", rd
->filename
);
29 pr_out(" %s statistic qp show link mlx5_2/1\n", rd
->filename
);
30 pr_out(" %s statistic qp mode\n", rd
->filename
);
31 pr_out(" %s statistic qp mode link mlx5_0\n", rd
->filename
);
32 pr_out(" %s statistic qp set link mlx5_2/1 auto type on\n", rd
->filename
);
33 pr_out(" %s statistic qp set link mlx5_2/1 auto off\n", rd
->filename
);
34 pr_out(" %s statistic qp bind link mlx5_2/1 lqpn 178\n", rd
->filename
);
35 pr_out(" %s statistic qp bind link mlx5_2/1 lqpn 178 cntn 4\n", rd
->filename
);
36 pr_out(" %s statistic qp unbind link mlx5_2/1 cntn 4\n", rd
->filename
);
37 pr_out(" %s statistic qp unbind link mlx5_2/1 cntn 4 lqpn 178\n", rd
->filename
);
38 pr_out(" %s statistic show\n", rd
->filename
);
39 pr_out(" %s statistic show link mlx5_2/1\n", rd
->filename
);
44 struct counter_param
{
49 static struct counter_param auto_params
[] = {
50 { "type", RDMA_COUNTER_MASK_QP_TYPE
, },
51 { "pid", RDMA_COUNTER_MASK_PID
, },
55 static int prepare_auto_mode_str(struct nlattr
**tb
, uint32_t mask
,
56 char *output
, int len
)
59 int i
, outlen
= strlen(s
);
62 memset(output
, 0, len
);
63 snprintf(output
, len
, "%s", s
);
66 for (i
= 0; auto_params
[i
].name
!= NULL
; i
++) {
67 if (mask
& auto_params
[i
].attr
) {
68 outlen
+= strlen(auto_params
[i
].name
) + 1;
77 strcat(output
, auto_params
[i
].name
);
81 if (outlen
+ strlen(" on") >= len
)
83 strcat(output
, " on");
85 if (outlen
+ strlen(" off") >= len
)
87 strcat(output
, " off");
93 static int qp_link_get_mode_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
95 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
96 uint32_t mode
= 0, mask
= 0;
97 char output
[128] = {};
102 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
103 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
])
106 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
107 pr_err("This tool doesn't support switches yet\n");
111 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
112 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
113 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
114 if (tb
[RDMA_NLDEV_ATTR_STAT_MODE
])
115 mode
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_MODE
]);
117 if (mode
== RDMA_COUNTER_MODE_AUTO
) {
118 if (!tb
[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
])
120 mask
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
]);
121 prepare_auto_mode_str(tb
, mask
, output
, sizeof(output
));
123 snprintf(output
, sizeof(output
), "qp auto off");
126 open_json_object(NULL
);
127 print_link(rd
, idx
, name
, port
, tb
);
128 print_color_string(PRINT_ANY
, COLOR_NONE
, "mode", "mode %s ", output
);
133 static int stat_one_qp_link_get_mode(struct rd
*rd
)
141 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
,
142 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
144 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
145 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
146 /* Make RDMA_NLDEV_ATTR_STAT_MODE valid so that kernel knows
147 * return only mode instead of all counters
149 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
150 RDMA_COUNTER_MODE_MANUAL
);
151 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
152 ret
= rd_send_msg(rd
);
156 ret
= rd_recv_msg(rd
, qp_link_get_mode_parse_cb
, rd
, seq
);
160 static int stat_qp_link_get_mode(struct rd
*rd
)
162 return rd_exec_link(rd
, stat_one_qp_link_get_mode
, false);
165 static int stat_qp_get_mode(struct rd
*rd
)
167 const struct rd_cmd cmds
[] = {
168 { NULL
, stat_qp_link_get_mode
},
169 { "link", stat_qp_link_get_mode
},
170 { "help", stat_help
},
174 return rd_exec_cmd(rd
, cmds
, "parameter");
177 int res_get_hwcounters(struct rd
*rd
, struct nlattr
*hwc_table
, bool print
)
179 struct nlattr
*nla_entry
;
184 mnl_attr_for_each_nested(nla_entry
, hwc_table
) {
185 struct nlattr
*hw_line
[RDMA_NLDEV_ATTR_MAX
] = {};
187 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, hw_line
);
188 if (err
!= MNL_CB_OK
)
191 if (!hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
] ||
192 !hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
]) {
199 nm
= mnl_attr_get_str(hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
]);
200 v
= mnl_attr_get_u64(hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
]);
201 if (rd
->pretty_output
&& !rd
->json_output
)
203 res_print_uint(rd
, nm
, v
, hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
]);
209 static int res_counter_line(struct rd
*rd
, const char *name
, int index
,
210 struct nlattr
**nla_line
)
212 uint32_t cntn
, port
= 0, pid
= 0, qpn
, qp_type
= 0;
213 struct nlattr
*hwc_table
, *qp_table
;
214 struct nlattr
*nla_entry
;
215 const char *comm
= NULL
;
219 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
220 port
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
222 hwc_table
= nla_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
];
223 qp_table
= nla_line
[RDMA_NLDEV_ATTR_RES_QP
];
224 if (!hwc_table
|| !qp_table
||
225 !nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
])
228 cntn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]);
229 if (rd_is_filtered_attr(rd
, "cntn", cntn
,
230 nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]))
233 if (nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
])
234 qp_type
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]);
236 if (rd_is_string_filtered_attr(rd
, "qp-type", qp_types_to_str(qp_type
),
237 nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]))
240 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
241 pid
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
242 comm
= get_task_name(pid
);
244 if (rd_is_filtered_attr(rd
, "pid", pid
,
245 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]))
248 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
249 comm
= (char *)mnl_attr_get_str(
250 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
252 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
253 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
255 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
256 if (err
!= MNL_CB_OK
)
259 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
262 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
263 if (rd_is_filtered_attr(rd
, "lqpn", qpn
,
264 qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]))
268 err
= res_get_hwcounters(rd
, hwc_table
, false);
269 if (err
!= MNL_CB_OK
)
271 open_json_object(NULL
);
272 print_link(rd
, index
, name
, port
, nla_line
);
273 print_color_uint(PRINT_ANY
, COLOR_NONE
, "cntn", "cntn %u ", cntn
);
274 if (nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
])
275 print_qp_type(rd
, qp_type
);
276 res_print_uint(rd
, "pid", pid
, nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
277 print_comm(rd
, comm
, nla_line
);
278 res_get_hwcounters(rd
, hwc_table
, true);
280 open_json_array(PRINT_JSON
, "lqpn");
281 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, "\n LQPN: <", NULL
);
282 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
283 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
284 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
285 if (err
!= MNL_CB_OK
)
288 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
291 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
293 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, ",",
295 print_color_uint(PRINT_ANY
, COLOR_NONE
, NULL
, "%d", qpn
);
298 close_json_array(PRINT_ANY
, ">");
303 static int stat_qp_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
305 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
306 struct nlattr
*nla_table
, *nla_entry
;
307 struct rd
*rd
= data
;
312 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
313 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
314 !tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
])
317 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
318 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
319 nla_table
= tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
];
321 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
322 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
324 ret
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
325 if (ret
!= MNL_CB_OK
)
328 ret
= res_counter_line(rd
, name
, idx
, nla_line
);
329 if (ret
!= MNL_CB_OK
)
336 static const struct filters stat_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
337 { .name
= "cntn", .is_number
= true },
338 { .name
= "lqpn", .is_number
= true },
339 { .name
= "pid", .is_number
= true },
340 { .name
= "qp-type", .is_number
= false },
343 static int stat_qp_show_one_link(struct rd
*rd
)
345 int flags
= NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
;
352 ret
= rd_build_filter(rd
, stat_valid_filters
);
356 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
357 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
358 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
359 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
360 ret
= rd_send_msg(rd
);
364 ret
= rd_recv_msg(rd
, stat_qp_show_parse_cb
, rd
, seq
);
368 static int stat_qp_show_link(struct rd
*rd
)
370 return rd_exec_link(rd
, stat_qp_show_one_link
, false);
373 static int stat_qp_show(struct rd
*rd
)
375 const struct rd_cmd cmds
[] = {
376 { NULL
, stat_qp_show_link
},
377 { "link", stat_qp_show_link
},
378 { "help", stat_help
},
382 return rd_exec_cmd(rd
, cmds
, "parameter");
385 static int stat_qp_set_link_auto_sendmsg(struct rd
*rd
, uint32_t mask
)
389 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
390 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
392 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
393 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
394 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
395 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
396 RDMA_COUNTER_MODE_AUTO
);
397 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
, mask
);
399 return rd_sendrecv_msg(rd
, seq
);
402 static int stat_get_auto_mode_mask(struct rd
*rd
)
404 char *modes
= rd_argv(rd
), *mode
, *saved_ptr
;
405 const char *delim
= ",";
406 int mask
= 0, found
, i
;
411 mode
= strtok_r(modes
, delim
, &saved_ptr
);
417 for (i
= 0; auto_params
[i
].name
!= NULL
; i
++) {
418 if (!strcmp(mode
, auto_params
[i
].name
)) {
419 mask
|= auto_params
[i
].attr
;
426 pr_err("Unknown auto mode '%s'.\n", mode
);
431 mode
= strtok_r(NULL
, delim
, &saved_ptr
);
440 static int stat_one_qp_set_link_auto(struct rd
*rd
)
447 if (!strcmpx(rd_argv(rd
), "off")) {
449 return stat_qp_set_link_auto_sendmsg(rd
, 0);
452 auto_mask
= stat_get_auto_mode_mask(rd
);
453 if (!auto_mask
|| !rd_argc(rd
))
456 if (!strcmpx(rd_argv(rd
), "on")) {
458 return stat_qp_set_link_auto_sendmsg(rd
, auto_mask
);
460 pr_err("Unknown parameter '%s'.\n", rd_argv(rd
));
465 static int stat_one_qp_set_link(struct rd
*rd
)
467 const struct rd_cmd cmds
[] = {
468 { NULL
, stat_one_qp_link_get_mode
},
469 { "auto", stat_one_qp_set_link_auto
},
476 return rd_exec_cmd(rd
, cmds
, "parameter");
479 static int stat_qp_set_link(struct rd
*rd
)
481 return rd_exec_link(rd
, stat_one_qp_set_link
, false);
484 static int stat_qp_set(struct rd
*rd
)
486 const struct rd_cmd cmds
[] = {
488 { "link", stat_qp_set_link
},
489 { "help", stat_help
},
493 return rd_exec_cmd(rd
, cmds
, "parameter");
496 static int stat_get_arg(struct rd
*rd
, const char *arg
)
501 if (strcmpx(rd_argv(rd
), arg
) != 0)
505 value
= strtol(rd_argv(rd
), &endp
, 10);
511 static int stat_one_qp_bind(struct rd
*rd
)
513 int lqpn
= 0, cntn
= 0, ret
;
521 ret
= rd_build_filter(rd
, stat_valid_filters
);
525 lqpn
= stat_get_arg(rd
, "lqpn");
527 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
528 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
530 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
531 RDMA_COUNTER_MODE_MANUAL
);
533 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
534 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
535 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
536 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
539 cntn
= stat_get_arg(rd
, "cntn");
540 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
,
544 return rd_sendrecv_msg(rd
, seq
);
547 static int do_stat_qp_unbind_lqpn(struct rd
*rd
, uint32_t cntn
, uint32_t lqpn
)
551 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_DEL
,
552 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
554 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
555 RDMA_COUNTER_MODE_MANUAL
);
556 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
557 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
558 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
559 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
560 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
562 return rd_sendrecv_msg(rd
, seq
);
565 static int stat_get_counter_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
567 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
568 struct nlattr
*nla_table
, *nla_entry
;
569 struct rd
*rd
= data
;
573 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
575 if (!tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
])
577 cntn
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]);
579 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_QP
];
583 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
584 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
586 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
587 if (err
!= MNL_CB_OK
)
590 if (!nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
593 lqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
594 err
= do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
602 static int stat_one_qp_unbind(struct rd
*rd
)
604 int flags
= NLM_F_REQUEST
| NLM_F_ACK
, ret
;
605 char buf
[MNL_SOCKET_BUFFER_SIZE
];
606 int lqpn
= 0, cntn
= 0;
610 ret
= rd_build_filter(rd
, stat_valid_filters
);
614 cntn
= stat_get_arg(rd
, "cntn");
616 lqpn
= stat_get_arg(rd
, "lqpn");
617 return do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
620 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
621 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
622 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
623 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
624 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
625 ret
= rd_send_msg(rd
);
630 /* Can't use rd_recv_msg() since the callback also calls it (recursively),
631 * then rd_recv_msg() always return -1 here
633 portid
= mnl_socket_get_portid(rd
->nl
);
634 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
638 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, stat_get_counter_parse_cb
, rd
);
639 mnl_socket_close(rd
->nl
);
640 if (ret
!= MNL_CB_OK
)
646 static int stat_qp_bind_link(struct rd
*rd
)
648 return rd_exec_link(rd
, stat_one_qp_bind
, true);
651 static int stat_qp_bind(struct rd
*rd
)
653 const struct rd_cmd cmds
[] = {
655 { "link", stat_qp_bind_link
},
656 { "help", stat_help
},
660 return rd_exec_cmd(rd
, cmds
, "parameter");
663 static int stat_qp_unbind_link(struct rd
*rd
)
665 return rd_exec_link(rd
, stat_one_qp_unbind
, true);
668 static int stat_qp_unbind(struct rd
*rd
)
670 const struct rd_cmd cmds
[] = {
672 { "link", stat_qp_unbind_link
},
673 { "help", stat_help
},
677 return rd_exec_cmd(rd
, cmds
, "parameter");
680 static int stat_qp(struct rd
*rd
)
682 const struct rd_cmd cmds
[] = {
683 { NULL
, stat_qp_show
},
684 { "show", stat_qp_show
},
685 { "list", stat_qp_show
},
686 { "mode", stat_qp_get_mode
},
687 { "set", stat_qp_set
},
688 { "bind", stat_qp_bind
},
689 { "unbind", stat_qp_unbind
},
690 { "help", stat_help
},
694 return rd_exec_cmd(rd
, cmds
, "parameter");
697 static int stat_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
699 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
700 struct rd
*rd
= data
;
705 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
706 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
707 !tb
[RDMA_NLDEV_ATTR_PORT_INDEX
] ||
708 !tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
])
711 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
712 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
713 open_json_object(NULL
);
714 print_color_string(PRINT_ANY
, COLOR_NONE
, "ifname", "link %s/", name
);
715 print_color_uint(PRINT_ANY
, COLOR_NONE
, "port", "%u ", port
);
716 ret
= res_get_hwcounters(rd
, tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
], true);
722 static int stat_show_one_link(struct rd
*rd
)
724 int flags
= NLM_F_REQUEST
| NLM_F_ACK
;
731 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
732 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
733 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
734 ret
= rd_send_msg(rd
);
738 return rd_recv_msg(rd
, stat_show_parse_cb
, rd
, seq
);
741 static int stat_show_link(struct rd
*rd
)
743 return rd_exec_link(rd
, stat_show_one_link
, false);
746 static int stat_show(struct rd
*rd
)
748 const struct rd_cmd cmds
[] = {
749 { NULL
, stat_show_link
},
750 { "link", stat_show_link
},
752 { "help", stat_help
},
756 return rd_exec_cmd(rd
, cmds
, "parameter");
759 int cmd_stat(struct rd
*rd
)
761 const struct rd_cmd cmds
[] = {
763 { "show", stat_show
},
764 { "list", stat_show
},
765 { "help", stat_help
},
771 return rd_exec_cmd(rd
, cmds
, "statistic command");