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]\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");
29 static int res_print_summary(struct rd
*rd
, struct nlattr
**tb
)
31 struct nlattr
*nla_table
= tb
[RDMA_NLDEV_ATTR_RES_SUMMARY
];
32 struct nlattr
*nla_entry
;
37 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
38 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
41 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
45 if (!nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME
] ||
46 !nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR
]) {
50 name
= mnl_attr_get_str(nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME
]);
51 curr
= mnl_attr_get_u64(nla_line
[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR
]);
52 if (rd
->json_output
) {
53 snprintf(json_name
, 32, "%s", name
);
54 jsonw_lluint_field(rd
->jw
, json_name
, curr
);
56 pr_out("%s %"PRId64
" ", name
, curr
);
62 static int res_no_args_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
64 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
69 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
70 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
71 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
72 !tb
[RDMA_NLDEV_ATTR_RES_SUMMARY
])
75 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
76 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
77 if (rd
->json_output
) {
78 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
79 jsonw_string_field(rd
->jw
, "ifname", name
);
81 pr_out("%u: %s: ", idx
, name
);
84 res_print_summary(rd
, tb
);
91 static int _res_send_msg(struct rd
*rd
, uint32_t command
, mnl_cb_t callback
)
93 uint32_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
97 if (command
!= RDMA_NLDEV_CMD_RES_GET
)
100 rd_prepare_msg(rd
, command
, &seq
, flags
);
101 mnl_attr_put_u32(rd
->nlh
, RDMA_NLDEV_ATTR_DEV_INDEX
, rd
->dev_idx
);
103 mnl_attr_put_u32(rd
->nlh
,
104 RDMA_NLDEV_ATTR_PORT_INDEX
, rd
->port_idx
);
106 ret
= rd_send_msg(rd
);
111 jsonw_start_object(rd
->jw
);
112 ret
= rd_recv_msg(rd
, callback
, rd
, seq
);
114 jsonw_end_object(rd
->jw
);
118 #define RES_FUNC(name, command, valid_filters, strict_port) \
119 static int _##name(struct rd *rd)\
121 return _res_send_msg(rd, command, name##_parse_cb); \
123 static int name(struct rd *rd) \
125 int ret = rd_build_filter(rd, valid_filters); \
128 if ((uintptr_t)valid_filters != (uintptr_t)NULL) { \
129 ret = rd_set_arg_to_devname(rd); \
134 return rd_exec_dev(rd, _##name); \
136 return rd_exec_link(rd, _##name, strict_port); \
139 static const char *path_mig_to_str(uint8_t idx
)
141 static const char * const path_mig_str
[] = { "MIGRATED",
144 if (idx
< ARRAY_SIZE(path_mig_str
))
145 return path_mig_str
[idx
];
149 static const char *qp_states_to_str(uint8_t idx
)
151 static const char * const qp_states_str
[] = { "RESET", "INIT",
155 if (idx
< ARRAY_SIZE(qp_states_str
))
156 return qp_states_str
[idx
];
160 static const char *qp_types_to_str(uint8_t idx
)
162 static const char * const qp_types_str
[] = { "SMI", "GSI", "RC",
163 "UC", "UD", "RAW_IPV6",
165 "UNKNOWN", "RAW_PACKET",
166 "XRC_INI", "XRC_TGT" };
168 if (idx
< ARRAY_SIZE(qp_types_str
))
169 return qp_types_str
[idx
];
173 static void print_lqpn(struct rd
*rd
, uint32_t val
)
176 jsonw_uint_field(rd
->jw
, "lqpn", val
);
178 pr_out("lqpn %u ", val
);
181 static void print_rqpn(struct rd
*rd
, uint32_t val
, struct nlattr
**nla_line
)
183 if (!nla_line
[RDMA_NLDEV_ATTR_RES_RQPN
])
187 jsonw_uint_field(rd
->jw
, "rqpn", val
);
189 pr_out("rqpn %u ", val
);
192 static void print_type(struct rd
*rd
, uint32_t val
)
195 jsonw_string_field(rd
->jw
, "type",
196 qp_types_to_str(val
));
198 pr_out("type %s ", qp_types_to_str(val
));
201 static void print_state(struct rd
*rd
, uint32_t val
)
204 jsonw_string_field(rd
->jw
, "state",
205 qp_states_to_str(val
));
207 pr_out("state %s ", qp_states_to_str(val
));
210 static void print_rqpsn(struct rd
*rd
, uint32_t val
, struct nlattr
**nla_line
)
212 if (!nla_line
[RDMA_NLDEV_ATTR_RES_RQ_PSN
])
216 jsonw_uint_field(rd
->jw
, "rq-psn", val
);
218 pr_out("rq-psn %u ", val
);
221 static void print_sqpsn(struct rd
*rd
, uint32_t val
)
224 jsonw_uint_field(rd
->jw
, "sq-psn", val
);
226 pr_out("sq-psn %u ", val
);
229 static void print_pathmig(struct rd
*rd
, uint32_t val
,
230 struct nlattr
**nla_line
)
232 if (!nla_line
[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
])
236 jsonw_string_field(rd
->jw
,
238 path_mig_to_str(val
));
240 pr_out("path-mig-state %s ", path_mig_to_str(val
));
243 static void print_pid(struct rd
*rd
, uint32_t val
)
246 jsonw_uint_field(rd
->jw
, "pid", val
);
248 pr_out("pid %u ", val
);
251 static void print_comm(struct rd
*rd
, const char *str
,
252 struct nlattr
**nla_line
)
256 if (rd
->json_output
) {
257 /* Don't beatify output in JSON format */
258 jsonw_string_field(rd
->jw
, "comm", str
);
262 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
263 snprintf(tmp
, sizeof(tmp
), "%s", str
);
265 snprintf(tmp
, sizeof(tmp
), "[%s]", str
);
267 pr_out("comm %s ", tmp
);
270 static void print_dev(struct rd
*rd
, uint32_t idx
, const char *name
)
272 if (rd
->json_output
) {
273 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
274 jsonw_string_field(rd
->jw
, "ifname", name
);
276 pr_out("dev %s ", name
);
280 static void print_link(struct rd
*rd
, uint32_t idx
, const char *name
,
281 uint32_t port
, struct nlattr
**nla_line
)
283 if (rd
->json_output
) {
284 jsonw_uint_field(rd
->jw
, "ifindex", idx
);
286 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
287 jsonw_uint_field(rd
->jw
, "port", port
);
289 jsonw_string_field(rd
->jw
, "ifname", name
);
291 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
292 pr_out("link %s/%u ", name
, port
);
294 pr_out("link %s/- ", name
);
298 static char *get_task_name(uint32_t pid
)
303 if (asprintf(&comm
, "/proc/%d/comm", pid
) < 0)
306 f
= fopen(comm
, "r");
311 if (fscanf(f
, "%ms\n", &comm
) != 1)
319 static int res_qp_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
321 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
322 struct nlattr
*nla_table
, *nla_entry
;
323 struct rd
*rd
= data
;
327 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
328 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
329 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
330 !tb
[RDMA_NLDEV_ATTR_RES_QP
])
333 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
334 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
335 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_QP
];
337 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
338 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
339 uint32_t lqpn
, rqpn
= 0, rq_psn
= 0, sq_psn
;
340 uint8_t type
, state
, path_mig_state
= 0;
341 uint32_t port
= 0, pid
= 0;
345 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
346 if (err
!= MNL_CB_OK
)
349 if (!nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
] ||
350 !nla_line
[RDMA_NLDEV_ATTR_RES_SQ_PSN
] ||
351 !nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
] ||
352 !nla_line
[RDMA_NLDEV_ATTR_RES_STATE
] ||
353 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
354 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
358 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
359 port
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
361 if (port
!= rd
->port_idx
)
364 lqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
365 if (rd_check_is_filtered(rd
, "lqpn", lqpn
))
368 if (nla_line
[RDMA_NLDEV_ATTR_RES_RQPN
]) {
369 rqpn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_RQPN
]);
370 if (rd_check_is_filtered(rd
, "rqpn", rqpn
))
373 if (rd_check_is_key_exist(rd
, "rqpn"))
377 if (nla_line
[RDMA_NLDEV_ATTR_RES_RQ_PSN
]) {
378 rq_psn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_RQ_PSN
]);
379 if (rd_check_is_filtered(rd
, "rq-psn", rq_psn
))
382 if (rd_check_is_key_exist(rd
, "rq-psn"))
386 sq_psn
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_SQ_PSN
]);
387 if (rd_check_is_filtered(rd
, "sq-psn", sq_psn
))
390 if (nla_line
[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
]) {
391 path_mig_state
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
]);
392 if (rd_check_is_string_filtered(rd
, "path-mig-state", path_mig_to_str(path_mig_state
)))
395 if (rd_check_is_key_exist(rd
, "path-mig-state"))
399 type
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]);
400 if (rd_check_is_string_filtered(rd
, "type", qp_types_to_str(type
)))
403 state
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_STATE
]);
404 if (rd_check_is_string_filtered(rd
, "state", qp_states_to_str(state
)))
407 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
408 pid
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
409 comm
= get_task_name(pid
);
412 if (rd_check_is_filtered(rd
, "pid", pid
)) {
417 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
418 /* discard const from mnl_attr_get_str */
419 comm
= (char *)mnl_attr_get_str(nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
422 jsonw_start_array(rd
->jw
);
424 print_link(rd
, idx
, name
, port
, nla_line
);
426 print_lqpn(rd
, lqpn
);
427 print_rqpn(rd
, rqpn
, nla_line
);
429 print_type(rd
, type
);
430 print_state(rd
, state
);
432 print_rqpsn(rd
, rq_psn
, nla_line
);
433 print_sqpsn(rd
, sq_psn
);
435 print_pathmig(rd
, path_mig_state
, nla_line
);
437 print_comm(rd
, comm
, nla_line
);
439 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
442 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
448 static void print_qp_type(struct rd
*rd
, uint32_t val
)
451 jsonw_string_field(rd
->jw
, "qp-type",
452 qp_types_to_str(val
));
454 pr_out("qp-type %s ", qp_types_to_str(val
));
457 static const char *cm_id_state_to_str(uint8_t idx
)
459 static const char * const cm_id_states_str
[] = {
460 "IDLE", "ADDR_QUERY", "ADDR_RESOLVED", "ROUTE_QUERY",
461 "ROUTE_RESOLVED", "CONNECT", "DISCONNECT", "ADDR_BOUND",
462 "LISTEN", "DEVICE_REMOVAL", "DESTROYING" };
464 if (idx
< ARRAY_SIZE(cm_id_states_str
))
465 return cm_id_states_str
[idx
];
469 static const char *cm_id_ps_to_str(uint32_t ps
)
485 static void print_cm_id_state(struct rd
*rd
, uint8_t state
)
487 if (rd
->json_output
) {
488 jsonw_string_field(rd
->jw
, "state", cm_id_state_to_str(state
));
491 pr_out("state %s ", cm_id_state_to_str(state
));
494 static void print_ps(struct rd
*rd
, uint32_t ps
)
496 if (rd
->json_output
) {
497 jsonw_string_field(rd
->jw
, "ps", cm_id_ps_to_str(ps
));
500 pr_out("ps %s ", cm_id_ps_to_str(ps
));
503 static void print_ipaddr(struct rd
*rd
, const char *key
, char *addrstr
,
506 if (rd
->json_output
) {
507 int name_size
= INET6_ADDRSTRLEN
+strlen(":65535");
508 char json_name
[name_size
];
510 snprintf(json_name
, name_size
, "%s:%u", addrstr
, port
);
511 jsonw_string_field(rd
->jw
, key
, json_name
);
514 pr_out("%s %s:%u ", key
, addrstr
, port
);
517 static int ss_ntop(struct nlattr
*nla_line
, char *addr_str
, uint16_t *port
)
519 struct __kernel_sockaddr_storage
*addr
;
521 addr
= (struct __kernel_sockaddr_storage
*)
522 mnl_attr_get_payload(nla_line
);
523 switch (addr
->ss_family
) {
525 struct sockaddr_in
*sin
= (struct sockaddr_in
*)addr
;
527 if (!inet_ntop(AF_INET
, (const void *)&sin
->sin_addr
, addr_str
,
530 *port
= ntohs(sin
->sin_port
);
534 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)addr
;
536 if (!inet_ntop(AF_INET6
, (const void *)&sin6
->sin6_addr
,
537 addr_str
, INET6_ADDRSTRLEN
))
539 *port
= ntohs(sin6
->sin6_port
);
548 static int res_cm_id_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
550 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
551 struct nlattr
*nla_table
, *nla_entry
;
552 struct rd
*rd
= data
;
556 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
557 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
558 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
559 !tb
[RDMA_NLDEV_ATTR_RES_CM_ID
])
562 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
563 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
564 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_CM_ID
];
565 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
566 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
567 char src_addr_str
[INET6_ADDRSTRLEN
];
568 char dst_addr_str
[INET6_ADDRSTRLEN
];
569 uint16_t src_port
, dst_port
;
570 uint32_t port
= 0, pid
= 0;
571 uint8_t type
= 0, state
;
572 uint32_t lqpn
= 0, ps
;
576 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
577 if (err
!= MNL_CB_OK
)
580 if (!nla_line
[RDMA_NLDEV_ATTR_RES_STATE
] ||
581 !nla_line
[RDMA_NLDEV_ATTR_RES_PS
] ||
582 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
583 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
587 if (nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
])
588 port
= mnl_attr_get_u32(
589 nla_line
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
591 if (port
&& port
!= rd
->port_idx
)
594 if (nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]) {
595 lqpn
= mnl_attr_get_u32(
596 nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
]);
597 if (rd_check_is_filtered(rd
, "lqpn", lqpn
))
600 if (nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]) {
601 type
= mnl_attr_get_u8(
602 nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
]);
603 if (rd_check_is_string_filtered(rd
, "qp-type",
604 qp_types_to_str(type
)))
608 ps
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_PS
]);
609 if (rd_check_is_string_filtered(rd
, "ps", cm_id_ps_to_str(ps
)))
612 state
= mnl_attr_get_u8(nla_line
[RDMA_NLDEV_ATTR_RES_STATE
]);
613 if (rd_check_is_string_filtered(rd
, "state",
614 cm_id_state_to_str(state
)))
617 if (nla_line
[RDMA_NLDEV_ATTR_RES_SRC_ADDR
]) {
618 if (ss_ntop(nla_line
[RDMA_NLDEV_ATTR_RES_SRC_ADDR
],
619 src_addr_str
, &src_port
))
621 if (rd_check_is_string_filtered(rd
, "src-addr",
626 if (nla_line
[RDMA_NLDEV_ATTR_RES_DST_ADDR
]) {
627 if (ss_ntop(nla_line
[RDMA_NLDEV_ATTR_RES_DST_ADDR
],
628 dst_addr_str
, &dst_port
))
630 if (rd_check_is_string_filtered(rd
, "dst-addr",
635 if (rd_check_is_filtered(rd
, "src-port", src_port
))
638 if (rd_check_is_filtered(rd
, "dst-port", dst_port
))
641 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
642 pid
= mnl_attr_get_u32(
643 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
644 comm
= get_task_name(pid
);
647 if (rd_check_is_filtered(rd
, "pid", pid
)) {
652 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]) {
653 /* discard const from mnl_attr_get_str */
654 comm
= (char *)mnl_attr_get_str(
655 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
659 jsonw_start_array(rd
->jw
);
661 print_link(rd
, idx
, name
, port
, nla_line
);
662 if (nla_line
[RDMA_NLDEV_ATTR_RES_LQPN
])
663 print_lqpn(rd
, lqpn
);
664 if (nla_line
[RDMA_NLDEV_ATTR_RES_TYPE
])
665 print_qp_type(rd
, type
);
666 print_cm_id_state(rd
, state
);
669 print_comm(rd
, comm
, nla_line
);
671 if (nla_line
[RDMA_NLDEV_ATTR_RES_SRC_ADDR
])
672 print_ipaddr(rd
, "src-addr", src_addr_str
, src_port
);
673 if (nla_line
[RDMA_NLDEV_ATTR_RES_DST_ADDR
])
674 print_ipaddr(rd
, "dst-addr", dst_addr_str
, dst_port
);
676 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
679 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
685 static void print_cqe(struct rd
*rd
, uint32_t val
)
688 jsonw_uint_field(rd
->jw
, "cqe", val
);
690 pr_out("cqe %u ", val
);
693 static void print_users(struct rd
*rd
, uint64_t val
)
696 jsonw_uint_field(rd
->jw
, "users", val
);
698 pr_out("users %" PRIu64
" ", val
);
701 static const char *poll_ctx_to_str(uint8_t idx
)
703 static const char * const cm_id_states_str
[] = {
704 "DIRECT", "SOFTIRQ", "WORKQUEUE"};
706 if (idx
< ARRAY_SIZE(cm_id_states_str
))
707 return cm_id_states_str
[idx
];
711 static void print_poll_ctx(struct rd
*rd
, uint8_t poll_ctx
)
713 if (rd
->json_output
) {
714 jsonw_string_field(rd
->jw
, "poll-ctx",
715 poll_ctx_to_str(poll_ctx
));
718 pr_out("poll-ctx %s ", poll_ctx_to_str(poll_ctx
));
721 static int res_cq_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
723 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
724 struct nlattr
*nla_table
, *nla_entry
;
725 struct rd
*rd
= data
;
729 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
730 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
731 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
732 !tb
[RDMA_NLDEV_ATTR_RES_CQ
])
735 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
736 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
737 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_CQ
];
739 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
740 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
743 uint8_t poll_ctx
= 0;
748 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
749 if (err
!= MNL_CB_OK
)
752 if (!nla_line
[RDMA_NLDEV_ATTR_RES_CQE
] ||
753 !nla_line
[RDMA_NLDEV_ATTR_RES_USECNT
] ||
754 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
755 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
759 cqe
= mnl_attr_get_u32(nla_line
[RDMA_NLDEV_ATTR_RES_CQE
]);
761 users
= mnl_attr_get_u64(nla_line
[RDMA_NLDEV_ATTR_RES_USECNT
]);
762 if (rd_check_is_filtered(rd
, "users", users
))
765 if (nla_line
[RDMA_NLDEV_ATTR_RES_POLL_CTX
]) {
766 poll_ctx
= mnl_attr_get_u8(
767 nla_line
[RDMA_NLDEV_ATTR_RES_POLL_CTX
]);
768 if (rd_check_is_string_filtered(rd
, "poll-ctx",
769 poll_ctx_to_str(poll_ctx
)))
773 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
774 pid
= mnl_attr_get_u32(
775 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
776 comm
= get_task_name(pid
);
779 if (rd_check_is_filtered(rd
, "pid", pid
)) {
784 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
785 /* discard const from mnl_attr_get_str */
786 comm
= (char *)mnl_attr_get_str(
787 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
790 jsonw_start_array(rd
->jw
);
792 print_dev(rd
, idx
, name
);
794 print_users(rd
, users
);
795 if (nla_line
[RDMA_NLDEV_ATTR_RES_POLL_CTX
])
796 print_poll_ctx(rd
, poll_ctx
);
798 print_comm(rd
, comm
, nla_line
);
800 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
803 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
809 static void print_key(struct rd
*rd
, const char *name
, uint32_t val
)
812 jsonw_xint_field(rd
->jw
, name
, val
);
814 pr_out("%s 0x%x ", name
, val
);
817 static void print_iova(struct rd
*rd
, uint64_t val
)
820 jsonw_xint_field(rd
->jw
, "iova", val
);
822 pr_out("iova 0x%" PRIx64
" ", val
);
825 static void print_mrlen(struct rd
*rd
, uint64_t val
)
828 jsonw_uint_field(rd
->jw
, "mrlen", val
);
830 pr_out("mrlen %" PRIu64
" ", val
);
833 static int res_mr_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
835 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
836 struct nlattr
*nla_table
, *nla_entry
;
837 struct rd
*rd
= data
;
841 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
842 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
843 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
844 !tb
[RDMA_NLDEV_ATTR_RES_MR
])
847 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
848 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
849 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_MR
];
851 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
852 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
853 uint32_t rkey
= 0, lkey
= 0;
854 uint64_t iova
= 0, mrlen
;
859 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
860 if (err
!= MNL_CB_OK
)
863 if (!nla_line
[RDMA_NLDEV_ATTR_RES_MRLEN
] ||
864 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
865 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
869 if (nla_line
[RDMA_NLDEV_ATTR_RES_RKEY
])
870 rkey
= mnl_attr_get_u32(
871 nla_line
[RDMA_NLDEV_ATTR_RES_RKEY
]);
872 if (nla_line
[RDMA_NLDEV_ATTR_RES_LKEY
])
873 lkey
= mnl_attr_get_u32(
874 nla_line
[RDMA_NLDEV_ATTR_RES_LKEY
]);
875 if (nla_line
[RDMA_NLDEV_ATTR_RES_IOVA
])
876 iova
= mnl_attr_get_u64(
877 nla_line
[RDMA_NLDEV_ATTR_RES_IOVA
]);
879 mrlen
= mnl_attr_get_u64(nla_line
[RDMA_NLDEV_ATTR_RES_MRLEN
]);
880 if (rd_check_is_filtered(rd
, "mrlen", mrlen
))
883 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
884 pid
= mnl_attr_get_u32(
885 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
886 comm
= get_task_name(pid
);
889 if (rd_check_is_filtered(rd
, "pid", pid
)) {
894 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
895 /* discard const from mnl_attr_get_str */
896 comm
= (char *)mnl_attr_get_str(
897 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
900 jsonw_start_array(rd
->jw
);
902 print_dev(rd
, idx
, name
);
903 if (nla_line
[RDMA_NLDEV_ATTR_RES_RKEY
])
904 print_key(rd
, "rkey", rkey
);
905 if (nla_line
[RDMA_NLDEV_ATTR_RES_LKEY
])
906 print_key(rd
, "lkey", lkey
);
907 if (nla_line
[RDMA_NLDEV_ATTR_RES_IOVA
])
908 print_iova(rd
, iova
);
909 print_mrlen(rd
, mrlen
);
911 print_comm(rd
, comm
, nla_line
);
913 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
916 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
922 static int res_pd_parse_cb(const struct nlmsghdr
*nlh
, void *data
)
924 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
925 struct nlattr
*nla_table
, *nla_entry
;
926 struct rd
*rd
= data
;
930 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
931 if (!tb
[RDMA_NLDEV_ATTR_DEV_INDEX
] ||
932 !tb
[RDMA_NLDEV_ATTR_DEV_NAME
] ||
933 !tb
[RDMA_NLDEV_ATTR_RES_PD
])
936 name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
937 idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
938 nla_table
= tb
[RDMA_NLDEV_ATTR_RES_PD
];
940 mnl_attr_for_each_nested(nla_entry
, nla_table
) {
941 uint32_t local_dma_lkey
= 0, unsafe_global_rkey
= 0;
942 struct nlattr
*nla_line
[RDMA_NLDEV_ATTR_MAX
] = {};
948 err
= mnl_attr_parse_nested(nla_entry
, rd_attr_cb
, nla_line
);
949 if (err
!= MNL_CB_OK
)
952 if (!nla_line
[RDMA_NLDEV_ATTR_RES_USECNT
] ||
953 (!nla_line
[RDMA_NLDEV_ATTR_RES_PID
] &&
954 !nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])) {
958 if (nla_line
[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY
])
959 local_dma_lkey
= mnl_attr_get_u32(
960 nla_line
[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY
]);
962 users
= mnl_attr_get_u64(nla_line
[RDMA_NLDEV_ATTR_RES_USECNT
]);
963 if (rd_check_is_filtered(rd
, "users", users
))
966 if (nla_line
[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY
])
967 unsafe_global_rkey
= mnl_attr_get_u32(
968 nla_line
[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY
]);
970 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
]) {
971 pid
= mnl_attr_get_u32(
972 nla_line
[RDMA_NLDEV_ATTR_RES_PID
]);
973 comm
= get_task_name(pid
);
976 if (rd_check_is_filtered(rd
, "pid", pid
))
979 if (nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
])
980 /* discard const from mnl_attr_get_str */
981 comm
= (char *)mnl_attr_get_str(
982 nla_line
[RDMA_NLDEV_ATTR_RES_KERN_NAME
]);
985 jsonw_start_array(rd
->jw
);
987 print_dev(rd
, idx
, name
);
988 if (nla_line
[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY
])
989 print_key(rd
, "local_dma_lkey", local_dma_lkey
);
990 print_users(rd
, users
);
991 if (nla_line
[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY
])
992 print_key(rd
, "unsafe_global_rkey", unsafe_global_rkey
);
994 print_comm(rd
, comm
, nla_line
);
996 if (nla_line
[RDMA_NLDEV_ATTR_RES_PID
])
999 print_driver_table(rd
, nla_line
[RDMA_NLDEV_ATTR_DRIVER
]);
1005 RES_FUNC(res_no_args
, RDMA_NLDEV_CMD_RES_GET
, NULL
, true);
1008 filters qp_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {{ .name
= "link",
1009 .is_number
= false },
1011 .is_number
= true },
1013 .is_number
= true },
1015 .is_number
= true },
1017 .is_number
= true },
1019 .is_number
= true },
1021 .is_number
= false },
1022 { .name
= "path-mig-state",
1023 .is_number
= false },
1025 .is_number
= false } };
1027 RES_FUNC(res_qp
, RDMA_NLDEV_CMD_RES_QP_GET
, qp_valid_filters
, false);
1030 struct filters cm_id_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
1031 { .name
= "link", .is_number
= false },
1032 { .name
= "lqpn", .is_number
= true },
1033 { .name
= "qp-type", .is_number
= false },
1034 { .name
= "state", .is_number
= false },
1035 { .name
= "ps", .is_number
= false },
1036 { .name
= "dev-type", .is_number
= false },
1037 { .name
= "transport-type", .is_number
= false },
1038 { .name
= "pid", .is_number
= true },
1039 { .name
= "src-addr", .is_number
= false },
1040 { .name
= "src-port", .is_number
= true },
1041 { .name
= "dst-addr", .is_number
= false },
1042 { .name
= "dst-port", .is_number
= true }
1045 RES_FUNC(res_cm_id
, RDMA_NLDEV_CMD_RES_CM_ID_GET
, cm_id_valid_filters
, false);
1048 struct filters cq_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
1049 { .name
= "dev", .is_number
= false },
1050 { .name
= "users", .is_number
= true },
1051 { .name
= "poll-ctx", .is_number
= false },
1052 { .name
= "pid", .is_number
= true }
1055 RES_FUNC(res_cq
, RDMA_NLDEV_CMD_RES_CQ_GET
, cq_valid_filters
, true);
1058 struct filters mr_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
1059 { .name
= "dev", .is_number
= false },
1060 { .name
= "rkey", .is_number
= true },
1061 { .name
= "lkey", .is_number
= true },
1062 { .name
= "mrlen", .is_number
= true },
1063 { .name
= "pid", .is_number
= true }
1066 RES_FUNC(res_mr
, RDMA_NLDEV_CMD_RES_MR_GET
, mr_valid_filters
, true);
1069 struct filters pd_valid_filters
[MAX_NUMBER_OF_FILTERS
] = {
1070 { .name
= "dev", .is_number
= false },
1071 { .name
= "users", .is_number
= true },
1072 { .name
= "pid", .is_number
= true }
1075 RES_FUNC(res_pd
, RDMA_NLDEV_CMD_RES_PD_GET
, pd_valid_filters
, true);
1077 static int res_show(struct rd
*rd
)
1079 const struct rd_cmd cmds
[] = {
1080 { NULL
, res_no_args
},
1082 { "cm_id", res_cm_id
},
1090 * Special case to support "rdma res show DEV_NAME"
1092 if (rd_argc(rd
) == 1 && dev_map_lookup(rd
, false))
1093 return rd_exec_dev(rd
, _res_no_args
);
1095 return rd_exec_cmd(rd
, cmds
, "parameter");
1098 int cmd_res(struct rd
*rd
)
1100 const struct rd_cmd cmds
[] = {
1102 { "show", res_show
},
1103 { "list", res_show
},
1104 { "help", res_help
},
1108 return rd_exec_cmd(rd
, cmds
, "resource command");