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
, },
54 static int prepare_auto_mode_str(struct nlattr
**tb
, uint32_t mask
,
55 char *output
, int len
)
58 int i
, outlen
= strlen(s
);
60 memset(output
, 0, len
);
61 snprintf(output
, len
, "%s", s
);
64 for (i
= 0; auto_params
[i
].name
!= NULL
; i
++) {
65 if (mask
& auto_params
[i
].attr
) {
66 outlen
+= strlen(auto_params
[i
].name
) + 1;
70 strcat(output
, auto_params
[i
].name
);
74 if (outlen
+ strlen(" on") >= len
)
76 strcat(output
, " on");
78 if (outlen
+ strlen(" off") >= len
)
80 strcat(output
, " off");
86 static int qp_link_get_mode_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
88 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
89 uint32_t mode
= 0, mask
= 0;
90 char output
[128] = {};
95 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
96 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
])
99 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
100 pr_err("This tool doesn't support switches yet\n");
104 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
105 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
106 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
107 if (tb
[RDMA_NLDEV_ATTR_STAT_MODE
])
108 mode
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_MODE
]);
110 if (mode
== RDMA_COUNTER_MODE_AUTO
) {
111 if (!tb
[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
])
113 mask
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
]);
114 prepare_auto_mode_str(tb
, mask
, output
, sizeof(output
));
116 snprintf(output
, sizeof(output
), "qp auto off");
119 open_json_object(NULL
);
120 print_link(rd
, idx
, name
, port
, tb
);
121 print_color_string(PRINT_ANY
, COLOR_NONE
, "mode", "mode %s ", output
);
126 static int stat_one_qp_link_get_mode(struct rd
*rd
)
134 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
,
135 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
137 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
138 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
139 /* Make RDMA_NLDEV_ATTR_STAT_MODE valid so that kernel knows
140 * return only mode instead of all counters
142 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
143 RDMA_COUNTER_MODE_MANUAL
);
144 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
145 ret
= rd_send_msg(rd
);
149 ret
= rd_recv_msg(rd
, qp_link_get_mode_parse_cb
, rd
, seq
);
153 static int stat_qp_link_get_mode(struct rd
*rd
)
155 return rd_exec_link(rd
, stat_one_qp_link_get_mode
, false);
158 static int stat_qp_get_mode(struct rd
*rd
)
160 const struct rd_cmd cmds
[] = {
161 { NULL
, stat_qp_link_get_mode
},
162 { "link", stat_qp_link_get_mode
},
163 { "help", stat_help
},
167 return rd_exec_cmd(rd
, cmds
, "parameter");
170 int res_get_hwcounters(struct rd
*rd
, struct nlattr
*hwc_table
, bool print
)
172 struct nlattr
*nla_entry
;
177 mnl_attr_for_each_nested(nla_entry
, hwc_table
) {
178 struct nlattr
*hw_line
[RDMA_NLDEV_ATTR_MAX
] = {};
180 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, hw_line
);
181 if (err
!= MNL_CB_OK
)
184 if (!hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
] ||
185 !hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
]) {
192 nm
= mnl_attr_get_str(hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
]);
193 v
= mnl_attr_get_u64(hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
]);
194 if (rd
->pretty_output
&& !rd
->json_output
)
196 res_print_uint(rd
, nm
, v
, hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
]);
202 static int res_counter_line(struct rd
*rd
, const char *name
, int index
,
203 struct nlattr
**nla_line
)
205 uint32_t cntn
, port
= 0, pid
= 0, qpn
;
206 struct nlattr
*hwc_table
, *qp_table
;
207 struct nlattr
*nla_entry
;
208 const char *comm
= NULL
;
212 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
213 port
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
215 hwc_table
= nla_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
];
216 qp_table
= nla_line
[RDMA_NLDEV_ATTR_RES_QP
];
217 if (!hwc_table
|| !qp_table
||
218 !nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
])
221 cntn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]);
222 if (rd_is_filtered_attr(rd
, "cntn", cntn
,
223 nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]))
226 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
227 pid
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
228 comm
= get_task_name(pid
);
230 if (rd_is_filtered_attr(rd
, "pid", pid
,
231 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]))
234 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
235 comm
= (char *)mnl_attr_get_str(
236 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
238 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
239 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
241 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
242 if (err
!= MNL_CB_OK
)
245 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
248 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
249 if (rd_is_filtered_attr(rd
, "lqpn", qpn
,
250 qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]))
254 err
= res_get_hwcounters(rd
, hwc_table
, false);
255 if (err
!= MNL_CB_OK
)
257 open_json_object(NULL
);
258 print_link(rd
, index
, name
, port
, nla_line
);
259 print_color_uint(PRINT_ANY
, COLOR_NONE
, "cntn", "cntn %u ", cntn
);
260 res_print_uint(rd
, "pid", pid
, nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
261 print_comm(rd
, comm
, nla_line
);
262 res_get_hwcounters(rd
, hwc_table
, true);
264 open_json_array(PRINT_JSON
, "lqpn");
265 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, "\n LQPN: <", NULL
);
266 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
267 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
268 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
269 if (err
!= MNL_CB_OK
)
272 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
275 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
277 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, ",",
279 print_color_uint(PRINT_ANY
, COLOR_NONE
, NULL
, "%d", qpn
);
282 close_json_array(PRINT_ANY
, ">");
287 static int stat_qp_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
289 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
290 struct nlattr
*nla_table
, *nla_entry
;
291 struct rd
*rd
= data
;
296 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
297 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
298 !tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
])
301 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
302 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
303 nla_table
= tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
];
305 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
306 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
308 ret
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
309 if (ret
!= MNL_CB_OK
)
312 ret
= res_counter_line(rd
, name
, idx
, nla_line
);
313 if (ret
!= MNL_CB_OK
)
320 static const struct filters stat_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
321 { .name
= "cntn", .is_number
= true },
322 { .name
= "lqpn", .is_number
= true },
323 { .name
= "pid", .is_number
= true },
326 static int stat_qp_show_one_link(struct rd
*rd
)
328 int flags
= NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
;
335 ret
= rd_build_filter(rd
, stat_valid_filters
);
339 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
340 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
341 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
342 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
343 ret
= rd_send_msg(rd
);
347 ret
= rd_recv_msg(rd
, stat_qp_show_parse_cb
, rd
, seq
);
351 static int stat_qp_show_link(struct rd
*rd
)
353 return rd_exec_link(rd
, stat_qp_show_one_link
, false);
356 static int stat_qp_show(struct rd
*rd
)
358 const struct rd_cmd cmds
[] = {
359 { NULL
, stat_qp_show_link
},
360 { "link", stat_qp_show_link
},
361 { "help", stat_help
},
365 return rd_exec_cmd(rd
, cmds
, "parameter");
368 static int stat_qp_set_link_auto_sendmsg(struct rd
*rd
, uint32_t mask
)
372 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
373 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
375 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
376 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
377 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
378 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
379 RDMA_COUNTER_MODE_AUTO
);
380 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
, mask
);
382 return rd_sendrecv_msg(rd
, seq
);
385 static int stat_one_qp_set_link_auto_off(struct rd
*rd
)
387 return stat_qp_set_link_auto_sendmsg(rd
, 0);
390 static int stat_one_qp_set_auto_type_on(struct rd
*rd
)
392 return stat_qp_set_link_auto_sendmsg(rd
, RDMA_COUNTER_MASK_QP_TYPE
);
395 static int stat_one_qp_set_link_auto_type(struct rd
*rd
)
397 const struct rd_cmd cmds
[] = {
399 { "on", stat_one_qp_set_auto_type_on
},
403 return rd_exec_cmd(rd
, cmds
, "parameter");
406 static int stat_one_qp_set_link_auto(struct rd
*rd
)
408 const struct rd_cmd cmds
[] = {
409 { NULL
, stat_one_qp_link_get_mode
},
410 { "off", stat_one_qp_set_link_auto_off
},
411 { "type", stat_one_qp_set_link_auto_type
},
415 return rd_exec_cmd(rd
, cmds
, "parameter");
418 static int stat_one_qp_set_link(struct rd
*rd
)
420 const struct rd_cmd cmds
[] = {
421 { NULL
, stat_one_qp_link_get_mode
},
422 { "auto", stat_one_qp_set_link_auto
},
429 return rd_exec_cmd(rd
, cmds
, "parameter");
432 static int stat_qp_set_link(struct rd
*rd
)
434 return rd_exec_link(rd
, stat_one_qp_set_link
, false);
437 static int stat_qp_set(struct rd
*rd
)
439 const struct rd_cmd cmds
[] = {
441 { "link", stat_qp_set_link
},
442 { "help", stat_help
},
446 return rd_exec_cmd(rd
, cmds
, "parameter");
449 static int stat_get_arg(struct rd
*rd
, const char *arg
)
454 if (strcmpx(rd_argv(rd
), arg
) != 0)
458 value
= strtol(rd_argv(rd
), &endp
, 10);
464 static int stat_one_qp_bind(struct rd
*rd
)
466 int lqpn
= 0, cntn
= 0, ret
;
474 ret
= rd_build_filter(rd
, stat_valid_filters
);
478 lqpn
= stat_get_arg(rd
, "lqpn");
480 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
481 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
483 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
484 RDMA_COUNTER_MODE_MANUAL
);
486 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
487 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
488 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
489 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
492 cntn
= stat_get_arg(rd
, "cntn");
493 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
,
497 return rd_sendrecv_msg(rd
, seq
);
500 static int do_stat_qp_unbind_lqpn(struct rd
*rd
, uint32_t cntn
, uint32_t lqpn
)
504 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_DEL
,
505 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
507 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
508 RDMA_COUNTER_MODE_MANUAL
);
509 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
510 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
511 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
512 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
513 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
515 return rd_sendrecv_msg(rd
, seq
);
518 static int stat_get_counter_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
520 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
521 struct nlattr
*nla_table
, *nla_entry
;
522 struct rd
*rd
= data
;
526 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
528 if (!tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
])
530 cntn
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]);
532 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_QP
];
536 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
537 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
539 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
540 if (err
!= MNL_CB_OK
)
543 if (!nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
546 lqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
547 err
= do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
555 static int stat_one_qp_unbind(struct rd
*rd
)
557 int flags
= NLM_F_REQUEST
| NLM_F_ACK
, ret
;
558 char buf
[MNL_SOCKET_BUFFER_SIZE
];
559 int lqpn
= 0, cntn
= 0;
563 ret
= rd_build_filter(rd
, stat_valid_filters
);
567 cntn
= stat_get_arg(rd
, "cntn");
569 lqpn
= stat_get_arg(rd
, "lqpn");
570 return do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
573 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
574 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
575 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
576 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
577 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
578 ret
= rd_send_msg(rd
);
583 /* Can't use rd_recv_msg() since the callback also calls it (recursively),
584 * then rd_recv_msg() always return -1 here
586 portid
= mnl_socket_get_portid(rd
->nl
);
587 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
591 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, stat_get_counter_parse_cb
, rd
);
592 mnl_socket_close(rd
->nl
);
593 if (ret
!= MNL_CB_OK
)
599 static int stat_qp_bind_link(struct rd
*rd
)
601 return rd_exec_link(rd
, stat_one_qp_bind
, true);
604 static int stat_qp_bind(struct rd
*rd
)
606 const struct rd_cmd cmds
[] = {
608 { "link", stat_qp_bind_link
},
609 { "help", stat_help
},
613 return rd_exec_cmd(rd
, cmds
, "parameter");
616 static int stat_qp_unbind_link(struct rd
*rd
)
618 return rd_exec_link(rd
, stat_one_qp_unbind
, true);
621 static int stat_qp_unbind(struct rd
*rd
)
623 const struct rd_cmd cmds
[] = {
625 { "link", stat_qp_unbind_link
},
626 { "help", stat_help
},
630 return rd_exec_cmd(rd
, cmds
, "parameter");
633 static int stat_qp(struct rd
*rd
)
635 const struct rd_cmd cmds
[] = {
636 { NULL
, stat_qp_show
},
637 { "show", stat_qp_show
},
638 { "list", stat_qp_show
},
639 { "mode", stat_qp_get_mode
},
640 { "set", stat_qp_set
},
641 { "bind", stat_qp_bind
},
642 { "unbind", stat_qp_unbind
},
643 { "help", stat_help
},
647 return rd_exec_cmd(rd
, cmds
, "parameter");
650 static int stat_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
652 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
653 struct rd
*rd
= data
;
658 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
659 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
660 !tb
[RDMA_NLDEV_ATTR_PORT_INDEX
] ||
661 !tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
])
664 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
665 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
666 open_json_object(NULL
);
667 print_color_string(PRINT_ANY
, COLOR_NONE
, "ifname", "link %s/", name
);
668 print_color_uint(PRINT_ANY
, COLOR_NONE
, "port", "%u ", port
);
669 ret
= res_get_hwcounters(rd
, tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
], true);
675 static int stat_show_one_link(struct rd
*rd
)
677 int flags
= NLM_F_REQUEST
| NLM_F_ACK
;
684 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
685 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
686 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
687 ret
= rd_send_msg(rd
);
691 return rd_recv_msg(rd
, stat_show_parse_cb
, rd
, seq
);
694 static int stat_show_link(struct rd
*rd
)
696 return rd_exec_link(rd
, stat_show_one_link
, false);
699 static int stat_show(struct rd
*rd
)
701 const struct rd_cmd cmds
[] = {
702 { NULL
, stat_show_link
},
703 { "link", stat_show_link
},
705 { "help", stat_help
},
709 return rd_exec_cmd(rd
, cmds
, "parameter");
712 int cmd_stat(struct rd
*rd
)
714 const struct rd_cmd cmds
[] = {
716 { "show", stat_show
},
717 { "list", stat_show
},
718 { "help", stat_help
},
724 return rd_exec_cmd(rd
, cmds
, "statistic command");