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("Examples:\n");
27 pr_out(" %s statistic qp show\n", rd
->filename
);
28 pr_out(" %s statistic qp show link mlx5_2/1\n", rd
->filename
);
29 pr_out(" %s statistic qp mode\n", rd
->filename
);
30 pr_out(" %s statistic qp mode link mlx5_0\n", rd
->filename
);
31 pr_out(" %s statistic qp set link mlx5_2/1 auto type on\n", rd
->filename
);
32 pr_out(" %s statistic qp set link mlx5_2/1 auto off\n", rd
->filename
);
33 pr_out(" %s statistic qp bind link mlx5_2/1 lqpn 178\n", rd
->filename
);
34 pr_out(" %s statistic qp bind link mlx5_2/1 lqpn 178 cntn 4\n", rd
->filename
);
35 pr_out(" %s statistic qp unbind link mlx5_2/1 cntn 4\n", rd
->filename
);
36 pr_out(" %s statistic qp unbind link mlx5_2/1 cntn 4 lqpn 178\n", rd
->filename
);
37 pr_out(" %s statistic show\n", rd
->filename
);
38 pr_out(" %s statistic show link mlx5_2/1\n", rd
->filename
);
43 struct counter_param
{
48 static struct counter_param auto_params
[] = {
49 { "type", RDMA_COUNTER_MASK_QP_TYPE
, },
53 static int prepare_auto_mode_str(struct nlattr
**tb
, uint32_t mask
,
54 char *output
, int len
)
57 int i
, outlen
= strlen(s
);
59 memset(output
, 0, len
);
60 snprintf(output
, len
, "%s", s
);
63 for (i
= 0; auto_params
[i
].name
!= NULL
; i
++) {
64 if (mask
& auto_params
[i
].attr
) {
65 outlen
+= strlen(auto_params
[i
].name
) + 1;
69 strcat(output
, auto_params
[i
].name
);
73 if (outlen
+ strlen(" on") >= len
)
75 strcat(output
, " on");
77 if (outlen
+ strlen(" off") >= len
)
79 strcat(output
, " off");
85 static int qp_link_get_mode_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
87 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
88 uint32_t mode
= 0, mask
= 0;
89 char output
[128] = {};
94 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
95 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
])
98 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
99 pr_err("This tool doesn't support switches yet\n");
103 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
104 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
105 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
106 if (tb
[RDMA_NLDEV_ATTR_STAT_MODE
])
107 mode
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_MODE
]);
109 if (mode
== RDMA_COUNTER_MODE_AUTO
) {
110 if (!tb
[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
])
112 mask
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
]);
113 prepare_auto_mode_str(tb
, mask
, output
, sizeof(output
));
115 snprintf(output
, sizeof(output
), "qp auto off");
118 open_json_object(NULL
);
119 print_link(rd
, idx
, name
, port
, tb
);
120 print_color_string(PRINT_ANY
, COLOR_NONE
, "mode", "mode %s ", output
);
125 static int stat_one_qp_link_get_mode(struct rd
*rd
)
133 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
,
134 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
136 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
137 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
138 /* Make RDMA_NLDEV_ATTR_STAT_MODE valid so that kernel knows
139 * return only mode instead of all counters
141 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
142 RDMA_COUNTER_MODE_MANUAL
);
143 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
144 ret
= rd_send_msg(rd
);
148 ret
= rd_recv_msg(rd
, qp_link_get_mode_parse_cb
, rd
, seq
);
152 static int stat_qp_link_get_mode(struct rd
*rd
)
154 return rd_exec_link(rd
, stat_one_qp_link_get_mode
, false);
157 static int stat_qp_get_mode(struct rd
*rd
)
159 const struct rd_cmd cmds
[] = {
160 { NULL
, stat_qp_link_get_mode
},
161 { "link", stat_qp_link_get_mode
},
162 { "help", stat_help
},
166 return rd_exec_cmd(rd
, cmds
, "parameter");
169 int res_get_hwcounters(struct rd
*rd
, struct nlattr
*hwc_table
, bool print
)
171 struct nlattr
*nla_entry
;
176 mnl_attr_for_each_nested(nla_entry
, hwc_table
) {
177 struct nlattr
*hw_line
[RDMA_NLDEV_ATTR_MAX
] = {};
179 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, hw_line
);
180 if (err
!= MNL_CB_OK
)
183 if (!hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
] ||
184 !hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
]) {
191 nm
= mnl_attr_get_str(hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
]);
192 v
= mnl_attr_get_u64(hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
]);
193 if (rd
->pretty_output
&& !rd
->json_output
)
195 res_print_uint(rd
, nm
, v
, hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
]);
201 static int res_counter_line(struct rd
*rd
, const char *name
, int index
,
202 struct nlattr
**nla_line
)
204 uint32_t cntn
, port
= 0, pid
= 0, qpn
;
205 struct nlattr
*hwc_table
, *qp_table
;
206 struct nlattr
*nla_entry
;
207 const char *comm
= NULL
;
211 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
212 port
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
214 hwc_table
= nla_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
];
215 qp_table
= nla_line
[RDMA_NLDEV_ATTR_RES_QP
];
216 if (!hwc_table
|| !qp_table
||
217 !nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
])
220 cntn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]);
221 if (rd_is_filtered_attr(rd
, "cntn", cntn
,
222 nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]))
225 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
226 pid
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
227 comm
= get_task_name(pid
);
229 if (rd_is_filtered_attr(rd
, "pid", pid
,
230 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]))
233 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
234 comm
= (char *)mnl_attr_get_str(
235 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
237 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
238 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
240 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
241 if (err
!= MNL_CB_OK
)
244 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
247 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
248 if (rd_is_filtered_attr(rd
, "lqpn", qpn
,
249 qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]))
253 err
= res_get_hwcounters(rd
, hwc_table
, false);
254 if (err
!= MNL_CB_OK
)
256 open_json_object(NULL
);
257 print_link(rd
, index
, name
, port
, nla_line
);
258 print_color_uint(PRINT_ANY
, COLOR_NONE
, "cntn", "cntn %u ", cntn
);
259 res_print_uint(rd
, "pid", pid
, nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
260 print_comm(rd
, comm
, nla_line
);
261 res_get_hwcounters(rd
, hwc_table
, true);
263 open_json_array(PRINT_JSON
, "lqpn");
264 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, "\n LQPN: <", NULL
);
265 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
266 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
267 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
268 if (err
!= MNL_CB_OK
)
271 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
274 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
276 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, ",",
278 print_color_uint(PRINT_ANY
, COLOR_NONE
, NULL
, "%d", qpn
);
281 close_json_array(PRINT_ANY
, ">");
286 static int stat_qp_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
288 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
289 struct nlattr
*nla_table
, *nla_entry
;
290 struct rd
*rd
= data
;
295 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
296 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
297 !tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
])
300 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
301 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
302 nla_table
= tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
];
304 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
305 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
307 ret
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
308 if (ret
!= MNL_CB_OK
)
311 ret
= res_counter_line(rd
, name
, idx
, nla_line
);
312 if (ret
!= MNL_CB_OK
)
319 static const struct filters stat_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
320 { .name
= "cntn", .is_number
= true },
321 { .name
= "lqpn", .is_number
= true },
322 { .name
= "pid", .is_number
= true },
325 static int stat_qp_show_one_link(struct rd
*rd
)
327 int flags
= NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
;
334 ret
= rd_build_filter(rd
, stat_valid_filters
);
338 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
339 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
340 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
341 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
342 ret
= rd_send_msg(rd
);
346 ret
= rd_recv_msg(rd
, stat_qp_show_parse_cb
, rd
, seq
);
350 static int stat_qp_show_link(struct rd
*rd
)
352 return rd_exec_link(rd
, stat_qp_show_one_link
, false);
355 static int stat_qp_show(struct rd
*rd
)
357 const struct rd_cmd cmds
[] = {
358 { NULL
, stat_qp_show_link
},
359 { "link", stat_qp_show_link
},
360 { "help", stat_help
},
364 return rd_exec_cmd(rd
, cmds
, "parameter");
367 static int stat_qp_set_link_auto_sendmsg(struct rd
*rd
, uint32_t mask
)
371 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
372 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
374 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
375 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
376 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
377 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
378 RDMA_COUNTER_MODE_AUTO
);
379 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
, mask
);
381 return rd_sendrecv_msg(rd
, seq
);
384 static int stat_one_qp_set_link_auto_off(struct rd
*rd
)
386 return stat_qp_set_link_auto_sendmsg(rd
, 0);
389 static int stat_one_qp_set_auto_type_on(struct rd
*rd
)
391 return stat_qp_set_link_auto_sendmsg(rd
, RDMA_COUNTER_MASK_QP_TYPE
);
394 static int stat_one_qp_set_link_auto_type(struct rd
*rd
)
396 const struct rd_cmd cmds
[] = {
398 { "on", stat_one_qp_set_auto_type_on
},
402 return rd_exec_cmd(rd
, cmds
, "parameter");
405 static int stat_one_qp_set_link_auto(struct rd
*rd
)
407 const struct rd_cmd cmds
[] = {
408 { NULL
, stat_one_qp_link_get_mode
},
409 { "off", stat_one_qp_set_link_auto_off
},
410 { "type", stat_one_qp_set_link_auto_type
},
414 return rd_exec_cmd(rd
, cmds
, "parameter");
417 static int stat_one_qp_set_link(struct rd
*rd
)
419 const struct rd_cmd cmds
[] = {
420 { NULL
, stat_one_qp_link_get_mode
},
421 { "auto", stat_one_qp_set_link_auto
},
428 return rd_exec_cmd(rd
, cmds
, "parameter");
431 static int stat_qp_set_link(struct rd
*rd
)
433 return rd_exec_link(rd
, stat_one_qp_set_link
, false);
436 static int stat_qp_set(struct rd
*rd
)
438 const struct rd_cmd cmds
[] = {
440 { "link", stat_qp_set_link
},
441 { "help", stat_help
},
445 return rd_exec_cmd(rd
, cmds
, "parameter");
448 static int stat_get_arg(struct rd
*rd
, const char *arg
)
453 if (strcmpx(rd_argv(rd
), arg
) != 0)
457 value
= strtol(rd_argv(rd
), &endp
, 10);
463 static int stat_one_qp_bind(struct rd
*rd
)
465 int lqpn
= 0, cntn
= 0, ret
;
473 ret
= rd_build_filter(rd
, stat_valid_filters
);
477 lqpn
= stat_get_arg(rd
, "lqpn");
479 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
480 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
482 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
483 RDMA_COUNTER_MODE_MANUAL
);
485 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
486 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
487 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
488 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
491 cntn
= stat_get_arg(rd
, "cntn");
492 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
,
496 return rd_sendrecv_msg(rd
, seq
);
499 static int do_stat_qp_unbind_lqpn(struct rd
*rd
, uint32_t cntn
, uint32_t lqpn
)
503 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_DEL
,
504 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
506 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
507 RDMA_COUNTER_MODE_MANUAL
);
508 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
509 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
510 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
511 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
512 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
514 return rd_sendrecv_msg(rd
, seq
);
517 static int stat_get_counter_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
519 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
520 struct nlattr
*nla_table
, *nla_entry
;
521 struct rd
*rd
= data
;
525 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
527 if (!tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
])
529 cntn
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]);
531 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_QP
];
535 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
536 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
538 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
539 if (err
!= MNL_CB_OK
)
542 if (!nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
545 lqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
546 err
= do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
554 static int stat_one_qp_unbind(struct rd
*rd
)
556 int flags
= NLM_F_REQUEST
| NLM_F_ACK
, ret
;
557 char buf
[MNL_SOCKET_BUFFER_SIZE
];
558 int lqpn
= 0, cntn
= 0;
562 ret
= rd_build_filter(rd
, stat_valid_filters
);
566 cntn
= stat_get_arg(rd
, "cntn");
568 lqpn
= stat_get_arg(rd
, "lqpn");
569 return do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
572 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
573 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
574 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
575 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
576 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
577 ret
= rd_send_msg(rd
);
582 /* Can't use rd_recv_msg() since the callback also calls it (recursively),
583 * then rd_recv_msg() always return -1 here
585 portid
= mnl_socket_get_portid(rd
->nl
);
586 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
590 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, stat_get_counter_parse_cb
, rd
);
591 mnl_socket_close(rd
->nl
);
592 if (ret
!= MNL_CB_OK
)
598 static int stat_qp_bind_link(struct rd
*rd
)
600 return rd_exec_link(rd
, stat_one_qp_bind
, true);
603 static int stat_qp_bind(struct rd
*rd
)
605 const struct rd_cmd cmds
[] = {
607 { "link", stat_qp_bind_link
},
608 { "help", stat_help
},
612 return rd_exec_cmd(rd
, cmds
, "parameter");
615 static int stat_qp_unbind_link(struct rd
*rd
)
617 return rd_exec_link(rd
, stat_one_qp_unbind
, true);
620 static int stat_qp_unbind(struct rd
*rd
)
622 const struct rd_cmd cmds
[] = {
624 { "link", stat_qp_unbind_link
},
625 { "help", stat_help
},
629 return rd_exec_cmd(rd
, cmds
, "parameter");
632 static int stat_qp(struct rd
*rd
)
634 const struct rd_cmd cmds
[] = {
635 { NULL
, stat_qp_show
},
636 { "show", stat_qp_show
},
637 { "list", stat_qp_show
},
638 { "mode", stat_qp_get_mode
},
639 { "set", stat_qp_set
},
640 { "bind", stat_qp_bind
},
641 { "unbind", stat_qp_unbind
},
642 { "help", stat_help
},
646 return rd_exec_cmd(rd
, cmds
, "parameter");
649 static int stat_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
651 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
652 struct rd
*rd
= data
;
657 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
658 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
659 !tb
[RDMA_NLDEV_ATTR_PORT_INDEX
] ||
660 !tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
])
663 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
664 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
665 open_json_object(NULL
);
666 print_color_string(PRINT_ANY
, COLOR_NONE
, "ifname", "link %s/", name
);
667 print_color_uint(PRINT_ANY
, COLOR_NONE
, "port", "%u ", port
);
668 ret
= res_get_hwcounters(rd
, tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
], true);
674 static int stat_show_one_link(struct rd
*rd
)
676 int flags
= NLM_F_REQUEST
| NLM_F_ACK
;
683 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
684 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
685 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
686 ret
= rd_send_msg(rd
);
690 return rd_recv_msg(rd
, stat_show_parse_cb
, rd
, seq
);
693 static int stat_show_link(struct rd
*rd
)
695 return rd_exec_link(rd
, stat_show_one_link
, false);
698 static int stat_show(struct rd
*rd
)
700 const struct rd_cmd cmds
[] = {
701 { NULL
, stat_show_link
},
702 { "link", stat_show_link
},
704 { "help", stat_help
},
708 return rd_exec_cmd(rd
, cmds
, "parameter");
711 int cmd_stat(struct rd
*rd
)
713 const struct rd_cmd cmds
[] = {
715 { "show", stat_show
},
716 { "list", stat_show
},
717 { "help", stat_help
},
723 return rd_exec_cmd(rd
, cmds
, "statistic command");