1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
4 * Authors: Mark Zhang <markz@mellanox.com>
11 static int stat_help(struct rd
*rd
)
13 pr_out("Usage: %s [ OPTIONS ] statistic { COMMAND | help }\n", rd
->filename
);
14 pr_out(" %s statistic OBJECT show\n", rd
->filename
);
15 pr_out(" %s statistic OBJECT show link [ DEV/PORT_INDEX ] [ FILTER-NAME FILTER-VALUE ]\n", rd
->filename
);
16 pr_out(" %s statistic OBJECT mode\n", rd
->filename
);
17 pr_out(" %s statistic OBJECT set COUNTER_SCOPE [DEV/PORT_INDEX] auto {CRITERIA | off}\n", rd
->filename
);
18 pr_out(" %s statistic OBJECT bind COUNTER_SCOPE [DEV/PORT_INDEX] [OBJECT-ID] [COUNTER-ID]\n", rd
->filename
);
19 pr_out(" %s statistic OBJECT unbind COUNTER_SCOPE [DEV/PORT_INDEX] [COUNTER-ID]\n", rd
->filename
);
20 pr_out(" %s statistic show\n", rd
->filename
);
21 pr_out(" %s statistic show link [ DEV/PORT_INDEX ]\n", rd
->filename
);
22 pr_out("where OBJECT: = { qp }\n");
23 pr_out(" CRITERIA : = { type }\n");
24 pr_out(" COUNTER_SCOPE: = { link | dev }\n");
25 pr_out("Examples:\n");
26 pr_out(" %s statistic qp show\n", rd
->filename
);
27 pr_out(" %s statistic qp show link mlx5_2/1\n", rd
->filename
);
28 pr_out(" %s statistic qp mode\n", rd
->filename
);
29 pr_out(" %s statistic qp mode link mlx5_0\n", rd
->filename
);
30 pr_out(" %s statistic qp set link mlx5_2/1 auto type on\n", rd
->filename
);
31 pr_out(" %s statistic qp set link mlx5_2/1 auto off\n", rd
->filename
);
32 pr_out(" %s statistic qp bind link mlx5_2/1 lqpn 178\n", rd
->filename
);
33 pr_out(" %s statistic qp bind link mlx5_2/1 lqpn 178 cntn 4\n", rd
->filename
);
34 pr_out(" %s statistic qp unbind link mlx5_2/1 cntn 4\n", rd
->filename
);
35 pr_out(" %s statistic qp unbind link mlx5_2/1 cntn 4 lqpn 178\n", rd
->filename
);
36 pr_out(" %s statistic show\n", rd
->filename
);
37 pr_out(" %s statistic show link mlx5_2/1\n", rd
->filename
);
42 struct counter_param
{
47 static struct counter_param auto_params
[] = {
48 { "type", RDMA_COUNTER_MASK_QP_TYPE
, },
52 static int prepare_auto_mode_str(struct nlattr
**tb
, uint32_t mask
,
53 char *output
, int len
)
56 int i
, outlen
= strlen(s
);
58 memset(output
, 0, len
);
59 snprintf(output
, len
, "%s", s
);
62 for (i
= 0; auto_params
[i
].name
!= NULL
; i
++) {
63 if (mask
& auto_params
[i
].attr
) {
64 outlen
+= strlen(auto_params
[i
].name
) + 1;
68 strcat(output
, auto_params
[i
].name
);
72 if (outlen
+ strlen(" on") >= len
)
74 strcat(output
, " on");
76 if (outlen
+ strlen(" off") >= len
)
78 strcat(output
, " off");
84 static int qp_link_get_mode_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
86 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
87 uint32_t mode
= 0, mask
= 0;
88 char output
[128] = {};
93 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
94 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
])
97 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
98 pr_err("This tool doesn't support switches yet\n");
102 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
103 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
104 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
105 if (tb
[RDMA_NLDEV_ATTR_STAT_MODE
])
106 mode
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_MODE
]);
108 if (mode
== RDMA_COUNTER_MODE_AUTO
) {
109 if (!tb
[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
])
111 mask
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
]);
112 prepare_auto_mode_str(tb
, mask
, output
, sizeof(output
));
114 snprintf(output
, sizeof(output
), "qp auto off");
117 if (rd
->json_output
) {
118 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
119 jsonw_uint_field(rd
->jw
, "port", port
);
120 jsonw_string_field(rd
->jw
, "mode", output
);
122 pr_out("%u/%u: %s/%u: %s\n", idx
, port
, name
, port
, output
);
128 static int stat_one_qp_link_get_mode(struct rd
*rd
)
136 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
,
137 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
139 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
140 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
141 /* Make RDMA_NLDEV_ATTR_STAT_MODE valid so that kernel knows
142 * return only mode instead of all counters
144 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
145 RDMA_COUNTER_MODE_MANUAL
);
146 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
147 ret
= rd_send_msg(rd
);
152 jsonw_start_object(rd
->jw
);
153 ret
= rd_recv_msg(rd
, qp_link_get_mode_parse_cb
, rd
, seq
);
155 jsonw_end_object(rd
->jw
);
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 static 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
;
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_PID
]) {
234 pid
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
235 comm
= get_task_name(pid
);
237 if (rd_is_filtered_attr(rd
, "pid", pid
,
238 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]))
241 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
242 comm
= (char *)mnl_attr_get_str(
243 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
245 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
246 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
248 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
249 if (err
!= MNL_CB_OK
)
252 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
255 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
256 if (rd_is_filtered_attr(rd
, "lqpn", qpn
,
257 qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]))
261 err
= res_get_hwcounters(rd
, hwc_table
, false);
262 if (err
!= MNL_CB_OK
)
265 if (rd
->json_output
) {
266 jsonw_string_field(rd
->jw
, "ifname", name
);
268 jsonw_uint_field(rd
->jw
, "port", port
);
269 jsonw_uint_field(rd
->jw
, "cntn", cntn
);
272 pr_out("link %s/%u cntn %u ", name
, port
, cntn
);
274 pr_out("dev %s cntn %u ", name
, cntn
);
277 res_print_uint(rd
, "pid", pid
, nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
278 print_comm(rd
, comm
, nla_line
);
280 res_get_hwcounters(rd
, hwc_table
, true);
283 mnl_attr_for_each_nested(nla_entry
, qp_table
) {
284 struct nlattr
*qp_line
[RDMA_NLDEV_ATTR_MAX
] = {};
286 if (isfirst
&& !rd
->json_output
)
287 pr_out("\n LQPN: <");
289 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, qp_line
);
290 if (err
!= MNL_CB_OK
)
293 if (!qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
296 qpn
= mnl_attr_get_u32(qp_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
297 if (rd
->json_output
) {
298 jsonw_uint_field(rd
->jw
, "lqpn", qpn
);
308 if (!rd
->json_output
)
313 static int stat_qp_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
315 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
316 struct nlattr
*nla_table
, *nla_entry
;
317 struct rd
*rd
= data
;
322 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
323 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
324 !tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
])
327 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
328 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
329 nla_table
= tb
[RDMA_NLDEV_ATTR_STAT_COUNTER
];
331 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
332 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
334 ret
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
335 if (ret
!= MNL_CB_OK
)
338 ret
= res_counter_line(rd
, name
, idx
, nla_line
);
339 if (ret
!= MNL_CB_OK
)
346 static const struct filters stat_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
347 { .name
= "cntn", .is_number
= true },
348 { .name
= "lqpn", .is_number
= true },
349 { .name
= "pid", .is_number
= true },
352 static int stat_qp_show_one_link(struct rd
*rd
)
354 int flags
= NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
;
361 ret
= rd_build_filter(rd
, stat_valid_filters
);
365 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
366 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
367 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
368 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
369 ret
= rd_send_msg(rd
);
374 jsonw_start_object(rd
->jw
);
375 ret
= rd_recv_msg(rd
, stat_qp_show_parse_cb
, rd
, seq
);
377 jsonw_end_object(rd
->jw
);
382 static int stat_qp_show_link(struct rd
*rd
)
384 return rd_exec_link(rd
, stat_qp_show_one_link
, false);
387 static int stat_qp_show(struct rd
*rd
)
389 const struct rd_cmd cmds
[] = {
390 { NULL
, stat_qp_show_link
},
391 { "link", stat_qp_show_link
},
392 { "help", stat_help
},
396 return rd_exec_cmd(rd
, cmds
, "parameter");
399 static int stat_qp_set_link_auto_sendmsg(struct rd
*rd
, uint32_t mask
)
403 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
404 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
406 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
407 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
408 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
409 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
410 RDMA_COUNTER_MODE_AUTO
);
411 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
, mask
);
413 return rd_sendrecv_msg(rd
, seq
);
416 static int stat_one_qp_set_link_auto_off(struct rd
*rd
)
418 return stat_qp_set_link_auto_sendmsg(rd
, 0);
421 static int stat_one_qp_set_auto_type_on(struct rd
*rd
)
423 return stat_qp_set_link_auto_sendmsg(rd
, RDMA_COUNTER_MASK_QP_TYPE
);
426 static int stat_one_qp_set_link_auto_type(struct rd
*rd
)
428 const struct rd_cmd cmds
[] = {
430 { "on", stat_one_qp_set_auto_type_on
},
434 return rd_exec_cmd(rd
, cmds
, "parameter");
437 static int stat_one_qp_set_link_auto(struct rd
*rd
)
439 const struct rd_cmd cmds
[] = {
440 { NULL
, stat_one_qp_link_get_mode
},
441 { "off", stat_one_qp_set_link_auto_off
},
442 { "type", stat_one_qp_set_link_auto_type
},
446 return rd_exec_cmd(rd
, cmds
, "parameter");
449 static int stat_one_qp_set_link(struct rd
*rd
)
451 const struct rd_cmd cmds
[] = {
452 { NULL
, stat_one_qp_link_get_mode
},
453 { "auto", stat_one_qp_set_link_auto
},
460 return rd_exec_cmd(rd
, cmds
, "parameter");
463 static int stat_qp_set_link(struct rd
*rd
)
465 return rd_exec_link(rd
, stat_one_qp_set_link
, false);
468 static int stat_qp_set(struct rd
*rd
)
470 const struct rd_cmd cmds
[] = {
472 { "link", stat_qp_set_link
},
473 { "help", stat_help
},
477 return rd_exec_cmd(rd
, cmds
, "parameter");
480 static int stat_get_arg(struct rd
*rd
, const char *arg
)
485 if (strcmpx(rd_argv(rd
), arg
) != 0)
489 value
= strtol(rd_argv(rd
), &endp
, 10);
495 static int stat_one_qp_bind(struct rd
*rd
)
497 int lqpn
= 0, cntn
= 0, ret
;
505 ret
= rd_build_filter(rd
, stat_valid_filters
);
509 lqpn
= stat_get_arg(rd
, "lqpn");
511 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_SET
,
512 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
514 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
515 RDMA_COUNTER_MODE_MANUAL
);
517 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
518 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
519 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
520 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
523 cntn
= stat_get_arg(rd
, "cntn");
524 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
,
528 return rd_sendrecv_msg(rd
, seq
);
531 static int do_stat_qp_unbind_lqpn(struct rd
*rd
, uint32_t cntn
, uint32_t lqpn
)
535 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_DEL
,
536 &seq
, (NLM_F_REQUEST
| NLM_F_ACK
));
538 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_MODE
,
539 RDMA_COUNTER_MODE_MANUAL
);
540 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
541 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
542 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
543 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
544 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_RES_LQPN
, lqpn
);
546 return rd_sendrecv_msg(rd
, seq
);
549 static int stat_get_counter_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
551 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
552 struct nlattr
*nla_table
, *nla_entry
;
553 struct rd
*rd
= data
;
557 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
559 if (!tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
])
561 cntn
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_STAT_COUNTER_ID
]);
563 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_QP
];
567 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
568 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
570 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
571 if (err
!= MNL_CB_OK
)
574 if (!nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
577 lqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
578 err
= do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
586 static int stat_one_qp_unbind(struct rd
*rd
)
588 int flags
= NLM_F_REQUEST
| NLM_F_ACK
, ret
;
589 char buf
[MNL_SOCKET_BUFFER_SIZE
];
590 int lqpn
= 0, cntn
= 0;
594 ret
= rd_build_filter(rd
, stat_valid_filters
);
598 cntn
= stat_get_arg(rd
, "cntn");
600 lqpn
= stat_get_arg(rd
, "lqpn");
601 return do_stat_qp_unbind_lqpn(rd
, cntn
, lqpn
);
604 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
605 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
606 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
607 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_RES
, RDMA_NLDEV_ATTR_RES_QP
);
608 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_STAT_COUNTER_ID
, cntn
);
609 ret
= rd_send_msg(rd
);
614 /* Can't use rd_recv_msg() since the callback also calls it (recursively),
615 * then rd_recv_msg() always return -1 here
617 portid
= mnl_socket_get_portid(rd
->nl
);
618 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
622 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, stat_get_counter_parse_cb
, rd
);
623 mnl_socket_close(rd
->nl
);
624 if (ret
!= MNL_CB_OK
)
630 static int stat_qp_bind_link(struct rd
*rd
)
632 return rd_exec_link(rd
, stat_one_qp_bind
, true);
635 static int stat_qp_bind(struct rd
*rd
)
637 const struct rd_cmd cmds
[] = {
639 { "link", stat_qp_bind_link
},
640 { "help", stat_help
},
644 return rd_exec_cmd(rd
, cmds
, "parameter");
647 static int stat_qp_unbind_link(struct rd
*rd
)
649 return rd_exec_link(rd
, stat_one_qp_unbind
, true);
652 static int stat_qp_unbind(struct rd
*rd
)
654 const struct rd_cmd cmds
[] = {
656 { "link", stat_qp_unbind_link
},
657 { "help", stat_help
},
661 return rd_exec_cmd(rd
, cmds
, "parameter");
664 static int stat_qp(struct rd
*rd
)
666 const struct rd_cmd cmds
[] = {
667 { NULL
, stat_qp_show
},
668 { "show", stat_qp_show
},
669 { "list", stat_qp_show
},
670 { "mode", stat_qp_get_mode
},
671 { "set", stat_qp_set
},
672 { "bind", stat_qp_bind
},
673 { "unbind", stat_qp_unbind
},
674 { "help", stat_help
},
678 return rd_exec_cmd(rd
, cmds
, "parameter");
681 static int stat_show_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
683 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
684 struct rd
*rd
= data
;
689 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
690 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] || !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
691 !tb
[RDMA_NLDEV_ATTR_PORT_INDEX
] ||
692 !tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
])
695 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
696 port
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
697 if (rd
->json_output
) {
698 jsonw_string_field(rd
->jw
, "ifname", name
);
699 jsonw_uint_field(rd
->jw
, "port", port
);
701 pr_out("link %s/%u ", name
, port
);
704 ret
= res_get_hwcounters(rd
, tb
[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
], true);
706 if (!rd
->json_output
)
711 static int stat_show_one_link(struct rd
*rd
)
713 int flags
= NLM_F_REQUEST
| NLM_F_ACK
;
720 rd_prepare_msg(rd
, RDMA_NLDEV_CMD_STAT_GET
, &seq
, flags
);
721 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
722 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
723 ret
= rd_send_msg(rd
);
727 return rd_recv_msg(rd
, stat_show_parse_cb
, rd
, seq
);
730 static int stat_show_link(struct rd
*rd
)
732 return rd_exec_link(rd
, stat_show_one_link
, false);
735 static int stat_show(struct rd
*rd
)
737 const struct rd_cmd cmds
[] = {
738 { NULL
, stat_show_link
},
739 { "link", stat_show_link
},
740 { "help", stat_help
},
744 return rd_exec_cmd(rd
, cmds
, "parameter");
747 int cmd_stat(struct rd
*rd
)
749 const struct rd_cmd cmds
[] = {
751 { "show", stat_show
},
752 { "list", stat_show
},
753 { "help", stat_help
},
758 return rd_exec_cmd(rd
, cmds
, "statistic command");