4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Leon Romanovsky <leonro@mellanox.com>
15 static int res_help(struct rd
*rd
)
17 pr_out("Usage: %s resource\n", rd
->filename
);
18 pr_out(" resource show [DEV]\n");
19 pr_out(" resource show [qp|cm_id|pd|mr|cq]\n");
20 pr_out(" resource show qp link [DEV/PORT]\n");
21 pr_out(" resource show qp link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
22 pr_out(" resource show cm_id link [DEV/PORT]\n");
23 pr_out(" resource show cm_id link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
24 pr_out(" resource show cq link [DEV/PORT]\n");
25 pr_out(" resource show cq link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
26 pr_out(" resource show pd dev [DEV]\n");
27 pr_out(" resource show pd dev [DEV] [FILTER-NAME FILTER-VALUE]\n");
28 pr_out(" resource show mr dev [DEV]\n");
29 pr_out(" resource show mr dev [DEV] [FILTER-NAME FILTER-VALUE]\n");
33 static int res_print_summary(struct rd
*rd
, struct nlattr
**tb
)
35 struct nlattr
*nla_table
= tb
[RDMA_NLDEV_ATTR_RES_SUMMARY
];
36 struct nlattr
*nla_entry
;
41 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
42 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
45 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
49 if (!nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME
] ||
50 !nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR
]) {
54 name
= mnl_attr_get_str(nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME
]);
55 curr
= mnl_attr_get_u64(nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR
]);
56 if (rd
->json_output
) {
57 snprintf(json_name
, 32, "%s", name
);
58 jsonw_lluint_field(rd
->jw
, json_name
, curr
);
60 pr_out("%s %"PRId64
" ", name
, curr
);
66 static int res_no_args_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
68 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
73 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
74 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
75 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
76 !tb
[RDMA_NLDEV_ATTR_RES_SUMMARY
])
79 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
80 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
81 if (rd
->json_output
) {
82 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
83 jsonw_string_field(rd
->jw
, "ifname", name
);
85 pr_out("%u: %s: ", idx
, name
);
88 res_print_summary(rd
, tb
);
95 static int _res_send_msg(struct rd
*rd
, uint32_t command
, mnl_cb_t callback
)
97 uint32_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
101 if (command
!= RDMA_NLDEV_CMD_RES_GET
)
104 rd_prepare_msg(rd
, command
, &seq
, flags
);
105 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
107 mnl_attr_put_u32(rd
->nlh
,
108 RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
110 ret
= rd_send_msg(rd
);
115 jsonw_start_object(rd
->jw
);
116 ret
= rd_recv_msg(rd
, callback
, rd
, seq
);
118 jsonw_end_object(rd
->jw
);
122 #define RES_FUNC(name, command, valid_filters, strict_port) \
123 static int _##name(struct rd *rd)\
125 return _res_send_msg(rd, command, name##_parse_cb); \
127 static int name(struct rd *rd) \
129 int ret = rd_build_filter(rd, valid_filters); \
132 if ((uintptr_t)valid_filters != (uintptr_t)NULL) { \
133 ret = rd_set_arg_to_devname(rd); \
138 return rd_exec_dev(rd, _##name); \
140 return rd_exec_link(rd, _##name, strict_port); \
143 static const char *path_mig_to_str(uint8_t idx
)
145 static const char * const path_mig_str
[] = { "MIGRATED",
148 if (idx
< ARRAY_SIZE(path_mig_str
))
149 return path_mig_str
[idx
];
153 static const char *qp_states_to_str(uint8_t idx
)
155 static const char * const qp_states_str
[] = { "RESET", "INIT",
159 if (idx
< ARRAY_SIZE(qp_states_str
))
160 return qp_states_str
[idx
];
164 static const char *qp_types_to_str(uint8_t idx
)
166 static const char * const qp_types_str
[] = { "SMI", "GSI", "RC",
167 "UC", "UD", "RAW_IPV6",
169 "UNKNOWN", "RAW_PACKET",
170 "XRC_INI", "XRC_TGT" };
172 if (idx
< ARRAY_SIZE(qp_types_str
))
173 return qp_types_str
[idx
];
177 static void print_lqpn(struct rd
*rd
, uint32_t val
)
180 jsonw_uint_field(rd
->jw
, "lqpn", val
);
182 pr_out("lqpn %u ", val
);
185 static void print_rqpn(struct rd
*rd
, uint32_t val
, struct nlattr
**nla_line
)
187 if (!nla_line
[RDMA_NLDEV_ATTR_RES_RQPN
])
191 jsonw_uint_field(rd
->jw
, "rqpn", val
);
193 pr_out("rqpn %u ", val
);
196 static void print_type(struct rd
*rd
, uint32_t val
)
199 jsonw_string_field(rd
->jw
, "type",
200 qp_types_to_str(val
));
202 pr_out("type %s ", qp_types_to_str(val
));
205 static void print_state(struct rd
*rd
, uint32_t val
)
208 jsonw_string_field(rd
->jw
, "state",
209 qp_states_to_str(val
));
211 pr_out("state %s ", qp_states_to_str(val
));
214 static void print_rqpsn(struct rd
*rd
, uint32_t val
, struct nlattr
**nla_line
)
216 if (!nla_line
[RDMA_NLDEV_ATTR_RES_RQ_PSN
])
220 jsonw_uint_field(rd
->jw
, "rq-psn", val
);
222 pr_out("rq-psn %u ", val
);
225 static void print_sqpsn(struct rd
*rd
, uint32_t val
)
228 jsonw_uint_field(rd
->jw
, "sq-psn", val
);
230 pr_out("sq-psn %u ", val
);
233 static void print_pathmig(struct rd
*rd
, uint32_t val
,
234 struct nlattr
**nla_line
)
236 if (!nla_line
[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
])
240 jsonw_string_field(rd
->jw
,
242 path_mig_to_str(val
));
244 pr_out("path-mig-state %s ", path_mig_to_str(val
));
247 static void print_pid(struct rd
*rd
, uint32_t val
)
250 jsonw_uint_field(rd
->jw
, "pid", val
);
252 pr_out("pid %u ", val
);
255 static void print_comm(struct rd
*rd
, const char *str
,
256 struct nlattr
**nla_line
)
260 if (rd
->json_output
) {
261 /* Don't beatify output in JSON format */
262 jsonw_string_field(rd
->jw
, "comm", str
);
266 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
267 snprintf(tmp
, sizeof(tmp
), "%s", str
);
269 snprintf(tmp
, sizeof(tmp
), "[%s]", str
);
271 pr_out("comm %s ", tmp
);
274 static void print_dev(struct rd
*rd
, uint32_t idx
, const char *name
)
276 if (rd
->json_output
) {
277 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
278 jsonw_string_field(rd
->jw
, "ifname", name
);
280 pr_out("dev %s ", name
);
284 static void print_link(struct rd
*rd
, uint32_t idx
, const char *name
,
285 uint32_t port
, struct nlattr
**nla_line
)
287 if (rd
->json_output
) {
288 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
290 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
291 jsonw_uint_field(rd
->jw
, "port", port
);
293 jsonw_string_field(rd
->jw
, "ifname", name
);
295 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
296 pr_out("link %s/%u ", name
, port
);
298 pr_out("link %s/- ", name
);
302 static char *get_task_name(uint32_t pid
)
307 if (asprintf(&comm
, "/proc/%d/comm", pid
) < 0)
310 f
= fopen(comm
, "r");
315 if (fscanf(f
, "%ms\n", &comm
) != 1)
323 static int res_qp_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
325 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
326 struct nlattr
*nla_table
, *nla_entry
;
327 struct rd
*rd
= data
;
331 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
332 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
333 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
334 !tb
[RDMA_NLDEV_ATTR_RES_QP
])
337 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
338 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
339 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_QP
];
341 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
342 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
343 uint32_t lqpn
, rqpn
= 0, rq_psn
= 0, sq_psn
;
344 uint8_t type
, state
, path_mig_state
= 0;
345 uint32_t port
= 0, pid
= 0;
349 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
350 if (err
!= MNL_CB_OK
)
353 if (!nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
] ||
354 !nla_line
[RDMA_NLDEV_ATTR_RES_SQ_PSN
] ||
355 !nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
] ||
356 !nla_line
[RDMA_NLDEV_ATTR_RES_STATE
] ||
357 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
358 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
362 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
363 port
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
365 if (port
!= rd
->port_idx
)
368 lqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
369 if (rd_check_is_filtered(rd
, "lqpn", lqpn
))
372 if (nla_line
[RDMA_NLDEV_ATTR_RES_RQPN
]) {
373 rqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_RQPN
]);
374 if (rd_check_is_filtered(rd
, "rqpn", rqpn
))
377 if (rd_check_is_key_exist(rd
, "rqpn"))
381 if (nla_line
[RDMA_NLDEV_ATTR_RES_RQ_PSN
]) {
382 rq_psn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_RQ_PSN
]);
383 if (rd_check_is_filtered(rd
, "rq-psn", rq_psn
))
386 if (rd_check_is_key_exist(rd
, "rq-psn"))
390 sq_psn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_SQ_PSN
]);
391 if (rd_check_is_filtered(rd
, "sq-psn", sq_psn
))
394 if (nla_line
[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
]) {
395 path_mig_state
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
]);
396 if (rd_check_is_string_filtered(rd
, "path-mig-state", path_mig_to_str(path_mig_state
)))
399 if (rd_check_is_key_exist(rd
, "path-mig-state"))
403 type
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]);
404 if (rd_check_is_string_filtered(rd
, "type", qp_types_to_str(type
)))
407 state
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_STATE
]);
408 if (rd_check_is_string_filtered(rd
, "state", qp_states_to_str(state
)))
411 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
412 pid
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
413 comm
= get_task_name(pid
);
416 if (rd_check_is_filtered(rd
, "pid", pid
)) {
421 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
422 /* discard const from mnl_attr_get_str */
423 comm
= (char *)mnl_attr_get_str(nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
426 jsonw_start_array(rd
->jw
);
428 print_link(rd
, idx
, name
, port
, nla_line
);
430 print_lqpn(rd
, lqpn
);
431 print_rqpn(rd
, rqpn
, nla_line
);
433 print_type(rd
, type
);
434 print_state(rd
, state
);
436 print_rqpsn(rd
, rq_psn
, nla_line
);
437 print_sqpsn(rd
, sq_psn
);
439 print_pathmig(rd
, path_mig_state
, nla_line
);
441 print_comm(rd
, comm
, nla_line
);
443 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
446 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
452 static void print_qp_type(struct rd
*rd
, uint32_t val
)
455 jsonw_string_field(rd
->jw
, "qp-type",
456 qp_types_to_str(val
));
458 pr_out("qp-type %s ", qp_types_to_str(val
));
461 static const char *cm_id_state_to_str(uint8_t idx
)
463 static const char * const cm_id_states_str
[] = {
464 "IDLE", "ADDR_QUERY", "ADDR_RESOLVED", "ROUTE_QUERY",
465 "ROUTE_RESOLVED", "CONNECT", "DISCONNECT", "ADDR_BOUND",
466 "LISTEN", "DEVICE_REMOVAL", "DESTROYING" };
468 if (idx
< ARRAY_SIZE(cm_id_states_str
))
469 return cm_id_states_str
[idx
];
473 static const char *cm_id_ps_to_str(uint32_t ps
)
489 static void print_cm_id_state(struct rd
*rd
, uint8_t state
)
491 if (rd
->json_output
) {
492 jsonw_string_field(rd
->jw
, "state", cm_id_state_to_str(state
));
495 pr_out("state %s ", cm_id_state_to_str(state
));
498 static void print_ps(struct rd
*rd
, uint32_t ps
)
500 if (rd
->json_output
) {
501 jsonw_string_field(rd
->jw
, "ps", cm_id_ps_to_str(ps
));
504 pr_out("ps %s ", cm_id_ps_to_str(ps
));
507 static void print_ipaddr(struct rd
*rd
, const char *key
, char *addrstr
,
510 if (rd
->json_output
) {
511 int name_size
= INET6_ADDRSTRLEN
+strlen(":65535");
512 char json_name
[name_size
];
514 snprintf(json_name
, name_size
, "%s:%u", addrstr
, port
);
515 jsonw_string_field(rd
->jw
, key
, json_name
);
518 pr_out("%s %s:%u ", key
, addrstr
, port
);
521 static int ss_ntop(struct nlattr
*nla_line
, char *addr_str
, uint16_t *port
)
523 struct __kernel_sockaddr_storage
*addr
;
525 addr
= (struct __kernel_sockaddr_storage
*)
526 mnl_attr_get_payload(nla_line
);
527 switch (addr
->ss_family
) {
529 struct sockaddr_in
*sin
= (struct sockaddr_in
*)addr
;
531 if (!inet_ntop(AF_INET
, (const void *)&sin
->sin_addr
, addr_str
,
534 *port
= ntohs(sin
->sin_port
);
538 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)addr
;
540 if (!inet_ntop(AF_INET6
, (const void *)&sin6
->sin6_addr
,
541 addr_str
, INET6_ADDRSTRLEN
))
543 *port
= ntohs(sin6
->sin6_port
);
552 static void print_key(struct rd
*rd
, const char *name
, uint64_t val
)
555 jsonw_xint_field(rd
->jw
, name
, val
);
557 pr_out("%s 0x%" PRIx64
" ", name
, val
);
560 static void res_print_uint(struct rd
*rd
, const char *name
, uint64_t val
)
563 jsonw_uint_field(rd
->jw
, name
, val
);
565 pr_out("%s %" PRIu64
" ", name
, val
);
568 static int res_cm_id_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
570 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
571 struct nlattr
*nla_table
, *nla_entry
;
572 struct rd
*rd
= data
;
576 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
577 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
578 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
579 !tb
[RDMA_NLDEV_ATTR_RES_CM_ID
])
582 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
583 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
584 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_CM_ID
];
585 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
586 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
587 char src_addr_str
[INET6_ADDRSTRLEN
];
588 char dst_addr_str
[INET6_ADDRSTRLEN
];
589 uint16_t src_port
, dst_port
;
590 uint32_t port
= 0, pid
= 0;
591 uint8_t type
= 0, state
;
592 uint32_t lqpn
= 0, ps
;
597 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
598 if (err
!= MNL_CB_OK
)
601 if (!nla_line
[RDMA_NLDEV_ATTR_RES_STATE
] ||
602 !nla_line
[RDMA_NLDEV_ATTR_RES_PS
] ||
603 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
604 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
608 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
609 port
= mnl_attr_get_u32(
610 nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
612 if (port
&& port
!= rd
->port_idx
)
615 if (nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]) {
616 lqpn
= mnl_attr_get_u32(
617 nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
618 if (rd_check_is_filtered(rd
, "lqpn", lqpn
))
621 if (nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]) {
622 type
= mnl_attr_get_u8(
623 nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]);
624 if (rd_check_is_string_filtered(rd
, "qp-type",
625 qp_types_to_str(type
)))
629 ps
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PS
]);
630 if (rd_check_is_string_filtered(rd
, "ps", cm_id_ps_to_str(ps
)))
633 state
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_STATE
]);
634 if (rd_check_is_string_filtered(rd
, "state",
635 cm_id_state_to_str(state
)))
638 if (nla_line
[RDMA_NLDEV_ATTR_RES_SRC_ADDR
]) {
639 if (ss_ntop(nla_line
[RDMA_NLDEV_ATTR_RES_SRC_ADDR
],
640 src_addr_str
, &src_port
))
642 if (rd_check_is_string_filtered(rd
, "src-addr",
645 if (rd_check_is_filtered(rd
, "src-port", src_port
))
649 if (nla_line
[RDMA_NLDEV_ATTR_RES_DST_ADDR
]) {
650 if (ss_ntop(nla_line
[RDMA_NLDEV_ATTR_RES_DST_ADDR
],
651 dst_addr_str
, &dst_port
))
653 if (rd_check_is_string_filtered(rd
, "dst-addr",
656 if (rd_check_is_filtered(rd
, "dst-port", dst_port
))
660 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
661 pid
= mnl_attr_get_u32(
662 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
663 comm
= get_task_name(pid
);
666 if (rd_check_is_filtered(rd
, "pid", pid
)) {
671 if (nla_line
[RDMA_NLDEV_ATTR_RES_CM_IDN
])
672 cm_idn
= mnl_attr_get_u32(
673 nla_line
[RDMA_NLDEV_ATTR_RES_CM_IDN
]);
674 if (rd_check_is_filtered(rd
, "cm-idn", cm_idn
))
677 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]) {
678 /* discard const from mnl_attr_get_str */
679 comm
= (char *)mnl_attr_get_str(
680 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
684 jsonw_start_array(rd
->jw
);
686 print_link(rd
, idx
, name
, port
, nla_line
);
687 if (nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
688 print_lqpn(rd
, lqpn
);
689 if (nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
])
690 print_qp_type(rd
, type
);
691 print_cm_id_state(rd
, state
);
694 print_comm(rd
, comm
, nla_line
);
695 if (nla_line
[RDMA_NLDEV_ATTR_RES_CM_IDN
])
696 res_print_uint(rd
, "cm-idn", cm_idn
);
698 if (nla_line
[RDMA_NLDEV_ATTR_RES_SRC_ADDR
])
699 print_ipaddr(rd
, "src-addr", src_addr_str
, src_port
);
700 if (nla_line
[RDMA_NLDEV_ATTR_RES_DST_ADDR
])
701 print_ipaddr(rd
, "dst-addr", dst_addr_str
, dst_port
);
703 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
706 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
712 static void print_cqe(struct rd
*rd
, uint32_t val
)
715 jsonw_uint_field(rd
->jw
, "cqe", val
);
717 pr_out("cqe %u ", val
);
720 static void print_users(struct rd
*rd
, uint64_t val
)
723 jsonw_uint_field(rd
->jw
, "users", val
);
725 pr_out("users %" PRIu64
" ", val
);
728 static const char *poll_ctx_to_str(uint8_t idx
)
730 static const char * const cm_id_states_str
[] = {
731 "DIRECT", "SOFTIRQ", "WORKQUEUE", "UNBOUND_WORKQUEUE"};
733 if (idx
< ARRAY_SIZE(cm_id_states_str
))
734 return cm_id_states_str
[idx
];
738 static void print_poll_ctx(struct rd
*rd
, uint8_t poll_ctx
)
740 if (rd
->json_output
) {
741 jsonw_string_field(rd
->jw
, "poll-ctx",
742 poll_ctx_to_str(poll_ctx
));
745 pr_out("poll-ctx %s ", poll_ctx_to_str(poll_ctx
));
748 static int res_cq_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
750 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
751 struct nlattr
*nla_table
, *nla_entry
;
752 struct rd
*rd
= data
;
756 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
757 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
758 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
759 !tb
[RDMA_NLDEV_ATTR_RES_CQ
])
762 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
763 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
764 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_CQ
];
766 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
767 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
770 uint8_t poll_ctx
= 0;
776 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
777 if (err
!= MNL_CB_OK
)
780 if (!nla_line
[RDMA_NLDEV_ATTR_RES_CQE
] ||
781 !nla_line
[RDMA_NLDEV_ATTR_RES_USECNT
] ||
782 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
783 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
787 cqe
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_CQE
]);
789 users
= mnl_attr_get_u64(nla_line
[RDMA_NLDEV_ATTR_RES_USECNT
]);
790 if (rd_check_is_filtered(rd
, "users", users
))
793 if (nla_line
[RDMA_NLDEV_ATTR_RES_POLL_CTX
]) {
794 poll_ctx
= mnl_attr_get_u8(
795 nla_line
[RDMA_NLDEV_ATTR_RES_POLL_CTX
]);
796 if (rd_check_is_string_filtered(rd
, "poll-ctx",
797 poll_ctx_to_str(poll_ctx
)))
801 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
802 pid
= mnl_attr_get_u32(
803 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
804 comm
= get_task_name(pid
);
807 if (rd_check_is_filtered(rd
, "pid", pid
)) {
812 if (nla_line
[RDMA_NLDEV_ATTR_RES_CQN
])
813 cqn
= mnl_attr_get_u32(
814 nla_line
[RDMA_NLDEV_ATTR_RES_CQN
]);
815 if (rd_check_is_filtered(rd
, "cqn", cqn
))
818 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
819 /* discard const from mnl_attr_get_str */
820 comm
= (char *)mnl_attr_get_str(
821 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
824 jsonw_start_array(rd
->jw
);
826 print_dev(rd
, idx
, name
);
828 print_users(rd
, users
);
829 if (nla_line
[RDMA_NLDEV_ATTR_RES_POLL_CTX
])
830 print_poll_ctx(rd
, poll_ctx
);
832 print_comm(rd
, comm
, nla_line
);
834 if (nla_line
[RDMA_NLDEV_ATTR_RES_CQN
])
835 res_print_uint(rd
, "cqn", cqn
);
837 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
840 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
846 static int res_mr_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
848 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
849 struct nlattr
*nla_table
, *nla_entry
;
850 struct rd
*rd
= data
;
854 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
855 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
856 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
857 !tb
[RDMA_NLDEV_ATTR_RES_MR
])
860 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
861 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
862 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_MR
];
864 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
865 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
866 uint32_t rkey
= 0, lkey
= 0;
867 uint64_t iova
= 0, mrlen
;
873 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
874 if (err
!= MNL_CB_OK
)
877 if (!nla_line
[RDMA_NLDEV_ATTR_RES_MRLEN
] ||
878 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
879 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
883 if (nla_line
[RDMA_NLDEV_ATTR_RES_RKEY
])
884 rkey
= mnl_attr_get_u32(
885 nla_line
[RDMA_NLDEV_ATTR_RES_RKEY
]);
886 if (nla_line
[RDMA_NLDEV_ATTR_RES_LKEY
])
887 lkey
= mnl_attr_get_u32(
888 nla_line
[RDMA_NLDEV_ATTR_RES_LKEY
]);
889 if (nla_line
[RDMA_NLDEV_ATTR_RES_IOVA
])
890 iova
= mnl_attr_get_u64(
891 nla_line
[RDMA_NLDEV_ATTR_RES_IOVA
]);
893 mrlen
= mnl_attr_get_u64(nla_line
[RDMA_NLDEV_ATTR_RES_MRLEN
]);
894 if (rd_check_is_filtered(rd
, "mrlen", mrlen
))
897 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
898 pid
= mnl_attr_get_u32(
899 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
900 comm
= get_task_name(pid
);
903 if (rd_check_is_filtered(rd
, "pid", pid
)) {
908 if (nla_line
[RDMA_NLDEV_ATTR_RES_MRN
])
909 mrn
= mnl_attr_get_u32(
910 nla_line
[RDMA_NLDEV_ATTR_RES_MRN
]);
911 if (rd_check_is_filtered(rd
, "mrn", mrn
))
914 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
915 /* discard const from mnl_attr_get_str */
916 comm
= (char *)mnl_attr_get_str(
917 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
920 jsonw_start_array(rd
->jw
);
922 print_dev(rd
, idx
, name
);
923 if (nla_line
[RDMA_NLDEV_ATTR_RES_RKEY
])
924 print_key(rd
, "rkey", rkey
);
925 if (nla_line
[RDMA_NLDEV_ATTR_RES_LKEY
])
926 print_key(rd
, "lkey", lkey
);
927 if (nla_line
[RDMA_NLDEV_ATTR_RES_IOVA
])
928 print_key(rd
, "iova", iova
);
929 res_print_uint(rd
, "mrlen", mrlen
);
931 print_comm(rd
, comm
, nla_line
);
933 if (nla_line
[RDMA_NLDEV_ATTR_RES_MRN
])
934 res_print_uint(rd
, "mrn", mrn
);
936 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
939 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
945 static int res_pd_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
947 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
948 struct nlattr
*nla_table
, *nla_entry
;
949 struct rd
*rd
= data
;
953 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
954 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
955 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
956 !tb
[RDMA_NLDEV_ATTR_RES_PD
])
959 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
960 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
961 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_PD
];
963 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
964 uint32_t local_dma_lkey
= 0, unsafe_global_rkey
= 0;
965 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
972 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
973 if (err
!= MNL_CB_OK
)
976 if (!nla_line
[RDMA_NLDEV_ATTR_RES_USECNT
] ||
977 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
978 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
982 if (nla_line
[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY
])
983 local_dma_lkey
= mnl_attr_get_u32(
984 nla_line
[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY
]);
986 users
= mnl_attr_get_u64(nla_line
[RDMA_NLDEV_ATTR_RES_USECNT
]);
987 if (rd_check_is_filtered(rd
, "users", users
))
990 if (nla_line
[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY
])
991 unsafe_global_rkey
= mnl_attr_get_u32(
992 nla_line
[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY
]);
994 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
995 pid
= mnl_attr_get_u32(
996 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
997 comm
= get_task_name(pid
);
1000 if (rd_check_is_filtered(rd
, "pid", pid
))
1003 if (nla_line
[RDMA_NLDEV_ATTR_RES_PDN
])
1004 pdn
= mnl_attr_get_u32(
1005 nla_line
[RDMA_NLDEV_ATTR_RES_PDN
]);
1006 if (rd_check_is_filtered(rd
, "pdn", pdn
))
1009 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
1010 /* discard const from mnl_attr_get_str */
1011 comm
= (char *)mnl_attr_get_str(
1012 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
1014 if (rd
->json_output
)
1015 jsonw_start_array(rd
->jw
);
1017 print_dev(rd
, idx
, name
);
1018 if (nla_line
[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY
])
1019 print_key(rd
, "local_dma_lkey", local_dma_lkey
);
1020 print_users(rd
, users
);
1021 if (nla_line
[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY
])
1022 print_key(rd
, "unsafe_global_rkey", unsafe_global_rkey
);
1024 print_comm(rd
, comm
, nla_line
);
1026 if (nla_line
[RDMA_NLDEV_ATTR_RES_PDN
])
1027 res_print_uint(rd
, "pdn", pdn
);
1029 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
1032 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
1038 RES_FUNC(res_no_args
, RDMA_NLDEV_CMD_RES_GET
, NULL
, true);
1041 filters qp_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {{ .name
= "link",
1042 .is_number
= false },
1044 .is_number
= true },
1046 .is_number
= true },
1048 .is_number
= true },
1050 .is_number
= true },
1052 .is_number
= true },
1054 .is_number
= false },
1055 { .name
= "path-mig-state",
1056 .is_number
= false },
1058 .is_number
= false } };
1060 RES_FUNC(res_qp
, RDMA_NLDEV_CMD_RES_QP_GET
, qp_valid_filters
, false);
1063 struct filters cm_id_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
1064 { .name
= "link", .is_number
= false },
1065 { .name
= "lqpn", .is_number
= true },
1066 { .name
= "qp-type", .is_number
= false },
1067 { .name
= "state", .is_number
= false },
1068 { .name
= "ps", .is_number
= false },
1069 { .name
= "dev-type", .is_number
= false },
1070 { .name
= "transport-type", .is_number
= false },
1071 { .name
= "pid", .is_number
= true },
1072 { .name
= "src-addr", .is_number
= false },
1073 { .name
= "src-port", .is_number
= true },
1074 { .name
= "dst-addr", .is_number
= false },
1075 { .name
= "dst-port", .is_number
= true },
1076 { .name
= "cm-idn", .is_number
= true }
1079 RES_FUNC(res_cm_id
, RDMA_NLDEV_CMD_RES_CM_ID_GET
, cm_id_valid_filters
, false);
1082 struct filters cq_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
1083 { .name
= "dev", .is_number
= false },
1084 { .name
= "users", .is_number
= true },
1085 { .name
= "poll-ctx", .is_number
= false },
1086 { .name
= "pid", .is_number
= true },
1087 { .name
= "cqn", .is_number
= true }
1090 RES_FUNC(res_cq
, RDMA_NLDEV_CMD_RES_CQ_GET
, cq_valid_filters
, true);
1093 struct filters mr_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
1094 { .name
= "dev", .is_number
= false },
1095 { .name
= "rkey", .is_number
= true },
1096 { .name
= "lkey", .is_number
= true },
1097 { .name
= "mrlen", .is_number
= true },
1098 { .name
= "pid", .is_number
= true },
1099 { .name
= "mrn", .is_number
= true }
1102 RES_FUNC(res_mr
, RDMA_NLDEV_CMD_RES_MR_GET
, mr_valid_filters
, true);
1105 struct filters pd_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
1106 { .name
= "dev", .is_number
= false },
1107 { .name
= "users", .is_number
= true },
1108 { .name
= "pid", .is_number
= true },
1109 { .name
= "pdn", .is_number
= true }
1112 RES_FUNC(res_pd
, RDMA_NLDEV_CMD_RES_PD_GET
, pd_valid_filters
, true);
1114 static int res_show(struct rd
*rd
)
1116 const struct rd_cmd cmds
[] = {
1117 { NULL
, res_no_args
},
1119 { "cm_id", res_cm_id
},
1127 * Special case to support "rdma res show DEV_NAME"
1129 if (rd_argc(rd
) == 1 && dev_map_lookup(rd
, false))
1130 return rd_exec_dev(rd
, _res_no_args
);
1132 return rd_exec_cmd(rd
, cmds
, "parameter");
1135 int cmd_res(struct rd
*rd
)
1137 const struct rd_cmd cmds
[] = {
1139 { "show", res_show
},
1140 { "list", res_show
},
1141 { "help", res_help
},
1145 return rd_exec_cmd(rd
, cmds
, "resource command");