1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
4 * Authors: Leon Romanovsky <leonro@mellanox.com>
11 int rd_argc(struct rd
*rd
)
16 char *rd_argv(struct rd
*rd
)
23 int strcmpx(const char *str1
, const char *str2
)
25 if (strlen(str1
) > strlen(str2
))
27 return strncmp(str1
, str2
, strlen(str1
));
30 static bool rd_argv_match(struct rd
*rd
, const char *pattern
)
34 return strcmpx(rd_argv(rd
), pattern
) == 0;
37 void rd_arg_inc(struct rd
*rd
)
45 bool rd_no_arg(struct rd
*rd
)
47 return rd_argc(rd
) == 0;
51 * Possible input:output
52 * dev/port | first port | is_dump_all
55 * mlx5_1/0 | 0 | false
56 * mlx5_1/1 | 1 | false
57 * mlx5_1/- | 0 | false
59 * In strict port mode, a non-0 port must be provided
61 static int get_port_from_argv(struct rd
*rd
, uint32_t *port
,
62 bool *is_dump_all
, bool strict_port
)
67 *is_dump_all
= strict_port
? false : true;
69 slash
= strchr(rd_argv(rd
), '/');
70 /* if no port found, return 0 */
79 if (isdigit(*slash
)) {
83 if (!*port
&& strlen(slash
))
86 if (strict_port
&& (*port
== 0))
92 static struct dev_map
*dev_map_alloc(const char *dev_name
)
94 struct dev_map
*dev_map
;
96 dev_map
= calloc(1, sizeof(*dev_map
));
99 dev_map
->dev_name
= strdup(dev_name
);
100 if (!dev_map
->dev_name
) {
108 static void dev_map_cleanup(struct rd
*rd
)
110 struct dev_map
*dev_map
, *tmp
;
112 list_for_each_entry_safe(dev_map
, tmp
,
113 &rd
->dev_map_list
, list
) {
114 list_del(&dev_map
->list
);
115 free(dev_map
->dev_name
);
120 static int add_filter(struct rd
*rd
, char *key
, char *value
,
121 const struct filters valid_filters
[])
123 char cset
[] = "1234567890,-";
124 struct filter_entry
*fe
;
125 bool key_found
= false;
130 fe
= calloc(1, sizeof(*fe
));
134 while (idx
< MAX_NUMBER_OF_FILTERS
&& valid_filters
[idx
].name
) {
135 if (!strcmpx(key
, valid_filters
[idx
].name
)) {
142 pr_err("Unsupported filter option: %s\n", key
);
148 * Check the filter validity, not optimal, but works
150 * Actually, there are three types of filters
151 * numeric - for example PID or QPN
152 * string - for example states
153 * link - user requested to filter on specific link
154 * e.g. mlx5_1/1, mlx5_1/-, mlx5_1 ...
156 if (valid_filters
[idx
].is_number
&&
157 strspn(value
, cset
) != strlen(value
)) {
158 pr_err("%s filter accepts \"%s\" characters only\n", key
, cset
);
163 fe
->key
= strdup(key
);
164 fe
->value
= strdup(value
);
165 if (!fe
->key
|| !fe
->value
) {
171 strtol(fe
->value
, &endp
, 10);
172 if (valid_filters
[idx
].is_doit
&& !errno
&& *endp
== '\0')
175 for (idx
= 0; idx
< strlen(fe
->value
); idx
++)
176 fe
->value
[idx
] = tolower(fe
->value
[idx
]);
178 list_add_tail(&fe
->list
, &rd
->filter_list
);
189 bool rd_doit_index(struct rd
*rd
, uint32_t *idx
)
191 struct filter_entry
*fe
;
193 list_for_each_entry(fe
, &rd
->filter_list
, list
) {
195 *idx
= atoi(fe
->value
);
203 int rd_build_filter(struct rd
*rd
, const struct filters valid_filters
[])
208 if (!valid_filters
|| !rd_argc(rd
))
211 if (rd_argc(rd
) == 1) {
212 pr_err("No filter data was supplied to filter option %s\n", rd_argv(rd
));
217 if (rd_argc(rd
) % 2) {
218 pr_err("There is filter option without data\n");
223 while (idx
!= rd_argc(rd
)) {
225 * We can do micro-optimization and skip "dev"
226 * and "link" filters, but it is not worth of it.
228 ret
= add_filter(rd
, *(rd
->argv
+ idx
),
229 *(rd
->argv
+ idx
+ 1), valid_filters
);
239 static bool rd_check_is_key_exist(struct rd
*rd
, const char *key
)
241 struct filter_entry
*fe
;
243 list_for_each_entry(fe
, &rd
->filter_list
, list
) {
244 if (!strcmpx(fe
->key
, key
))
252 * Check if string entry is filtered:
253 * * key doesn't exist -> user didn't request -> not filtered
255 static bool rd_check_is_string_filtered(struct rd
*rd
, const char *key
,
258 bool key_is_filtered
= false;
259 struct filter_entry
*fe
;
263 list_for_each_entry(fe
, &rd
->filter_list
, list
) {
264 if (!strcmpx(fe
->key
, key
)) {
265 /* We found the key */
266 p
= strdup(fe
->value
);
267 key_is_filtered
= true;
270 * Something extremely wrong if we fail
271 * to allocate small amount of bytes.
273 pr_err("Found key, but failed to allocate memory to store value\n");
274 return key_is_filtered
;
278 * Need to check if value in range
279 * It can come in the following formats
280 * and their permutations:
284 str
= strtok(p
, ",");
286 if (strlen(str
) == strlen(val
) &&
287 !strcasecmp(str
, val
)) {
288 key_is_filtered
= false;
291 str
= strtok(NULL
, ",");
299 return key_is_filtered
;
303 * Check if key is filtered:
304 * key doesn't exist -> user didn't request -> not filtered
306 static bool rd_check_is_filtered(struct rd
*rd
, const char *key
, uint32_t val
)
308 bool key_is_filtered
= false;
309 struct filter_entry
*fe
;
311 list_for_each_entry(fe
, &rd
->filter_list
, list
) {
312 uint32_t left_val
= 0, fe_value
= 0;
313 bool range_check
= false;
316 if (!strcmpx(fe
->key
, key
)) {
317 /* We found the key */
318 key_is_filtered
= true;
320 * Need to check if value in range
321 * It can come in the following formats
322 * (and their permutations):
327 * numb1,numb2-numb3,numb4-numb5
331 fe_value
= strtol(p
, &p
, 10);
332 if (fe_value
== val
||
333 (range_check
&& left_val
< val
&&
335 key_is_filtered
= false;
352 return key_is_filtered
;
355 bool rd_is_filtered_attr(struct rd
*rd
, const char *key
, uint32_t val
,
359 return rd_check_is_key_exist(rd
, key
);
361 return rd_check_is_filtered(rd
, key
, val
);
364 bool rd_is_string_filtered_attr(struct rd
*rd
, const char *key
, const char *val
,
368 rd_check_is_key_exist(rd
, key
);
370 return rd_check_is_string_filtered(rd
, key
, val
);
373 static void filters_cleanup(struct rd
*rd
)
375 struct filter_entry
*fe
, *tmp
;
377 list_for_each_entry_safe(fe
, tmp
,
378 &rd
->filter_list
, list
) {
386 static const enum mnl_attr_data_type nldev_policy
[RDMA_NLDEV_ATTR_MAX
] = {
387 [RDMA_NLDEV_ATTR_DEV_INDEX
] = MNL_TYPE_U32
,
388 [RDMA_NLDEV_ATTR_DEV_NAME
] = MNL_TYPE_NUL_STRING
,
389 [RDMA_NLDEV_ATTR_PORT_INDEX
] = MNL_TYPE_U32
,
390 [RDMA_NLDEV_ATTR_CAP_FLAGS
] = MNL_TYPE_U64
,
391 [RDMA_NLDEV_ATTR_FW_VERSION
] = MNL_TYPE_NUL_STRING
,
392 [RDMA_NLDEV_ATTR_NODE_GUID
] = MNL_TYPE_U64
,
393 [RDMA_NLDEV_ATTR_SYS_IMAGE_GUID
] = MNL_TYPE_U64
,
394 [RDMA_NLDEV_ATTR_LID
] = MNL_TYPE_U32
,
395 [RDMA_NLDEV_ATTR_SM_LID
] = MNL_TYPE_U32
,
396 [RDMA_NLDEV_ATTR_LMC
] = MNL_TYPE_U8
,
397 [RDMA_NLDEV_ATTR_PORT_STATE
] = MNL_TYPE_U8
,
398 [RDMA_NLDEV_ATTR_PORT_PHYS_STATE
] = MNL_TYPE_U8
,
399 [RDMA_NLDEV_ATTR_DEV_NODE_TYPE
] = MNL_TYPE_U8
,
400 [RDMA_NLDEV_ATTR_RES_SUMMARY
] = MNL_TYPE_NESTED
,
401 [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY
] = MNL_TYPE_NESTED
,
402 [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME
] = MNL_TYPE_NUL_STRING
,
403 [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR
] = MNL_TYPE_U64
,
404 [RDMA_NLDEV_ATTR_RES_QP
] = MNL_TYPE_NESTED
,
405 [RDMA_NLDEV_ATTR_RES_QP_ENTRY
] = MNL_TYPE_NESTED
,
406 [RDMA_NLDEV_ATTR_RES_LQPN
] = MNL_TYPE_U32
,
407 [RDMA_NLDEV_ATTR_RES_RQPN
] = MNL_TYPE_U32
,
408 [RDMA_NLDEV_ATTR_RES_RQ_PSN
] = MNL_TYPE_U32
,
409 [RDMA_NLDEV_ATTR_RES_SQ_PSN
] = MNL_TYPE_U32
,
410 [RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE
] = MNL_TYPE_U8
,
411 [RDMA_NLDEV_ATTR_RES_TYPE
] = MNL_TYPE_U8
,
412 [RDMA_NLDEV_ATTR_RES_STATE
] = MNL_TYPE_U8
,
413 [RDMA_NLDEV_ATTR_RES_PID
] = MNL_TYPE_U32
,
414 [RDMA_NLDEV_ATTR_RES_KERN_NAME
] = MNL_TYPE_NUL_STRING
,
415 [RDMA_NLDEV_ATTR_RES_CM_ID
] = MNL_TYPE_NESTED
,
416 [RDMA_NLDEV_ATTR_RES_CM_ID_ENTRY
] = MNL_TYPE_NESTED
,
417 [RDMA_NLDEV_ATTR_RES_PS
] = MNL_TYPE_U32
,
418 [RDMA_NLDEV_ATTR_RES_SRC_ADDR
] = MNL_TYPE_UNSPEC
,
419 [RDMA_NLDEV_ATTR_RES_DST_ADDR
] = MNL_TYPE_UNSPEC
,
420 [RDMA_NLDEV_ATTR_RES_CQ
] = MNL_TYPE_NESTED
,
421 [RDMA_NLDEV_ATTR_RES_CQ_ENTRY
] = MNL_TYPE_NESTED
,
422 [RDMA_NLDEV_ATTR_RES_CQE
] = MNL_TYPE_U32
,
423 [RDMA_NLDEV_ATTR_RES_USECNT
] = MNL_TYPE_U64
,
424 [RDMA_NLDEV_ATTR_RES_POLL_CTX
] = MNL_TYPE_U8
,
425 [RDMA_NLDEV_ATTR_RES_MR
] = MNL_TYPE_NESTED
,
426 [RDMA_NLDEV_ATTR_RES_MR_ENTRY
] = MNL_TYPE_NESTED
,
427 [RDMA_NLDEV_ATTR_RES_RKEY
] = MNL_TYPE_U32
,
428 [RDMA_NLDEV_ATTR_RES_LKEY
] = MNL_TYPE_U32
,
429 [RDMA_NLDEV_ATTR_RES_IOVA
] = MNL_TYPE_U64
,
430 [RDMA_NLDEV_ATTR_RES_MRLEN
] = MNL_TYPE_U64
,
431 [RDMA_NLDEV_ATTR_NDEV_INDEX
] = MNL_TYPE_U32
,
432 [RDMA_NLDEV_ATTR_NDEV_NAME
] = MNL_TYPE_NUL_STRING
,
433 [RDMA_NLDEV_ATTR_DRIVER
] = MNL_TYPE_NESTED
,
434 [RDMA_NLDEV_ATTR_DRIVER_ENTRY
] = MNL_TYPE_NESTED
,
435 [RDMA_NLDEV_ATTR_DRIVER_STRING
] = MNL_TYPE_NUL_STRING
,
436 [RDMA_NLDEV_ATTR_DRIVER_PRINT_TYPE
] = MNL_TYPE_U8
,
437 [RDMA_NLDEV_ATTR_DRIVER_S32
] = MNL_TYPE_U32
,
438 [RDMA_NLDEV_ATTR_DRIVER_U32
] = MNL_TYPE_U32
,
439 [RDMA_NLDEV_ATTR_DRIVER_S64
] = MNL_TYPE_U64
,
440 [RDMA_NLDEV_ATTR_DRIVER_U64
] = MNL_TYPE_U64
,
441 [RDMA_NLDEV_SYS_ATTR_NETNS_MODE
] = MNL_TYPE_U8
,
442 [RDMA_NLDEV_ATTR_STAT_COUNTER
] = MNL_TYPE_NESTED
,
443 [RDMA_NLDEV_ATTR_STAT_COUNTER_ENTRY
] = MNL_TYPE_NESTED
,
444 [RDMA_NLDEV_ATTR_STAT_COUNTER_ID
] = MNL_TYPE_U32
,
445 [RDMA_NLDEV_ATTR_STAT_HWCOUNTERS
] = MNL_TYPE_NESTED
,
446 [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY
] = MNL_TYPE_NESTED
,
447 [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME
] = MNL_TYPE_NUL_STRING
,
448 [RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE
] = MNL_TYPE_U64
,
449 [RDMA_NLDEV_ATTR_STAT_MODE
] = MNL_TYPE_U32
,
450 [RDMA_NLDEV_ATTR_STAT_RES
] = MNL_TYPE_U32
,
451 [RDMA_NLDEV_ATTR_STAT_AUTO_MODE_MASK
] = MNL_TYPE_U32
,
452 [RDMA_NLDEV_ATTR_DEV_DIM
] = MNL_TYPE_U8
,
453 [RDMA_NLDEV_ATTR_RES_RAW
] = MNL_TYPE_BINARY
,
456 int rd_attr_check(const struct nlattr
*attr
, int *typep
)
460 if (mnl_attr_type_valid(attr
, RDMA_NLDEV_ATTR_MAX
) < 0)
463 type
= mnl_attr_get_type(attr
);
465 if (mnl_attr_validate(attr
, nldev_policy
[type
]) < 0)
468 *typep
= nldev_policy
[type
];
472 int rd_attr_cb(const struct nlattr
*attr
, void *data
)
474 const struct nlattr
**tb
= data
;
477 if (mnl_attr_type_valid(attr
, RDMA_NLDEV_ATTR_MAX
- 1) < 0)
478 /* We received unknown attribute */
481 type
= mnl_attr_get_type(attr
);
483 if (mnl_attr_validate(attr
, nldev_policy
[type
]) < 0)
490 int rd_dev_init_cb(const struct nlmsghdr
*nlh
, void *data
)
492 struct nlattr
*tb
[RDMA_NLDEV_ATTR_MAX
] = {};
493 struct dev_map
*dev_map
;
494 struct rd
*rd
= data
;
495 const char *dev_name
;
497 mnl_attr_parse(nlh
, 0, rd_attr_cb
, tb
);
498 if (!tb
[RDMA_NLDEV_ATTR_DEV_NAME
] || !tb
[RDMA_NLDEV_ATTR_DEV_INDEX
])
500 if (!tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]) {
501 pr_err("This tool doesn't support switches yet\n");
505 dev_name
= mnl_attr_get_str(tb
[RDMA_NLDEV_ATTR_DEV_NAME
]);
507 dev_map
= dev_map_alloc(dev_name
);
509 /* The main function will cleanup the allocations */
511 list_add_tail(&dev_map
->list
, &rd
->dev_map_list
);
513 dev_map
->num_ports
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_PORT_INDEX
]);
514 dev_map
->idx
= mnl_attr_get_u32(tb
[RDMA_NLDEV_ATTR_DEV_INDEX
]);
518 void rd_free(struct rd
*rd
)
527 int rd_set_arg_to_devname(struct rd
*rd
)
531 while (!rd_no_arg(rd
)) {
532 if (rd_argv_match(rd
, "dev") || rd_argv_match(rd
, "link")) {
535 pr_err("No device name was supplied\n");
546 int rd_exec_link(struct rd
*rd
, int (*cb
)(struct rd
*rd
), bool strict_port
)
548 struct dev_map
*dev_map
;
552 new_json_obj(rd
->json_output
);
554 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
) {
555 rd
->dev_idx
= dev_map
->idx
;
556 port
= (strict_port
) ? 1 : 0;
557 for (; port
< dev_map
->num_ports
+ 1; port
++) {
568 dev_map
= dev_map_lookup(rd
, true);
569 ret
= get_port_from_argv(rd
, &port
, &is_dump_all
, strict_port
);
570 if (!dev_map
|| port
> dev_map
->num_ports
|| (!port
&& ret
)) {
571 pr_err("Wrong device name\n");
576 rd
->dev_idx
= dev_map
->idx
;
578 for (; rd
->port_idx
< dev_map
->num_ports
+ 1; rd
->port_idx
++) {
584 * We got request to show link for devname
596 int rd_exec_dev(struct rd
*rd
, int (*cb
)(struct rd
*rd
))
598 struct dev_map
*dev_map
;
601 new_json_obj(rd
->json_output
);
603 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
) {
604 rd
->dev_idx
= dev_map
->idx
;
610 dev_map
= dev_map_lookup(rd
, false);
612 pr_err("Wrong device name - %s\n", rd_argv(rd
));
617 rd
->dev_idx
= dev_map
->idx
;
625 int rd_exec_require_dev(struct rd
*rd
, int (*cb
)(struct rd
*rd
))
628 pr_err("Please provide device name.\n");
632 return rd_exec_dev(rd
, cb
);
635 int rd_exec_cmd(struct rd
*rd
, const struct rd_cmd
*cmds
, const char *str
)
637 const struct rd_cmd
*c
;
639 /* First argument in objs table is default variant */
641 return cmds
->func(rd
);
643 for (c
= cmds
+ 1; c
->cmd
; ++c
) {
644 if (rd_argv_match(rd
, c
->cmd
)) {
645 /* Move to next argument */
651 pr_err("Unknown %s '%s'.\n", str
, rd_argv(rd
));
655 void rd_prepare_msg(struct rd
*rd
, uint32_t cmd
, uint32_t *seq
, uint16_t flags
)
659 rd
->nlh
= mnl_nlmsg_put_header(rd
->buff
);
660 rd
->nlh
->nlmsg_type
= RDMA_NL_GET_TYPE(RDMA_NL_NLDEV
, cmd
);
661 rd
->nlh
->nlmsg_seq
= *seq
;
662 rd
->nlh
->nlmsg_flags
= flags
;
665 int rd_send_msg(struct rd
*rd
)
669 rd
->nl
= mnl_socket_open(NETLINK_RDMA
);
671 pr_err("Failed to open NETLINK_RDMA socket\n");
675 ret
= mnl_socket_bind(rd
->nl
, 0, MNL_SOCKET_AUTOPID
);
677 pr_err("Failed to bind socket with err %d\n", ret
);
681 ret
= mnl_socket_sendto(rd
->nl
, rd
->nlh
, rd
->nlh
->nlmsg_len
);
683 pr_err("Failed to send to socket with err %d\n", ret
);
689 mnl_socket_close(rd
->nl
);
693 int rd_recv_msg(struct rd
*rd
, mnl_cb_t callback
, void *data
, unsigned int seq
)
697 char buf
[MNL_SOCKET_BUFFER_SIZE
];
699 portid
= mnl_socket_get_portid(rd
->nl
);
701 ret
= mnl_socket_recvfrom(rd
->nl
, buf
, sizeof(buf
));
705 ret
= mnl_cb_run(buf
, ret
, seq
, portid
, callback
, data
);
708 if (ret
< 0 && !rd
->suppress_errors
)
711 mnl_socket_close(rd
->nl
);
715 static int null_cb(const struct nlmsghdr
*nlh
, void *data
)
720 int rd_sendrecv_msg(struct rd
*rd
, unsigned int seq
)
724 ret
= rd_send_msg(rd
);
726 ret
= rd_recv_msg(rd
, null_cb
, rd
, seq
);
730 static struct dev_map
*_dev_map_lookup(struct rd
*rd
, const char *dev_name
)
732 struct dev_map
*dev_map
;
734 list_for_each_entry(dev_map
, &rd
->dev_map_list
, list
)
735 if (strcmp(dev_name
, dev_map
->dev_name
) == 0)
741 struct dev_map
*dev_map_lookup(struct rd
*rd
, bool allow_port_index
)
743 struct dev_map
*dev_map
;
750 dev_name
= strdup(rd_argv(rd
));
751 if (allow_port_index
) {
752 slash
= strrchr(dev_name
, '/');
757 dev_map
= _dev_map_lookup(rd
, dev_name
);
762 #define nla_type(attr) ((attr)->nla_type & NLA_TYPE_MASK)
764 void newline(struct rd
*rd
)
767 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, "\n", NULL
);
770 void newline_indent(struct rd
*rd
)
773 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, " ", NULL
);
776 static int print_driver_string(struct rd
*rd
, const char *key_str
,
779 print_color_string(PRINT_ANY
, COLOR_NONE
, key_str
, key_str
, val_str
);
780 print_color_string(PRINT_FP
, COLOR_NONE
, NULL
, " %s ", val_str
);
784 void print_on_off(struct rd
*rd
, const char *key_str
, bool on
)
786 print_driver_string(rd
, key_str
, (on
) ? "on":"off");
789 static int print_driver_s32(struct rd
*rd
, const char *key_str
, int32_t val
,
790 enum rdma_nldev_print_type print_type
)
792 if (!rd
->json_output
) {
793 switch (print_type
) {
794 case RDMA_NLDEV_PRINT_TYPE_UNSPEC
:
795 return pr_out("%s %d ", key_str
, val
);
796 case RDMA_NLDEV_PRINT_TYPE_HEX
:
797 return pr_out("%s 0x%x ", key_str
, val
);
802 print_color_int(PRINT_JSON
, COLOR_NONE
, key_str
, NULL
, val
);
806 static int print_driver_u32(struct rd
*rd
, const char *key_str
, uint32_t val
,
807 enum rdma_nldev_print_type print_type
)
809 if (!rd
->json_output
) {
810 switch (print_type
) {
811 case RDMA_NLDEV_PRINT_TYPE_UNSPEC
:
812 return pr_out("%s %u ", key_str
, val
);
813 case RDMA_NLDEV_PRINT_TYPE_HEX
:
814 return pr_out("%s 0x%x ", key_str
, val
);
819 print_color_int(PRINT_JSON
, COLOR_NONE
, key_str
, NULL
, val
);
823 static int print_driver_s64(struct rd
*rd
, const char *key_str
, int64_t val
,
824 enum rdma_nldev_print_type print_type
)
826 if (!rd
->json_output
) {
827 switch (print_type
) {
828 case RDMA_NLDEV_PRINT_TYPE_UNSPEC
:
829 return pr_out("%s %" PRId64
" ", key_str
, val
);
830 case RDMA_NLDEV_PRINT_TYPE_HEX
:
831 return pr_out("%s 0x%" PRIx64
" ", key_str
, val
);
836 print_color_int(PRINT_JSON
, COLOR_NONE
, key_str
, NULL
, val
);
840 static int print_driver_u64(struct rd
*rd
, const char *key_str
, uint64_t val
,
841 enum rdma_nldev_print_type print_type
)
843 if (!rd
->json_output
) {
844 switch (print_type
) {
845 case RDMA_NLDEV_PRINT_TYPE_UNSPEC
:
846 return pr_out("%s %" PRIu64
" ", key_str
, val
);
847 case RDMA_NLDEV_PRINT_TYPE_HEX
:
848 return pr_out("%s 0x%" PRIx64
" ", key_str
, val
);
853 print_color_int(PRINT_JSON
, COLOR_NONE
, key_str
, NULL
, val
);
857 static int print_driver_entry(struct rd
*rd
, struct nlattr
*key_attr
,
858 struct nlattr
*val_attr
,
859 enum rdma_nldev_print_type print_type
)
861 int attr_type
= nla_type(val_attr
);
865 if (asprintf(&key_str
, "drv_%s", mnl_attr_get_str(key_attr
)) == -1)
869 case RDMA_NLDEV_ATTR_DRIVER_STRING
:
870 ret
= print_driver_string(rd
, key_str
,
871 mnl_attr_get_str(val_attr
));
873 case RDMA_NLDEV_ATTR_DRIVER_S32
:
874 ret
= print_driver_s32(rd
, key_str
, mnl_attr_get_u32(val_attr
),
877 case RDMA_NLDEV_ATTR_DRIVER_U32
:
878 ret
= print_driver_u32(rd
, key_str
, mnl_attr_get_u32(val_attr
),
881 case RDMA_NLDEV_ATTR_DRIVER_S64
:
882 ret
= print_driver_s64(rd
, key_str
, mnl_attr_get_u64(val_attr
),
885 case RDMA_NLDEV_ATTR_DRIVER_U64
:
886 ret
= print_driver_u64(rd
, key_str
, mnl_attr_get_u64(val_attr
),
894 void print_raw_data(struct rd
*rd
, struct nlattr
**nla_line
)
903 len
= mnl_attr_get_payload_len(nla_line
[RDMA_NLDEV_ATTR_RES_RAW
]);
904 data
= mnl_attr_get_payload(nla_line
[RDMA_NLDEV_ATTR_RES_RAW
]);
905 open_json_array(PRINT_JSON
, "data");
907 print_color_uint(PRINT_ANY
, COLOR_NONE
, NULL
, "%d", data
[i
]);
910 close_json_array(PRINT_ANY
, ">");
913 void print_driver_table(struct rd
*rd
, struct nlattr
*tb
)
915 int print_type
= RDMA_NLDEV_PRINT_TYPE_UNSPEC
;
916 struct nlattr
*tb_entry
, *key
= NULL
, *val
;
920 if (!rd
->show_driver_details
|| !tb
)
923 if (rd
->pretty_output
)
927 * Driver attrs are tuples of {key, [print-type], value}.
928 * The key must be a string. If print-type is present, it
929 * defines an alternate printf format type vs the native format
930 * for the attribute. And the value can be any available
933 mnl_attr_for_each_nested(tb_entry
, tb
) {
935 if (cc
> MAX_LINE_LENGTH
) {
936 if (rd
->pretty_output
)
940 if (rd_attr_check(tb_entry
, &type
) != MNL_CB_OK
)
943 if (type
!= MNL_TYPE_NUL_STRING
)
946 } else if (type
== MNL_TYPE_U8
) {
947 print_type
= mnl_attr_get_u8(tb_entry
);
950 ret
= print_driver_entry(rd
, key
, val
, print_type
);
954 print_type
= RDMA_NLDEV_PRINT_TYPE_UNSPEC
;