]>
Commit | Line | Data |
---|---|---|
923aa825 LR |
1 | /* |
2 | * res.c RDMA tool | |
3 | * | |
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. | |
8 | * | |
9 | * Authors: Leon Romanovsky <leonro@mellanox.com> | |
10 | */ | |
11 | ||
12 | #include "rdma.h" | |
13 | #include <inttypes.h> | |
14 | ||
15 | static int res_help(struct rd *rd) | |
16 | { | |
17 | pr_out("Usage: %s resource\n", rd->filename); | |
18 | pr_out(" resource show [DEV]\n"); | |
9a362cc7 | 19 | pr_out(" resource show [qp|cm_id]\n"); |
8ecac46a LR |
20 | pr_out(" resource show qp link [DEV/PORT]\n"); |
21 | pr_out(" resource show qp link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n"); | |
9a362cc7 SW |
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"); | |
b0b8e32c SW |
24 | pr_out(" resource show cq link [DEV/PORT]\n"); |
25 | pr_out(" resource show cq link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n"); | |
923aa825 LR |
26 | return 0; |
27 | } | |
28 | ||
29 | static int res_print_summary(struct rd *rd, struct nlattr **tb) | |
30 | { | |
31 | struct nlattr *nla_table = tb[RDMA_NLDEV_ATTR_RES_SUMMARY]; | |
32 | struct nlattr *nla_entry; | |
33 | const char *name; | |
34 | uint64_t curr; | |
35 | int err; | |
36 | ||
37 | mnl_attr_for_each_nested(nla_entry, nla_table) { | |
38 | struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; | |
39 | char json_name[32]; | |
40 | ||
41 | err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); | |
42 | if (err != MNL_CB_OK) | |
43 | return -EINVAL; | |
44 | ||
45 | if (!nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME] || | |
46 | !nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR]) { | |
47 | return -EINVAL; | |
48 | } | |
49 | ||
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); | |
55 | } else { | |
56 | pr_out("%s %"PRId64 " ", name, curr); | |
57 | } | |
58 | } | |
59 | return 0; | |
60 | } | |
61 | ||
62 | static int res_no_args_parse_cb(const struct nlmsghdr *nlh, void *data) | |
63 | { | |
64 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; | |
65 | struct rd *rd = data; | |
66 | const char *name; | |
67 | uint32_t idx; | |
68 | ||
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]) | |
73 | return MNL_CB_ERROR; | |
74 | ||
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); | |
80 | } else { | |
81 | pr_out("%u: %s: ", idx, name); | |
82 | } | |
83 | ||
84 | res_print_summary(rd, tb); | |
85 | ||
86 | if (!rd->json_output) | |
87 | pr_out("\n"); | |
88 | return MNL_CB_OK; | |
89 | } | |
90 | ||
91 | static int _res_send_msg(struct rd *rd, uint32_t command, mnl_cb_t callback) | |
92 | { | |
93 | uint32_t flags = NLM_F_REQUEST | NLM_F_ACK; | |
94 | uint32_t seq; | |
95 | int ret; | |
96 | ||
97 | if (command != RDMA_NLDEV_CMD_RES_GET) | |
98 | flags |= NLM_F_DUMP; | |
99 | ||
100 | rd_prepare_msg(rd, command, &seq, flags); | |
101 | mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx); | |
102 | if (rd->port_idx) | |
103 | mnl_attr_put_u32(rd->nlh, | |
104 | RDMA_NLDEV_ATTR_PORT_INDEX, rd->port_idx); | |
105 | ||
106 | ret = rd_send_msg(rd); | |
107 | if (ret) | |
108 | return ret; | |
109 | ||
110 | if (rd->json_output) | |
111 | jsonw_start_object(rd->jw); | |
112 | ret = rd_recv_msg(rd, callback, rd, seq); | |
113 | if (rd->json_output) | |
114 | jsonw_end_object(rd->jw); | |
115 | return ret; | |
116 | } | |
117 | ||
118 | #define RES_FUNC(name, command, valid_filters, strict_port) \ | |
119 | static int _##name(struct rd *rd)\ | |
120 | { \ | |
121 | return _res_send_msg(rd, command, name##_parse_cb); \ | |
122 | } \ | |
123 | static int name(struct rd *rd) \ | |
124 | {\ | |
125 | int ret = rd_build_filter(rd, valid_filters); \ | |
126 | if (ret) \ | |
127 | return ret; \ | |
128 | if ((uintptr_t)valid_filters != (uintptr_t)NULL) { \ | |
129 | ret = rd_set_arg_to_devname(rd); \ | |
130 | if (ret) \ | |
131 | return ret;\ | |
132 | } \ | |
133 | if (strict_port) \ | |
134 | return rd_exec_dev(rd, _##name); \ | |
135 | else \ | |
136 | return rd_exec_link(rd, _##name, strict_port); \ | |
137 | } | |
138 | ||
8ecac46a LR |
139 | static const char *path_mig_to_str(uint8_t idx) |
140 | { | |
141 | static const char * const path_mig_str[] = { "MIGRATED", | |
142 | "REARM", "ARMED" }; | |
143 | ||
144 | if (idx < ARRAY_SIZE(path_mig_str)) | |
145 | return path_mig_str[idx]; | |
146 | return "UNKNOWN"; | |
147 | } | |
148 | ||
149 | static const char *qp_states_to_str(uint8_t idx) | |
150 | { | |
151 | static const char * const qp_states_str[] = { "RESET", "INIT", | |
152 | "RTR", "RTS", "SQD", | |
153 | "SQE", "ERR" }; | |
154 | ||
155 | if (idx < ARRAY_SIZE(qp_states_str)) | |
156 | return qp_states_str[idx]; | |
157 | return "UNKNOWN"; | |
158 | } | |
159 | ||
160 | static const char *qp_types_to_str(uint8_t idx) | |
161 | { | |
162 | static const char * const qp_types_str[] = { "SMI", "GSI", "RC", | |
163 | "UC", "UD", "RAW_IPV6", | |
164 | "RAW_ETHERTYPE", | |
165 | "UNKNOWN", "RAW_PACKET", | |
166 | "XRC_INI", "XRC_TGT" }; | |
167 | ||
168 | if (idx < ARRAY_SIZE(qp_types_str)) | |
169 | return qp_types_str[idx]; | |
170 | return "UNKNOWN"; | |
171 | } | |
172 | ||
173 | static void print_lqpn(struct rd *rd, uint32_t val) | |
174 | { | |
175 | if (rd->json_output) | |
176 | jsonw_uint_field(rd->jw, "lqpn", val); | |
177 | else | |
178 | pr_out("lqpn %u ", val); | |
179 | } | |
180 | ||
181 | static void print_rqpn(struct rd *rd, uint32_t val, struct nlattr **nla_line) | |
182 | { | |
183 | if (!nla_line[RDMA_NLDEV_ATTR_RES_RQPN]) | |
184 | return; | |
185 | ||
186 | if (rd->json_output) | |
187 | jsonw_uint_field(rd->jw, "rqpn", val); | |
188 | else | |
189 | pr_out("rqpn %u ", val); | |
190 | } | |
191 | ||
192 | static void print_type(struct rd *rd, uint32_t val) | |
193 | { | |
194 | if (rd->json_output) | |
195 | jsonw_string_field(rd->jw, "type", | |
196 | qp_types_to_str(val)); | |
197 | else | |
198 | pr_out("type %s ", qp_types_to_str(val)); | |
199 | } | |
200 | ||
201 | static void print_state(struct rd *rd, uint32_t val) | |
202 | { | |
203 | if (rd->json_output) | |
204 | jsonw_string_field(rd->jw, "state", | |
205 | qp_states_to_str(val)); | |
206 | else | |
207 | pr_out("state %s ", qp_states_to_str(val)); | |
208 | } | |
209 | ||
210 | static void print_rqpsn(struct rd *rd, uint32_t val, struct nlattr **nla_line) | |
211 | { | |
212 | if (!nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN]) | |
213 | return; | |
214 | ||
215 | if (rd->json_output) | |
216 | jsonw_uint_field(rd->jw, "rq-psn", val); | |
217 | else | |
218 | pr_out("rq-psn %u ", val); | |
219 | } | |
220 | ||
221 | static void print_sqpsn(struct rd *rd, uint32_t val) | |
222 | { | |
223 | if (rd->json_output) | |
224 | jsonw_uint_field(rd->jw, "sq-psn", val); | |
225 | else | |
226 | pr_out("sq-psn %u ", val); | |
227 | } | |
228 | ||
229 | static void print_pathmig(struct rd *rd, uint32_t val, | |
230 | struct nlattr **nla_line) | |
231 | { | |
232 | if (!nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]) | |
233 | return; | |
234 | ||
235 | if (rd->json_output) | |
236 | jsonw_string_field(rd->jw, | |
237 | "path-mig-state", | |
238 | path_mig_to_str(val)); | |
239 | else | |
240 | pr_out("path-mig-state %s ", path_mig_to_str(val)); | |
241 | } | |
242 | ||
243 | static void print_pid(struct rd *rd, uint32_t val) | |
244 | { | |
245 | if (rd->json_output) | |
246 | jsonw_uint_field(rd->jw, "pid", val); | |
247 | else | |
248 | pr_out("pid %u ", val); | |
249 | } | |
250 | ||
251 | static void print_comm(struct rd *rd, const char *str, | |
252 | struct nlattr **nla_line) | |
253 | { | |
254 | char tmp[18]; | |
255 | ||
256 | if (rd->json_output) { | |
257 | /* Don't beatify output in JSON format */ | |
258 | jsonw_string_field(rd->jw, "comm", str); | |
259 | return; | |
260 | } | |
261 | ||
262 | if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) | |
263 | snprintf(tmp, sizeof(tmp), "%s", str); | |
264 | else | |
265 | snprintf(tmp, sizeof(tmp), "[%s]", str); | |
266 | ||
267 | pr_out("comm %s ", tmp); | |
268 | } | |
269 | ||
b0b8e32c SW |
270 | static void print_dev(struct rd *rd, uint32_t idx, const char *name) |
271 | { | |
272 | if (rd->json_output) { | |
273 | jsonw_uint_field(rd->jw, "ifindex", idx); | |
274 | jsonw_string_field(rd->jw, "ifname", name); | |
275 | } else { | |
276 | pr_out("dev %s ", name); | |
277 | } | |
278 | } | |
279 | ||
8ecac46a LR |
280 | static void print_link(struct rd *rd, uint32_t idx, const char *name, |
281 | uint32_t port, struct nlattr **nla_line) | |
282 | { | |
283 | if (rd->json_output) { | |
284 | jsonw_uint_field(rd->jw, "ifindex", idx); | |
285 | ||
286 | if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]) | |
287 | jsonw_uint_field(rd->jw, "port", port); | |
288 | ||
289 | jsonw_string_field(rd->jw, "ifname", name); | |
290 | } else { | |
291 | if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]) | |
292 | pr_out("link %s/%u ", name, port); | |
293 | else | |
294 | pr_out("link %s/- ", name); | |
295 | } | |
296 | } | |
297 | ||
298 | static char *get_task_name(uint32_t pid) | |
299 | { | |
300 | char *comm; | |
301 | FILE *f; | |
302 | ||
303 | if (asprintf(&comm, "/proc/%d/comm", pid) < 0) | |
304 | return NULL; | |
305 | ||
306 | f = fopen(comm, "r"); | |
307 | free(comm); | |
308 | if (!f) | |
309 | return NULL; | |
310 | ||
311 | if (fscanf(f, "%ms\n", &comm) != 1) | |
312 | comm = NULL; | |
313 | ||
314 | fclose(f); | |
315 | ||
316 | return comm; | |
317 | } | |
318 | ||
319 | static int res_qp_parse_cb(const struct nlmsghdr *nlh, void *data) | |
320 | { | |
321 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; | |
322 | struct nlattr *nla_table, *nla_entry; | |
323 | struct rd *rd = data; | |
324 | const char *name; | |
325 | uint32_t idx; | |
326 | ||
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]) | |
331 | return MNL_CB_ERROR; | |
332 | ||
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]; | |
336 | ||
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; | |
342 | char *comm = NULL; | |
343 | int err; | |
344 | ||
345 | err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); | |
346 | if (err != MNL_CB_OK) | |
347 | return MNL_CB_ERROR; | |
348 | ||
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])) { | |
355 | return MNL_CB_ERROR; | |
356 | } | |
357 | ||
358 | if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]) | |
359 | port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]); | |
360 | ||
361 | if (port != rd->port_idx) | |
362 | continue; | |
363 | ||
364 | lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]); | |
365 | if (rd_check_is_filtered(rd, "lqpn", lqpn)) | |
366 | continue; | |
367 | ||
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)) | |
371 | continue; | |
372 | } else { | |
373 | if (rd_check_is_key_exist(rd, "rqpn")) | |
374 | continue; | |
375 | } | |
376 | ||
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)) | |
380 | continue; | |
381 | } else { | |
382 | if (rd_check_is_key_exist(rd, "rq-psn")) | |
383 | continue; | |
384 | } | |
385 | ||
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)) | |
388 | continue; | |
389 | ||
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))) | |
393 | continue; | |
394 | } else { | |
395 | if (rd_check_is_key_exist(rd, "path-mig-state")) | |
396 | continue; | |
397 | } | |
398 | ||
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))) | |
401 | continue; | |
402 | ||
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))) | |
405 | continue; | |
406 | ||
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); | |
410 | } | |
411 | ||
4ac152d0 LR |
412 | if (rd_check_is_filtered(rd, "pid", pid)) { |
413 | free(comm); | |
8ecac46a | 414 | continue; |
4ac152d0 | 415 | } |
8ecac46a LR |
416 | |
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]); | |
420 | ||
421 | if (rd->json_output) | |
422 | jsonw_start_array(rd->jw); | |
423 | ||
424 | print_link(rd, idx, name, port, nla_line); | |
425 | ||
426 | print_lqpn(rd, lqpn); | |
427 | print_rqpn(rd, rqpn, nla_line); | |
428 | ||
429 | print_type(rd, type); | |
430 | print_state(rd, state); | |
431 | ||
432 | print_rqpsn(rd, rq_psn, nla_line); | |
433 | print_sqpsn(rd, sq_psn); | |
434 | ||
435 | print_pathmig(rd, path_mig_state, nla_line); | |
436 | print_pid(rd, pid); | |
437 | print_comm(rd, comm, nla_line); | |
438 | ||
439 | if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) | |
440 | free(comm); | |
441 | ||
33115275 SW |
442 | print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); |
443 | newline(rd); | |
8ecac46a LR |
444 | } |
445 | return MNL_CB_OK; | |
446 | } | |
447 | ||
9a362cc7 SW |
448 | static void print_qp_type(struct rd *rd, uint32_t val) |
449 | { | |
450 | if (rd->json_output) | |
451 | jsonw_string_field(rd->jw, "qp-type", | |
452 | qp_types_to_str(val)); | |
453 | else | |
454 | pr_out("qp-type %s ", qp_types_to_str(val)); | |
455 | } | |
456 | ||
457 | static const char *cm_id_state_to_str(uint8_t idx) | |
458 | { | |
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" }; | |
463 | ||
464 | if (idx < ARRAY_SIZE(cm_id_states_str)) | |
465 | return cm_id_states_str[idx]; | |
466 | return "UNKNOWN"; | |
467 | } | |
468 | ||
469 | static const char *cm_id_ps_to_str(uint32_t ps) | |
470 | { | |
471 | switch (ps) { | |
472 | case RDMA_PS_IPOIB: | |
473 | return "IPoIB"; | |
474 | case RDMA_PS_IB: | |
475 | return "IPoIB"; | |
476 | case RDMA_PS_TCP: | |
477 | return "TCP"; | |
478 | case RDMA_PS_UDP: | |
479 | return "UDP"; | |
480 | default: | |
481 | return "---"; | |
482 | } | |
483 | } | |
484 | ||
485 | static void print_cm_id_state(struct rd *rd, uint8_t state) | |
486 | { | |
487 | if (rd->json_output) { | |
488 | jsonw_string_field(rd->jw, "state", cm_id_state_to_str(state)); | |
489 | return; | |
490 | } | |
491 | pr_out("state %s ", cm_id_state_to_str(state)); | |
492 | } | |
493 | ||
494 | static void print_ps(struct rd *rd, uint32_t ps) | |
495 | { | |
496 | if (rd->json_output) { | |
497 | jsonw_string_field(rd->jw, "ps", cm_id_ps_to_str(ps)); | |
498 | return; | |
499 | } | |
500 | pr_out("ps %s ", cm_id_ps_to_str(ps)); | |
501 | } | |
502 | ||
503 | static void print_ipaddr(struct rd *rd, const char *key, char *addrstr, | |
504 | uint16_t port) | |
505 | { | |
506 | if (rd->json_output) { | |
507 | int name_size = INET6_ADDRSTRLEN+strlen(":65535"); | |
508 | char json_name[name_size]; | |
509 | ||
510 | snprintf(json_name, name_size, "%s:%u", addrstr, port); | |
511 | jsonw_string_field(rd->jw, key, json_name); | |
512 | return; | |
513 | } | |
514 | pr_out("%s %s:%u ", key, addrstr, port); | |
515 | } | |
516 | ||
517 | static int ss_ntop(struct nlattr *nla_line, char *addr_str, uint16_t *port) | |
518 | { | |
519 | struct __kernel_sockaddr_storage *addr; | |
520 | ||
521 | addr = (struct __kernel_sockaddr_storage *) | |
522 | mnl_attr_get_payload(nla_line); | |
523 | switch (addr->ss_family) { | |
524 | case AF_INET: { | |
525 | struct sockaddr_in *sin = (struct sockaddr_in *)addr; | |
526 | ||
527 | if (!inet_ntop(AF_INET, (const void *)&sin->sin_addr, addr_str, | |
528 | INET6_ADDRSTRLEN)) | |
529 | return -EINVAL; | |
530 | *port = ntohs(sin->sin_port); | |
531 | break; | |
532 | } | |
533 | case AF_INET6: { | |
534 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; | |
535 | ||
536 | if (!inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr, | |
537 | addr_str, INET6_ADDRSTRLEN)) | |
538 | return -EINVAL; | |
539 | *port = ntohs(sin6->sin6_port); | |
540 | break; | |
541 | } | |
542 | default: | |
543 | return -EINVAL; | |
544 | } | |
545 | return 0; | |
546 | } | |
547 | ||
548 | static int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data) | |
549 | { | |
550 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; | |
551 | struct nlattr *nla_table, *nla_entry; | |
552 | struct rd *rd = data; | |
553 | const char *name; | |
554 | int idx; | |
555 | ||
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]) | |
560 | return MNL_CB_ERROR; | |
561 | ||
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; | |
573 | char *comm = NULL; | |
574 | int err; | |
575 | ||
576 | err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); | |
577 | if (err != MNL_CB_OK) | |
578 | return -EINVAL; | |
579 | ||
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])) { | |
584 | return MNL_CB_ERROR; | |
585 | } | |
586 | ||
587 | if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]) | |
588 | port = mnl_attr_get_u32( | |
589 | nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]); | |
590 | ||
591 | if (port && port != rd->port_idx) | |
592 | continue; | |
593 | ||
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)) | |
598 | continue; | |
599 | } | |
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))) | |
605 | continue; | |
606 | } | |
607 | ||
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))) | |
610 | continue; | |
611 | ||
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))) | |
615 | continue; | |
616 | ||
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)) | |
620 | continue; | |
621 | if (rd_check_is_string_filtered(rd, "src-addr", | |
622 | src_addr_str)) | |
623 | continue; | |
624 | } | |
625 | ||
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)) | |
629 | continue; | |
630 | if (rd_check_is_string_filtered(rd, "dst-addr", | |
631 | dst_addr_str)) | |
632 | continue; | |
633 | } | |
634 | ||
635 | if (rd_check_is_filtered(rd, "src-port", src_port)) | |
636 | continue; | |
637 | ||
638 | if (rd_check_is_filtered(rd, "dst-port", dst_port)) | |
639 | continue; | |
640 | ||
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); | |
645 | } | |
646 | ||
647 | if (rd_check_is_filtered(rd, "pid", pid)) { | |
648 | free(comm); | |
649 | continue; | |
650 | } | |
651 | ||
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]); | |
656 | } | |
657 | ||
658 | if (rd->json_output) | |
659 | jsonw_start_array(rd->jw); | |
660 | ||
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); | |
667 | print_ps(rd, ps); | |
668 | print_pid(rd, pid); | |
669 | print_comm(rd, comm, nla_line); | |
670 | ||
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); | |
675 | ||
676 | if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) | |
677 | free(comm); | |
678 | ||
33115275 SW |
679 | print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); |
680 | newline(rd); | |
9a362cc7 SW |
681 | } |
682 | return MNL_CB_OK; | |
683 | } | |
684 | ||
b0b8e32c SW |
685 | static void print_cqe(struct rd *rd, uint32_t val) |
686 | { | |
687 | if (rd->json_output) | |
688 | jsonw_uint_field(rd->jw, "cqe", val); | |
689 | else | |
690 | pr_out("cqe %u ", val); | |
691 | } | |
692 | ||
693 | static void print_users(struct rd *rd, uint64_t val) | |
694 | { | |
695 | if (rd->json_output) | |
696 | jsonw_uint_field(rd->jw, "users", val); | |
697 | else | |
698 | pr_out("users %" PRIu64 " ", val); | |
699 | } | |
700 | ||
701 | static const char *poll_ctx_to_str(uint8_t idx) | |
702 | { | |
703 | static const char * const cm_id_states_str[] = { | |
704 | "DIRECT", "SOFTIRQ", "WORKQUEUE"}; | |
705 | ||
706 | if (idx < ARRAY_SIZE(cm_id_states_str)) | |
707 | return cm_id_states_str[idx]; | |
708 | return "UNKNOWN"; | |
709 | } | |
710 | ||
711 | static void print_poll_ctx(struct rd *rd, uint8_t poll_ctx) | |
712 | { | |
713 | if (rd->json_output) { | |
714 | jsonw_string_field(rd->jw, "poll-ctx", | |
715 | poll_ctx_to_str(poll_ctx)); | |
716 | return; | |
717 | } | |
718 | pr_out("poll-ctx %s ", poll_ctx_to_str(poll_ctx)); | |
719 | } | |
720 | ||
721 | static int res_cq_parse_cb(const struct nlmsghdr *nlh, void *data) | |
722 | { | |
723 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; | |
724 | struct nlattr *nla_table, *nla_entry; | |
725 | struct rd *rd = data; | |
726 | const char *name; | |
727 | uint32_t idx; | |
728 | ||
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]) | |
733 | return MNL_CB_ERROR; | |
734 | ||
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]; | |
738 | ||
739 | mnl_attr_for_each_nested(nla_entry, nla_table) { | |
740 | struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; | |
741 | char *comm = NULL; | |
742 | uint32_t pid = 0; | |
743 | uint8_t poll_ctx = 0; | |
744 | uint64_t users; | |
745 | uint32_t cqe; | |
746 | int err; | |
747 | ||
748 | err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); | |
749 | if (err != MNL_CB_OK) | |
750 | return MNL_CB_ERROR; | |
751 | ||
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])) { | |
756 | return MNL_CB_ERROR; | |
757 | } | |
758 | ||
759 | cqe = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CQE]); | |
760 | ||
761 | users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]); | |
762 | if (rd_check_is_filtered(rd, "users", users)) | |
763 | continue; | |
764 | ||
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))) | |
770 | continue; | |
771 | } | |
772 | ||
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); | |
777 | } | |
778 | ||
779 | if (rd_check_is_filtered(rd, "pid", pid)) { | |
780 | free(comm); | |
781 | continue; | |
782 | } | |
783 | ||
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]); | |
788 | ||
789 | if (rd->json_output) | |
790 | jsonw_start_array(rd->jw); | |
791 | ||
792 | print_dev(rd, idx, name); | |
793 | print_cqe(rd, cqe); | |
794 | print_users(rd, users); | |
795 | if (nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]) | |
796 | print_poll_ctx(rd, poll_ctx); | |
797 | print_pid(rd, pid); | |
798 | print_comm(rd, comm, nla_line); | |
799 | ||
800 | if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) | |
801 | free(comm); | |
802 | ||
33115275 SW |
803 | print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); |
804 | newline(rd); | |
b0b8e32c SW |
805 | } |
806 | return MNL_CB_OK; | |
807 | } | |
808 | ||
8958a15c SW |
809 | static void print_key(struct rd *rd, const char *name, uint32_t val) |
810 | { | |
811 | if (rd->json_output) | |
812 | jsonw_xint_field(rd->jw, name, val); | |
813 | else | |
814 | pr_out("%s 0x%x ", name, val); | |
815 | } | |
816 | ||
817 | static void print_iova(struct rd *rd, uint64_t val) | |
818 | { | |
819 | if (rd->json_output) | |
820 | jsonw_xint_field(rd->jw, "iova", val); | |
821 | else | |
822 | pr_out("iova 0x%" PRIx64 " ", val); | |
823 | } | |
824 | ||
825 | static void print_mrlen(struct rd *rd, uint64_t val) | |
826 | { | |
827 | if (rd->json_output) | |
828 | jsonw_uint_field(rd->jw, "mrlen", val); | |
829 | else | |
830 | pr_out("mrlen %" PRIu64 " ", val); | |
831 | } | |
832 | ||
833 | static int res_mr_parse_cb(const struct nlmsghdr *nlh, void *data) | |
834 | { | |
835 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; | |
836 | struct nlattr *nla_table, *nla_entry; | |
837 | struct rd *rd = data; | |
838 | const char *name; | |
839 | uint32_t idx; | |
840 | ||
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]) | |
845 | return MNL_CB_ERROR; | |
846 | ||
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]; | |
850 | ||
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; | |
855 | char *comm = NULL; | |
856 | uint32_t pid = 0; | |
857 | int err; | |
858 | ||
859 | err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); | |
860 | if (err != MNL_CB_OK) | |
861 | return MNL_CB_ERROR; | |
862 | ||
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])) { | |
866 | return MNL_CB_ERROR; | |
867 | } | |
868 | ||
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]); | |
878 | ||
879 | mrlen = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_MRLEN]); | |
880 | if (rd_check_is_filtered(rd, "mrlen", mrlen)) | |
881 | continue; | |
882 | ||
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); | |
887 | } | |
888 | ||
889 | if (rd_check_is_filtered(rd, "pid", pid)) { | |
890 | free(comm); | |
891 | continue; | |
892 | } | |
893 | ||
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]); | |
898 | ||
899 | if (rd->json_output) | |
900 | jsonw_start_array(rd->jw); | |
901 | ||
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); | |
910 | print_pid(rd, pid); | |
911 | print_comm(rd, comm, nla_line); | |
912 | ||
913 | if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) | |
914 | free(comm); | |
915 | ||
33115275 SW |
916 | print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); |
917 | newline(rd); | |
8958a15c SW |
918 | } |
919 | return MNL_CB_OK; | |
920 | } | |
921 | ||
4060e4c0 SW |
922 | static int res_pd_parse_cb(const struct nlmsghdr *nlh, void *data) |
923 | { | |
924 | struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; | |
925 | struct nlattr *nla_table, *nla_entry; | |
926 | struct rd *rd = data; | |
927 | const char *name; | |
928 | uint32_t idx; | |
929 | ||
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]) | |
934 | return MNL_CB_ERROR; | |
935 | ||
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]; | |
939 | ||
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] = {}; | |
943 | char *comm = NULL; | |
944 | uint32_t pid = 0; | |
945 | uint64_t users; | |
946 | int err; | |
947 | ||
948 | err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); | |
949 | if (err != MNL_CB_OK) | |
950 | return MNL_CB_ERROR; | |
951 | ||
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])) { | |
955 | return MNL_CB_ERROR; | |
956 | } | |
957 | ||
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]); | |
961 | ||
962 | users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]); | |
963 | if (rd_check_is_filtered(rd, "users", users)) | |
964 | continue; | |
965 | ||
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]); | |
969 | ||
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); | |
974 | } | |
975 | ||
976 | if (rd_check_is_filtered(rd, "pid", pid)) | |
977 | continue; | |
978 | ||
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]); | |
983 | ||
984 | if (rd->json_output) | |
985 | jsonw_start_array(rd->jw); | |
986 | ||
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); | |
993 | print_pid(rd, pid); | |
994 | print_comm(rd, comm, nla_line); | |
995 | ||
996 | if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) | |
997 | free(comm); | |
998 | ||
33115275 SW |
999 | print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); |
1000 | newline(rd); | |
4060e4c0 SW |
1001 | } |
1002 | return MNL_CB_OK; | |
1003 | } | |
1004 | ||
923aa825 LR |
1005 | RES_FUNC(res_no_args, RDMA_NLDEV_CMD_RES_GET, NULL, true); |
1006 | ||
8ecac46a LR |
1007 | static const struct |
1008 | filters qp_valid_filters[MAX_NUMBER_OF_FILTERS] = {{ .name = "link", | |
1009 | .is_number = false }, | |
1010 | { .name = "lqpn", | |
1011 | .is_number = true }, | |
1012 | { .name = "rqpn", | |
1013 | .is_number = true }, | |
1014 | { .name = "pid", | |
1015 | .is_number = true }, | |
1016 | { .name = "sq-psn", | |
1017 | .is_number = true }, | |
1018 | { .name = "rq-psn", | |
1019 | .is_number = true }, | |
1020 | { .name = "type", | |
1021 | .is_number = false }, | |
1022 | { .name = "path-mig-state", | |
1023 | .is_number = false }, | |
1024 | { .name = "state", | |
1025 | .is_number = false } }; | |
1026 | ||
1027 | RES_FUNC(res_qp, RDMA_NLDEV_CMD_RES_QP_GET, qp_valid_filters, false); | |
1028 | ||
9a362cc7 SW |
1029 | static const |
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 } | |
1043 | }; | |
1044 | ||
1045 | RES_FUNC(res_cm_id, RDMA_NLDEV_CMD_RES_CM_ID_GET, cm_id_valid_filters, false); | |
1046 | ||
b0b8e32c SW |
1047 | static const |
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 } | |
1053 | }; | |
1054 | ||
1055 | RES_FUNC(res_cq, RDMA_NLDEV_CMD_RES_CQ_GET, cq_valid_filters, true); | |
1056 | ||
8958a15c SW |
1057 | static const |
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 } | |
1064 | }; | |
1065 | ||
1066 | RES_FUNC(res_mr, RDMA_NLDEV_CMD_RES_MR_GET, mr_valid_filters, true); | |
1067 | ||
4060e4c0 SW |
1068 | static const |
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 } | |
1073 | }; | |
1074 | ||
1075 | RES_FUNC(res_pd, RDMA_NLDEV_CMD_RES_PD_GET, pd_valid_filters, true); | |
1076 | ||
923aa825 LR |
1077 | static int res_show(struct rd *rd) |
1078 | { | |
1079 | const struct rd_cmd cmds[] = { | |
1080 | { NULL, res_no_args }, | |
8ecac46a | 1081 | { "qp", res_qp }, |
9a362cc7 | 1082 | { "cm_id", res_cm_id }, |
b0b8e32c | 1083 | { "cq", res_cq }, |
8958a15c | 1084 | { "mr", res_mr }, |
4060e4c0 | 1085 | { "pd", res_pd }, |
923aa825 LR |
1086 | { 0 } |
1087 | }; | |
1088 | ||
1089 | /* | |
1090 | * Special case to support "rdma res show DEV_NAME" | |
1091 | */ | |
1092 | if (rd_argc(rd) == 1 && dev_map_lookup(rd, false)) | |
1093 | return rd_exec_dev(rd, _res_no_args); | |
1094 | ||
1095 | return rd_exec_cmd(rd, cmds, "parameter"); | |
1096 | } | |
1097 | ||
1098 | int cmd_res(struct rd *rd) | |
1099 | { | |
1100 | const struct rd_cmd cmds[] = { | |
1101 | { NULL, res_show }, | |
1102 | { "show", res_show }, | |
1103 | { "list", res_show }, | |
1104 | { "help", res_help }, | |
1105 | { 0 } | |
1106 | }; | |
1107 | ||
1108 | return rd_exec_cmd(rd, cmds, "resource command"); | |
1109 | } |