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 if (rd
->json_output
) {
119 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
120 jsonw_uint_field(rd
->jw
, "port", port
);
121 jsonw_string_field(rd
->jw
, "mode", output
);
123 pr_out("%u/%u: %s/%u: %s\n", idx
, port
, name
, port
, output
);
129 static int stat_one_qp_link_get_mode(struct rd
*rd
)
137 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
,
138 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
140 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
141 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
142 /* Make RDMA_NLDEV_ATTR_STAT_MODE valid so that kernel knows
143 * return only mode instead of all counters
145 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
146 RDMA_COUNTER_MODE_MANUAL
);
147 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
148 ret
= rd_send_msg(rd
);
153 jsonw_start_object(rd
->jw
);
154 ret
= rd_recv_msg(rd
, qp_link_get_mode_parse_cb
, rd
, seq
);
156 jsonw_end_object(rd
->jw
);
161 static int stat_qp_link_get_mode(struct rd
*rd
)
163 return rd_exec_link(rd
, stat_one_qp_link_get_mode
, false);
166 static int stat_qp_get_mode(struct rd
*rd
)
168 const struct rd_cmd cmds
[] = {
169 { NULL
, stat_qp_link_get_mode
},
170 { "link", stat_qp_link_get_mode
},
171 { "help", stat_help
},
175 return rd_exec_cmd(rd
, cmds
, "parameter");
178 int res_get_hwcounters(struct rd
*rd
, struct nlattr
*hwc_table
, bool print
)
180 struct nlattr
*nla_entry
;
185 mnl_attr_for_each_nested(nla_entry
, hwc_table
) {
186 struct nlattr
*hw_line
[RDMA_NLDEV_ATTR_MAX
] = {};
188 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, hw_line
);
189 if (err
!= MNL_CB_OK
)
192 if (!hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
] ||
193 !hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
]) {
200 nm
= mnl_attr_get_str(hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
]);
201 v
= mnl_attr_get_u64(hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
]);
202 if (rd
->pretty_output
&& !rd
->json_output
)
204 res_print_uint(rd
, nm
, v
, hw_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
]);
210 static int res_counter_line(struct rd
*rd
, const char *name
, int index
,
211 struct nlattr
**nla_line
)
213 uint32_t cntn
, port
= 0, pid
= 0, qpn
;
214 struct nlattr
*hwc_table
, *qp_table
;
215 struct nlattr
*nla_entry
;
216 const char *comm
= NULL
;
220 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
221 port
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
223 hwc_table
= nla_line
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
];
224 qp_table
= nla_line
[RDMA_NLDEV_ATTR_RES_QP
];
225 if (!hwc_table
|| !qp_table
||
226 !nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
])
229 cntn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]);
230 if (rd_is_filtered_attr(rd
, "cntn", cntn
,
231 nla_line
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]))
234 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
235 pid
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
236 comm
= get_task_name(pid
);
238 if (rd_is_filtered_attr(rd
, "pid", pid
,
239 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]))
242 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
243 comm
= (char *)mnl_attr_get_str(
244 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
246 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
247 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
249 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
250 if (err
!= MNL_CB_OK
)
253 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
256 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
257 if (rd_is_filtered_attr(rd
, "lqpn", qpn
,
258 qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]))
262 err
= res_get_hwcounters(rd
, hwc_table
, false);
263 if (err
!= MNL_CB_OK
)
266 if (rd
->json_output
) {
267 jsonw_string_field(rd
->jw
, "ifname", name
);
269 jsonw_uint_field(rd
->jw
, "port", port
);
270 jsonw_uint_field(rd
->jw
, "cntn", cntn
);
273 pr_out("link %s/%u cntn %u ", name
, port
, cntn
);
275 pr_out("dev %s cntn %u ", name
, cntn
);
278 res_print_uint(rd
, "pid", pid
, nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
279 print_comm(rd
, comm
, nla_line
);
281 res_get_hwcounters(rd
, hwc_table
, true);
284 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
285 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
287 if (isfirst
&& !rd
->json_output
)
288 pr_out("\n LQPN: <");
290 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
291 if (err
!= MNL_CB_OK
)
294 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
297 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
298 if (rd
->json_output
) {
299 jsonw_uint_field(rd
->jw
, "lqpn", qpn
);
309 if (!rd
->json_output
)
314 static int stat_qp_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
316 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
317 struct nlattr
*nla_table
, *nla_entry
;
318 struct rd
*rd
= data
;
323 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
324 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
325 !tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
])
328 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
329 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
330 nla_table
= tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
];
332 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
333 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
335 ret
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
336 if (ret
!= MNL_CB_OK
)
339 ret
= res_counter_line(rd
, name
, idx
, nla_line
);
340 if (ret
!= MNL_CB_OK
)
347 static const struct filters stat_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
348 { .name
= "cntn", .is_number
= true },
349 { .name
= "lqpn", .is_number
= true },
350 { .name
= "pid", .is_number
= true },
353 static int stat_qp_show_one_link(struct rd
*rd
)
355 int flags
= NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
;
362 ret
= rd_build_filter(rd
, stat_valid_filters
);
366 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
367 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
368 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
369 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
370 ret
= rd_send_msg(rd
);
375 jsonw_start_object(rd
->jw
);
376 ret
= rd_recv_msg(rd
, stat_qp_show_parse_cb
, rd
, seq
);
378 jsonw_end_object(rd
->jw
);
383 static int stat_qp_show_link(struct rd
*rd
)
385 return rd_exec_link(rd
, stat_qp_show_one_link
, false);
388 static int stat_qp_show(struct rd
*rd
)
390 const struct rd_cmd cmds
[] = {
391 { NULL
, stat_qp_show_link
},
392 { "link", stat_qp_show_link
},
393 { "help", stat_help
},
397 return rd_exec_cmd(rd
, cmds
, "parameter");
400 static int stat_qp_set_link_auto_sendmsg(struct rd
*rd
, uint32_t mask
)
404 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
405 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
407 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
408 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
409 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
410 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
411 RDMA_COUNTER_MODE_AUTO
);
412 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
, mask
);
414 return rd_sendrecv_msg(rd
, seq
);
417 static int stat_one_qp_set_link_auto_off(struct rd
*rd
)
419 return stat_qp_set_link_auto_sendmsg(rd
, 0);
422 static int stat_one_qp_set_auto_type_on(struct rd
*rd
)
424 return stat_qp_set_link_auto_sendmsg(rd
, RDMA_COUNTER_MASK_QP_TYPE
);
427 static int stat_one_qp_set_link_auto_type(struct rd
*rd
)
429 const struct rd_cmd cmds
[] = {
431 { "on", stat_one_qp_set_auto_type_on
},
435 return rd_exec_cmd(rd
, cmds
, "parameter");
438 static int stat_one_qp_set_link_auto(struct rd
*rd
)
440 const struct rd_cmd cmds
[] = {
441 { NULL
, stat_one_qp_link_get_mode
},
442 { "off", stat_one_qp_set_link_auto_off
},
443 { "type", stat_one_qp_set_link_auto_type
},
447 return rd_exec_cmd(rd
, cmds
, "parameter");
450 static int stat_one_qp_set_link(struct rd
*rd
)
452 const struct rd_cmd cmds
[] = {
453 { NULL
, stat_one_qp_link_get_mode
},
454 { "auto", stat_one_qp_set_link_auto
},
461 return rd_exec_cmd(rd
, cmds
, "parameter");
464 static int stat_qp_set_link(struct rd
*rd
)
466 return rd_exec_link(rd
, stat_one_qp_set_link
, false);
469 static int stat_qp_set(struct rd
*rd
)
471 const struct rd_cmd cmds
[] = {
473 { "link", stat_qp_set_link
},
474 { "help", stat_help
},
478 return rd_exec_cmd(rd
, cmds
, "parameter");
481 static int stat_get_arg(struct rd
*rd
, const char *arg
)
486 if (strcmpx(rd_argv(rd
), arg
) != 0)
490 value
= strtol(rd_argv(rd
), &endp
, 10);
496 static int stat_one_qp_bind(struct rd
*rd
)
498 int lqpn
= 0, cntn
= 0, ret
;
506 ret
= rd_build_filter(rd
, stat_valid_filters
);
510 lqpn
= stat_get_arg(rd
, "lqpn");
512 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
513 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
515 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
516 RDMA_COUNTER_MODE_MANUAL
);
518 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
519 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
520 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
521 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
524 cntn
= stat_get_arg(rd
, "cntn");
525 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
,
529 return rd_sendrecv_msg(rd
, seq
);
532 static int do_stat_qp_unbind_lqpn(struct rd
*rd
, uint32_t cntn
, uint32_t lqpn
)
536 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_DEL
,
537 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
539 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
540 RDMA_COUNTER_MODE_MANUAL
);
541 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
542 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
543 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
544 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
545 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
547 return rd_sendrecv_msg(rd
, seq
);
550 static int stat_get_counter_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
552 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
553 struct nlattr
*nla_table
, *nla_entry
;
554 struct rd
*rd
= data
;
558 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
560 if (!tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
])
562 cntn
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]);
564 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_QP
];
568 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
569 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
571 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
572 if (err
!= MNL_CB_OK
)
575 if (!nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
578 lqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
579 err
= do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
587 static int stat_one_qp_unbind(struct rd
*rd
)
589 int flags
= NLM_F_REQUEST
| NLM_F_ACK
, ret
;
590 char buf
[MNL_SOCKET_BUFFER_SIZE
];
591 int lqpn
= 0, cntn
= 0;
595 ret
= rd_build_filter(rd
, stat_valid_filters
);
599 cntn
= stat_get_arg(rd
, "cntn");
601 lqpn
= stat_get_arg(rd
, "lqpn");
602 return do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
605 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
606 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
607 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
608 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
609 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
610 ret
= rd_send_msg(rd
);
615 /* Can't use rd_recv_msg() since the callback also calls it (recursively),
616 * then rd_recv_msg() always return -1 here
618 portid
= mnl_socket_get_portid(rd
->nl
);
619 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
623 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, stat_get_counter_parse_cb
, rd
);
624 mnl_socket_close(rd
->nl
);
625 if (ret
!= MNL_CB_OK
)
631 static int stat_qp_bind_link(struct rd
*rd
)
633 return rd_exec_link(rd
, stat_one_qp_bind
, true);
636 static int stat_qp_bind(struct rd
*rd
)
638 const struct rd_cmd cmds
[] = {
640 { "link", stat_qp_bind_link
},
641 { "help", stat_help
},
645 return rd_exec_cmd(rd
, cmds
, "parameter");
648 static int stat_qp_unbind_link(struct rd
*rd
)
650 return rd_exec_link(rd
, stat_one_qp_unbind
, true);
653 static int stat_qp_unbind(struct rd
*rd
)
655 const struct rd_cmd cmds
[] = {
657 { "link", stat_qp_unbind_link
},
658 { "help", stat_help
},
662 return rd_exec_cmd(rd
, cmds
, "parameter");
665 static int stat_qp(struct rd
*rd
)
667 const struct rd_cmd cmds
[] = {
668 { NULL
, stat_qp_show
},
669 { "show", stat_qp_show
},
670 { "list", stat_qp_show
},
671 { "mode", stat_qp_get_mode
},
672 { "set", stat_qp_set
},
673 { "bind", stat_qp_bind
},
674 { "unbind", stat_qp_unbind
},
675 { "help", stat_help
},
679 return rd_exec_cmd(rd
, cmds
, "parameter");
682 static int stat_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
684 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
685 struct rd
*rd
= data
;
690 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
691 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
692 !tb
[RDMA_NLDEV_ATTR_PORT_INDEX
] ||
693 !tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
])
696 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
697 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
698 if (rd
->json_output
) {
699 jsonw_string_field(rd
->jw
, "ifname", name
);
700 jsonw_uint_field(rd
->jw
, "port", port
);
702 pr_out("link %s/%u ", name
, port
);
705 ret
= res_get_hwcounters(rd
, tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
], true);
707 if (!rd
->json_output
)
712 static int stat_show_one_link(struct rd
*rd
)
714 int flags
= NLM_F_REQUEST
| NLM_F_ACK
;
721 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
722 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
723 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
724 ret
= rd_send_msg(rd
);
728 return rd_recv_msg(rd
, stat_show_parse_cb
, rd
, seq
);
731 static int stat_show_link(struct rd
*rd
)
733 return rd_exec_link(rd
, stat_show_one_link
, false);
736 static int stat_show(struct rd
*rd
)
738 const struct rd_cmd cmds
[] = {
739 { NULL
, stat_show_link
},
740 { "link", stat_show_link
},
742 { "help", stat_help
},
746 return rd_exec_cmd(rd
, cmds
, "parameter");
749 int cmd_stat(struct rd
*rd
)
751 const struct rd_cmd cmds
[] = {
753 { "show", stat_show
},
754 { "list", stat_show
},
755 { "help", stat_help
},
761 return rd_exec_cmd(rd
, cmds
, "statistic command");