2 * devlink.c Devlink tool
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: Jiri Pirko <jiri@mellanox.com>
20 #include <linux/genetlink.h>
21 #include <linux/devlink.h>
22 #include <libmnl/libmnl.h>
27 #include "json_writer.h"
29 #define pr_err(args...) fprintf(stderr, ##args)
30 #define pr_out(args...) fprintf(stdout, ##args)
31 #define pr_out_sp(num, args...) \
33 int ret = fprintf(stdout, ##args); \
35 fprintf(stdout, "%*s", num - ret, ""); \
38 static int _mnlg_socket_recv_run(struct mnlg_socket
*nlg
,
39 mnl_cb_t data_cb
, void *data
)
43 err
= mnlg_socket_recv_run(nlg
, data_cb
, data
);
45 pr_err("devlink answers: %s\n", strerror(errno
));
51 static int _mnlg_socket_sndrcv(struct mnlg_socket
*nlg
,
52 const struct nlmsghdr
*nlh
,
53 mnl_cb_t data_cb
, void *data
)
57 err
= mnlg_socket_send(nlg
, nlh
);
59 pr_err("Failed to call mnlg_socket_send\n");
62 return _mnlg_socket_recv_run(nlg
, data_cb
, data
);
65 static int _mnlg_socket_group_add(struct mnlg_socket
*nlg
,
66 const char *group_name
)
70 err
= mnlg_socket_group_add(nlg
, group_name
);
72 pr_err("Failed to call mnlg_socket_group_add\n");
79 struct list_head list
;
86 static struct ifname_map
*ifname_map_alloc(const char *bus_name
,
91 struct ifname_map
*ifname_map
;
93 ifname_map
= calloc(1, sizeof(*ifname_map
));
96 ifname_map
->bus_name
= strdup(bus_name
);
97 ifname_map
->dev_name
= strdup(dev_name
);
98 ifname_map
->port_index
= port_index
;
99 ifname_map
->ifname
= strdup(ifname
);
100 if (!ifname_map
->bus_name
|| !ifname_map
->dev_name
||
101 !ifname_map
->ifname
) {
102 free(ifname_map
->ifname
);
103 free(ifname_map
->dev_name
);
104 free(ifname_map
->bus_name
);
111 static void ifname_map_free(struct ifname_map
*ifname_map
)
113 free(ifname_map
->ifname
);
114 free(ifname_map
->dev_name
);
115 free(ifname_map
->bus_name
);
119 #define BIT(nr) (1UL << (nr))
120 #define DL_OPT_HANDLE BIT(0)
121 #define DL_OPT_HANDLEP BIT(1)
122 #define DL_OPT_PORT_TYPE BIT(2)
123 #define DL_OPT_PORT_COUNT BIT(3)
124 #define DL_OPT_SB BIT(4)
125 #define DL_OPT_SB_POOL BIT(5)
126 #define DL_OPT_SB_SIZE BIT(6)
127 #define DL_OPT_SB_TYPE BIT(7)
128 #define DL_OPT_SB_THTYPE BIT(8)
129 #define DL_OPT_SB_TH BIT(9)
130 #define DL_OPT_SB_TC BIT(10)
133 uint32_t present
; /* flags of present items */
137 enum devlink_port_type port_type
;
140 uint16_t sb_pool_index
;
141 uint32_t sb_pool_size
;
142 enum devlink_sb_pool_type sb_pool_type
;
143 enum devlink_sb_threshold_type sb_pool_thtype
;
144 uint32_t sb_threshold
;
145 uint16_t sb_tc_index
;
149 struct mnlg_socket
*nlg
;
150 struct list_head ifname_map_list
;
166 static int dl_argc(struct dl
*dl
)
171 static char *dl_argv(struct dl
*dl
)
173 if (dl_argc(dl
) == 0)
178 static void dl_arg_inc(struct dl
*dl
)
180 if (dl_argc(dl
) == 0)
186 static char *dl_argv_next(struct dl
*dl
)
190 if (dl_argc(dl
) == 0)
198 static char *dl_argv_index(struct dl
*dl
, unsigned int index
)
200 if (index
>= dl_argc(dl
))
202 return dl
->argv
[index
];
205 static int strcmpx(const char *str1
, const char *str2
)
207 if (strlen(str1
) > strlen(str2
))
209 return strncmp(str1
, str2
, strlen(str1
));
212 static bool dl_argv_match(struct dl
*dl
, const char *pattern
)
214 if (dl_argc(dl
) == 0)
216 return strcmpx(dl_argv(dl
), pattern
) == 0;
219 static bool dl_no_arg(struct dl
*dl
)
221 return dl_argc(dl
) == 0;
224 static int attr_cb(const struct nlattr
*attr
, void *data
)
226 const struct nlattr
**tb
= data
;
229 type
= mnl_attr_get_type(attr
);
231 if (mnl_attr_type_valid(attr
, DEVLINK_ATTR_MAX
) < 0)
234 if (type
== DEVLINK_ATTR_BUS_NAME
&&
235 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
237 if (type
== DEVLINK_ATTR_DEV_NAME
&&
238 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
240 if (type
== DEVLINK_ATTR_PORT_INDEX
&&
241 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
243 if (type
== DEVLINK_ATTR_PORT_TYPE
&&
244 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
246 if (type
== DEVLINK_ATTR_PORT_DESIRED_TYPE
&&
247 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
249 if (type
== DEVLINK_ATTR_PORT_NETDEV_IFINDEX
&&
250 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
252 if (type
== DEVLINK_ATTR_PORT_NETDEV_NAME
&&
253 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
255 if (type
== DEVLINK_ATTR_PORT_IBDEV_NAME
&&
256 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
258 if (type
== DEVLINK_ATTR_SB_INDEX
&&
259 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
261 if (type
== DEVLINK_ATTR_SB_SIZE
&&
262 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
264 if (type
== DEVLINK_ATTR_SB_INGRESS_POOL_COUNT
&&
265 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
267 if (type
== DEVLINK_ATTR_SB_EGRESS_POOL_COUNT
&&
268 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
270 if (type
== DEVLINK_ATTR_SB_INGRESS_TC_COUNT
&&
271 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
273 if (type
== DEVLINK_ATTR_SB_EGRESS_TC_COUNT
&&
274 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
276 if (type
== DEVLINK_ATTR_SB_POOL_INDEX
&&
277 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
279 if (type
== DEVLINK_ATTR_SB_POOL_TYPE
&&
280 mnl_attr_validate(attr
, MNL_TYPE_U8
) < 0)
282 if (type
== DEVLINK_ATTR_SB_POOL_SIZE
&&
283 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
285 if (type
== DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
&&
286 mnl_attr_validate(attr
, MNL_TYPE_U8
) < 0)
288 if (type
== DEVLINK_ATTR_SB_THRESHOLD
&&
289 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
291 if (type
== DEVLINK_ATTR_SB_TC_INDEX
&&
292 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
294 if (type
== DEVLINK_ATTR_SB_OCC_CUR
&&
295 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
297 if (type
== DEVLINK_ATTR_SB_OCC_MAX
&&
298 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
304 static int ifname_map_cb(const struct nlmsghdr
*nlh
, void *data
)
306 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
307 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
308 struct dl
*dl
= data
;
309 struct ifname_map
*ifname_map
;
310 const char *bus_name
;
311 const char *dev_name
;
312 uint32_t port_ifindex
;
313 const char *port_ifname
;
315 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
316 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
317 !tb
[DEVLINK_ATTR_PORT_INDEX
])
320 if (!tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
323 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
324 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
325 port_ifindex
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
326 port_ifname
= mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]);
327 ifname_map
= ifname_map_alloc(bus_name
, dev_name
,
328 port_ifindex
, port_ifname
);
331 list_add(&ifname_map
->list
, &dl
->ifname_map_list
);
336 static void ifname_map_fini(struct dl
*dl
)
338 struct ifname_map
*ifname_map
, *tmp
;
340 list_for_each_entry_safe(ifname_map
, tmp
,
341 &dl
->ifname_map_list
, list
) {
342 list_del(&ifname_map
->list
);
343 ifname_map_free(ifname_map
);
347 static int ifname_map_init(struct dl
*dl
)
349 struct nlmsghdr
*nlh
;
352 INIT_LIST_HEAD(&dl
->ifname_map_list
);
354 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
,
355 NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
);
357 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, ifname_map_cb
, dl
);
365 static int ifname_map_lookup(struct dl
*dl
, const char *ifname
,
366 char **p_bus_name
, char **p_dev_name
,
367 uint32_t *p_port_index
)
369 struct ifname_map
*ifname_map
;
371 list_for_each_entry(ifname_map
, &dl
->ifname_map_list
, list
) {
372 if (strcmp(ifname
, ifname_map
->ifname
) == 0) {
373 *p_bus_name
= ifname_map
->bus_name
;
374 *p_dev_name
= ifname_map
->dev_name
;
375 *p_port_index
= ifname_map
->port_index
;
382 static int ifname_map_rev_lookup(struct dl
*dl
, const char *bus_name
,
383 const char *dev_name
, uint32_t port_index
,
386 struct ifname_map
*ifname_map
;
388 list_for_each_entry(ifname_map
, &dl
->ifname_map_list
, list
) {
389 if (strcmp(bus_name
, ifname_map
->bus_name
) == 0 &&
390 strcmp(dev_name
, ifname_map
->dev_name
) == 0 &&
391 port_index
== ifname_map
->port_index
) {
392 *p_ifname
= ifname_map
->ifname
;
399 static unsigned int strslashcount(char *str
)
401 unsigned int count
= 0;
404 while ((pos
= strchr(pos
, '/'))) {
411 static int strslashrsplit(char *str
, char **before
, char **after
)
415 slash
= strrchr(str
, '/');
424 static int strtouint32_t(const char *str
, uint32_t *p_val
)
427 unsigned long int val
;
429 val
= strtoul(str
, &endptr
, 10);
430 if (endptr
== str
|| *endptr
!= '\0')
438 static int strtouint16_t(const char *str
, uint16_t *p_val
)
441 unsigned long int val
;
443 val
= strtoul(str
, &endptr
, 10);
444 if (endptr
== str
|| *endptr
!= '\0')
452 static int __dl_argv_handle(char *str
, char **p_bus_name
, char **p_dev_name
)
454 strslashrsplit(str
, p_bus_name
, p_dev_name
);
458 static int dl_argv_handle(struct dl
*dl
, char **p_bus_name
, char **p_dev_name
)
460 char *str
= dl_argv_next(dl
);
463 pr_err("Devlink identification (\"bus_name/dev_name\") expected\n");
466 if (strslashcount(str
) != 1) {
467 pr_err("Wrong devlink identification string format.\n");
468 pr_err("Expected \"bus_name/dev_name\".\n");
471 return __dl_argv_handle(str
, p_bus_name
, p_dev_name
);
474 static int __dl_argv_handle_port(char *str
,
475 char **p_bus_name
, char **p_dev_name
,
476 uint32_t *p_port_index
)
478 char *handlestr
= handlestr
;
479 char *portstr
= portstr
;
482 strslashrsplit(str
, &handlestr
, &portstr
);
483 err
= strtouint32_t(portstr
, p_port_index
);
485 pr_err("Port index \"%s\" is not a number or not within range\n",
489 strslashrsplit(handlestr
, p_bus_name
, p_dev_name
);
493 static int __dl_argv_handle_port_ifname(struct dl
*dl
, char *str
,
494 char **p_bus_name
, char **p_dev_name
,
495 uint32_t *p_port_index
)
499 err
= ifname_map_lookup(dl
, str
, p_bus_name
, p_dev_name
,
502 pr_err("Netdevice \"%s\" not found\n", str
);
508 static int dl_argv_handle_port(struct dl
*dl
, char **p_bus_name
,
509 char **p_dev_name
, uint32_t *p_port_index
)
511 char *str
= dl_argv_next(dl
);
512 unsigned int slash_count
;
515 pr_err("Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\") expected.\n");
518 slash_count
= strslashcount(str
);
519 if (slash_count
!= 2 && slash_count
!= 0) {
520 pr_err("Wrong port identification string format.\n");
521 pr_err("Expected \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
524 if (slash_count
== 2) {
525 return __dl_argv_handle_port(str
, p_bus_name
,
526 p_dev_name
, p_port_index
);
527 } else if (slash_count
== 0) {
528 return __dl_argv_handle_port_ifname(dl
, str
, p_bus_name
,
529 p_dev_name
, p_port_index
);
534 static int dl_argv_handle_both(struct dl
*dl
, char **p_bus_name
,
535 char **p_dev_name
, uint32_t *p_port_index
,
536 uint32_t *p_handle_bit
)
538 char *str
= dl_argv_next(dl
);
539 unsigned int slash_count
;
543 pr_err("One of following identifications expected:\n"
544 "Devlink identification (\"bus_name/dev_name\")\n"
545 "Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\")\n");
548 slash_count
= strslashcount(str
);
549 if (slash_count
== 1) {
550 err
= __dl_argv_handle(str
, p_bus_name
, p_dev_name
);
553 *p_handle_bit
= DL_OPT_HANDLE
;
554 } else if (slash_count
== 2) {
555 err
= __dl_argv_handle_port(str
, p_bus_name
,
556 p_dev_name
, p_port_index
);
559 *p_handle_bit
= DL_OPT_HANDLEP
;
560 } else if (slash_count
== 0) {
561 err
= __dl_argv_handle_port_ifname(dl
, str
, p_bus_name
,
562 p_dev_name
, p_port_index
);
565 *p_handle_bit
= DL_OPT_HANDLEP
;
567 pr_err("Wrong port identification string format.\n");
568 pr_err("Expected \"bus_name/dev_name\" or \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
574 static int dl_argv_uint32_t(struct dl
*dl
, uint32_t *p_val
)
576 char *str
= dl_argv_next(dl
);
580 pr_err("Unsigned number argument expected\n");
584 err
= strtouint32_t(str
, p_val
);
586 pr_err("\"%s\" is not a number or not within range\n", str
);
592 static int dl_argv_uint16_t(struct dl
*dl
, uint16_t *p_val
)
594 char *str
= dl_argv_next(dl
);
598 pr_err("Unsigned number argument expected\n");
602 err
= strtouint16_t(str
, p_val
);
604 pr_err("\"%s\" is not a number or not within range\n", str
);
610 static int dl_argv_str(struct dl
*dl
, const char **p_str
)
612 const char *str
= dl_argv_next(dl
);
615 pr_err("String parameter expected\n");
622 static int port_type_get(const char *typestr
, enum devlink_port_type
*p_type
)
624 if (strcmp(typestr
, "auto") == 0) {
625 *p_type
= DEVLINK_PORT_TYPE_AUTO
;
626 } else if (strcmp(typestr
, "eth") == 0) {
627 *p_type
= DEVLINK_PORT_TYPE_ETH
;
628 } else if (strcmp(typestr
, "ib") == 0) {
629 *p_type
= DEVLINK_PORT_TYPE_IB
;
631 pr_err("Unknown port type \"%s\"\n", typestr
);
637 static int pool_type_get(const char *typestr
, enum devlink_sb_pool_type
*p_type
)
639 if (strcmp(typestr
, "ingress") == 0) {
640 *p_type
= DEVLINK_SB_POOL_TYPE_INGRESS
;
641 } else if (strcmp(typestr
, "egress") == 0) {
642 *p_type
= DEVLINK_SB_POOL_TYPE_EGRESS
;
644 pr_err("Unknown pool type \"%s\"\n", typestr
);
650 static int threshold_type_get(const char *typestr
,
651 enum devlink_sb_threshold_type
*p_type
)
653 if (strcmp(typestr
, "static") == 0) {
654 *p_type
= DEVLINK_SB_THRESHOLD_TYPE_STATIC
;
655 } else if (strcmp(typestr
, "dynamic") == 0) {
656 *p_type
= DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC
;
658 pr_err("Unknown threshold type \"%s\"\n", typestr
);
664 static int dl_argv_parse(struct dl
*dl
, uint32_t o_required
,
667 struct dl_opts
*opts
= &dl
->opts
;
668 uint32_t o_all
= o_required
| o_optional
;
669 uint32_t o_found
= 0;
672 if (o_required
& DL_OPT_HANDLE
&& o_required
& DL_OPT_HANDLEP
) {
673 uint32_t handle_bit
= handle_bit
;
675 err
= dl_argv_handle_both(dl
, &opts
->bus_name
, &opts
->dev_name
,
676 &opts
->port_index
, &handle_bit
);
679 o_found
|= handle_bit
;
680 } else if (o_required
& DL_OPT_HANDLE
) {
681 err
= dl_argv_handle(dl
, &opts
->bus_name
, &opts
->dev_name
);
684 o_found
|= DL_OPT_HANDLE
;
685 } else if (o_required
& DL_OPT_HANDLEP
) {
686 err
= dl_argv_handle_port(dl
, &opts
->bus_name
, &opts
->dev_name
,
690 o_found
|= DL_OPT_HANDLEP
;
693 while (dl_argc(dl
)) {
694 if (dl_argv_match(dl
, "type") &&
695 (o_all
& DL_OPT_PORT_TYPE
)) {
699 err
= dl_argv_str(dl
, &typestr
);
702 err
= port_type_get(typestr
, &opts
->port_type
);
705 o_found
|= DL_OPT_PORT_TYPE
;
706 } else if (dl_argv_match(dl
, "count") &&
707 (o_all
& DL_OPT_PORT_COUNT
)) {
709 err
= dl_argv_uint32_t(dl
, &opts
->port_count
);
712 o_found
|= DL_OPT_PORT_COUNT
;
713 } else if (dl_argv_match(dl
, "sb") &&
714 (o_all
& DL_OPT_SB
)) {
716 err
= dl_argv_uint32_t(dl
, &opts
->sb_index
);
719 o_found
|= DL_OPT_SB
;
720 } else if (dl_argv_match(dl
, "pool") &&
721 (o_all
& DL_OPT_SB_POOL
)) {
723 err
= dl_argv_uint16_t(dl
, &opts
->sb_pool_index
);
726 o_found
|= DL_OPT_SB_POOL
;
727 } else if (dl_argv_match(dl
, "size") &&
728 (o_all
& DL_OPT_SB_SIZE
)) {
730 err
= dl_argv_uint32_t(dl
, &opts
->sb_pool_size
);
733 o_found
|= DL_OPT_SB_SIZE
;
734 } else if (dl_argv_match(dl
, "type") &&
735 (o_all
& DL_OPT_SB_TYPE
)) {
739 err
= dl_argv_str(dl
, &typestr
);
742 err
= pool_type_get(typestr
, &opts
->sb_pool_type
);
745 o_found
|= DL_OPT_SB_TYPE
;
746 } else if (dl_argv_match(dl
, "thtype") &&
747 (o_all
& DL_OPT_SB_THTYPE
)) {
751 err
= dl_argv_str(dl
, &typestr
);
754 err
= threshold_type_get(typestr
,
755 &opts
->sb_pool_thtype
);
758 o_found
|= DL_OPT_SB_THTYPE
;
759 } else if (dl_argv_match(dl
, "th") &&
760 (o_all
& DL_OPT_SB_TH
)) {
762 err
= dl_argv_uint32_t(dl
, &opts
->sb_threshold
);
765 o_found
|= DL_OPT_SB_TH
;
766 } else if (dl_argv_match(dl
, "tc") &&
767 (o_all
& DL_OPT_SB_TC
)) {
769 err
= dl_argv_uint16_t(dl
, &opts
->sb_tc_index
);
772 o_found
|= DL_OPT_SB_TC
;
774 pr_err("Unknown option \"%s\"\n", dl_argv(dl
));
779 opts
->present
= o_found
;
781 if ((o_optional
& DL_OPT_SB
) && !(o_found
& DL_OPT_SB
)) {
783 opts
->present
|= DL_OPT_SB
;
786 if ((o_required
& DL_OPT_PORT_TYPE
) && !(o_found
& DL_OPT_PORT_TYPE
)) {
787 pr_err("Port type option expected.\n");
791 if ((o_required
& DL_OPT_PORT_COUNT
) &&
792 !(o_found
& DL_OPT_PORT_COUNT
)) {
793 pr_err("Port split count option expected.\n");
797 if ((o_required
& DL_OPT_SB_POOL
) && !(o_found
& DL_OPT_SB_POOL
)) {
798 pr_err("Pool index option expected.\n");
802 if ((o_required
& DL_OPT_SB_SIZE
) && !(o_found
& DL_OPT_SB_SIZE
)) {
803 pr_err("Pool size option expected.\n");
807 if ((o_required
& DL_OPT_SB_TYPE
) && !(o_found
& DL_OPT_SB_TYPE
)) {
808 pr_err("Pool type option expected.\n");
812 if ((o_required
& DL_OPT_SB_THTYPE
) && !(o_found
& DL_OPT_SB_THTYPE
)) {
813 pr_err("Pool threshold type option expected.\n");
817 if ((o_required
& DL_OPT_SB_TH
) && !(o_found
& DL_OPT_SB_TH
)) {
818 pr_err("Threshold option expected.\n");
822 if ((o_required
& DL_OPT_SB_TC
) && !(o_found
& DL_OPT_SB_TC
)) {
823 pr_err("TC index option expected.\n");
829 static void dl_opts_put(struct nlmsghdr
*nlh
, struct dl
*dl
)
831 struct dl_opts
*opts
= &dl
->opts
;
833 if (opts
->present
& DL_OPT_HANDLE
) {
834 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, opts
->bus_name
);
835 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, opts
->dev_name
);
836 } else if (opts
->present
& DL_OPT_HANDLEP
) {
837 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, opts
->bus_name
);
838 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, opts
->dev_name
);
839 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_INDEX
,
842 if (opts
->present
& DL_OPT_PORT_TYPE
)
843 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_PORT_TYPE
,
845 if (opts
->present
& DL_OPT_PORT_COUNT
)
846 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_SPLIT_COUNT
,
848 if (opts
->present
& DL_OPT_SB
)
849 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_SB_INDEX
,
851 if (opts
->present
& DL_OPT_SB_POOL
)
852 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_SB_POOL_INDEX
,
853 opts
->sb_pool_index
);
854 if (opts
->present
& DL_OPT_SB_SIZE
)
855 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_SB_POOL_SIZE
,
857 if (opts
->present
& DL_OPT_SB_TYPE
)
858 mnl_attr_put_u8(nlh
, DEVLINK_ATTR_SB_POOL_TYPE
,
860 if (opts
->present
& DL_OPT_SB_THTYPE
)
861 mnl_attr_put_u8(nlh
, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
,
862 opts
->sb_pool_thtype
);
863 if (opts
->present
& DL_OPT_SB_TH
)
864 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_SB_THRESHOLD
,
866 if (opts
->present
& DL_OPT_SB_TC
)
867 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_SB_TC_INDEX
,
871 static int dl_argv_parse_put(struct nlmsghdr
*nlh
, struct dl
*dl
,
872 uint32_t o_required
, uint32_t o_optional
)
876 err
= dl_argv_parse(dl
, o_required
, o_optional
);
879 dl_opts_put(nlh
, dl
);
883 static bool dl_dump_filter(struct dl
*dl
, struct nlattr
**tb
)
885 struct dl_opts
*opts
= &dl
->opts
;
886 struct nlattr
*attr_bus_name
= tb
[DEVLINK_ATTR_BUS_NAME
];
887 struct nlattr
*attr_dev_name
= tb
[DEVLINK_ATTR_DEV_NAME
];
888 struct nlattr
*attr_port_index
= tb
[DEVLINK_ATTR_PORT_INDEX
];
889 struct nlattr
*attr_sb_index
= tb
[DEVLINK_ATTR_SB_INDEX
];
891 if (opts
->present
& DL_OPT_HANDLE
&&
892 attr_bus_name
&& attr_dev_name
) {
893 const char *bus_name
= mnl_attr_get_str(attr_bus_name
);
894 const char *dev_name
= mnl_attr_get_str(attr_dev_name
);
896 if (strcmp(bus_name
, opts
->bus_name
) != 0 ||
897 strcmp(dev_name
, opts
->dev_name
) != 0)
900 if (opts
->present
& DL_OPT_HANDLEP
&&
901 attr_bus_name
&& attr_dev_name
&& attr_port_index
) {
902 const char *bus_name
= mnl_attr_get_str(attr_bus_name
);
903 const char *dev_name
= mnl_attr_get_str(attr_dev_name
);
904 uint32_t port_index
= mnl_attr_get_u32(attr_port_index
);
906 if (strcmp(bus_name
, opts
->bus_name
) != 0 ||
907 strcmp(dev_name
, opts
->dev_name
) != 0 ||
908 port_index
!= opts
->port_index
)
911 if (opts
->present
& DL_OPT_SB
&& attr_sb_index
) {
912 uint32_t sb_index
= mnl_attr_get_u32(attr_sb_index
);
914 if (sb_index
!= opts
->sb_index
)
920 static void cmd_dev_help(void)
922 pr_err("Usage: devlink dev show [ DEV ]\n");
925 static bool cmp_arr_last_handle(struct dl
*dl
, const char *bus_name
,
926 const char *dev_name
)
928 if (!dl
->arr_last
.present
)
930 return strcmp(dl
->arr_last
.bus_name
, bus_name
) == 0 &&
931 strcmp(dl
->arr_last
.dev_name
, dev_name
) == 0;
934 static void arr_last_handle_set(struct dl
*dl
, const char *bus_name
,
935 const char *dev_name
)
937 dl
->arr_last
.present
= true;
938 free(dl
->arr_last
.dev_name
);
939 free(dl
->arr_last
.bus_name
);
940 dl
->arr_last
.bus_name
= strdup(bus_name
);
941 dl
->arr_last
.dev_name
= strdup(dev_name
);
944 static bool should_arr_last_handle_start(struct dl
*dl
, const char *bus_name
,
945 const char *dev_name
)
947 return !cmp_arr_last_handle(dl
, bus_name
, dev_name
);
950 static bool should_arr_last_handle_end(struct dl
*dl
, const char *bus_name
,
951 const char *dev_name
)
953 return dl
->arr_last
.present
&&
954 !cmp_arr_last_handle(dl
, bus_name
, dev_name
);
957 static void __pr_out_handle_start(struct dl
*dl
, struct nlattr
**tb
,
958 bool content
, bool array
)
960 const char *bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
961 const char *dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
964 sprintf(buf
, "%s/%s", bus_name
, dev_name
);
966 if (dl
->json_output
) {
968 if (should_arr_last_handle_end(dl
, bus_name
, dev_name
))
969 jsonw_end_array(dl
->jw
);
970 if (should_arr_last_handle_start(dl
, bus_name
,
972 jsonw_name(dl
->jw
, buf
);
973 jsonw_start_array(dl
->jw
);
974 jsonw_start_object(dl
->jw
);
975 arr_last_handle_set(dl
, bus_name
, dev_name
);
977 jsonw_start_object(dl
->jw
);
980 jsonw_name(dl
->jw
, buf
);
981 jsonw_start_object(dl
->jw
);
984 pr_out("%s%s", buf
, content
? ":" : "");
988 static void pr_out_handle_start_arr(struct dl
*dl
, struct nlattr
**tb
)
990 __pr_out_handle_start(dl
, tb
, true, true);
993 static void pr_out_handle_end(struct dl
*dl
)
996 jsonw_end_object(dl
->jw
);
1001 static void pr_out_handle(struct dl
*dl
, struct nlattr
**tb
)
1003 __pr_out_handle_start(dl
, tb
, false, false);
1004 pr_out_handle_end(dl
);
1007 static bool cmp_arr_last_port_handle(struct dl
*dl
, const char *bus_name
,
1008 const char *dev_name
, uint32_t port_index
)
1010 return cmp_arr_last_handle(dl
, bus_name
, dev_name
) &&
1011 dl
->arr_last
.port_index
== port_index
;
1014 static void arr_last_port_handle_set(struct dl
*dl
, const char *bus_name
,
1015 const char *dev_name
, uint32_t port_index
)
1017 arr_last_handle_set(dl
, bus_name
, dev_name
);
1018 dl
->arr_last
.port_index
= port_index
;
1021 static bool should_arr_last_port_handle_start(struct dl
*dl
,
1022 const char *bus_name
,
1023 const char *dev_name
,
1024 uint32_t port_index
)
1026 return !cmp_arr_last_port_handle(dl
, bus_name
, dev_name
, port_index
);
1029 static bool should_arr_last_port_handle_end(struct dl
*dl
,
1030 const char *bus_name
,
1031 const char *dev_name
,
1032 uint32_t port_index
)
1034 return dl
->arr_last
.present
&&
1035 !cmp_arr_last_port_handle(dl
, bus_name
, dev_name
, port_index
);
1038 static void __pr_out_port_handle_start(struct dl
*dl
, const char *bus_name
,
1039 const char *dev_name
,
1040 uint32_t port_index
, bool try_nice
,
1043 static char buf
[32];
1044 char *ifname
= NULL
;
1046 if (dl
->no_nice_names
|| !try_nice
||
1047 ifname_map_rev_lookup(dl
, bus_name
, dev_name
,
1048 port_index
, &ifname
) != 0)
1049 sprintf(buf
, "%s/%s/%d", bus_name
, dev_name
, port_index
);
1051 sprintf(buf
, "%s", ifname
);
1053 if (dl
->json_output
) {
1055 if (should_arr_last_port_handle_end(dl
, bus_name
,
1058 jsonw_end_array(dl
->jw
);
1059 if (should_arr_last_port_handle_start(dl
, bus_name
,
1062 jsonw_name(dl
->jw
, buf
);
1063 jsonw_start_array(dl
->jw
);
1064 jsonw_start_object(dl
->jw
);
1065 arr_last_port_handle_set(dl
, bus_name
, dev_name
,
1068 jsonw_start_object(dl
->jw
);
1071 jsonw_name(dl
->jw
, buf
);
1072 jsonw_start_object(dl
->jw
);
1079 static void pr_out_port_handle_start(struct dl
*dl
, struct nlattr
**tb
, bool try_nice
)
1081 const char *bus_name
;
1082 const char *dev_name
;
1083 uint32_t port_index
;
1085 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
1086 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
1087 port_index
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
1088 __pr_out_port_handle_start(dl
, bus_name
, dev_name
, port_index
, try_nice
, false);
1091 static void pr_out_port_handle_start_arr(struct dl
*dl
, struct nlattr
**tb
, bool try_nice
)
1093 const char *bus_name
;
1094 const char *dev_name
;
1095 uint32_t port_index
;
1097 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
1098 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
1099 port_index
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
1100 __pr_out_port_handle_start(dl
, bus_name
, dev_name
, port_index
, try_nice
, true);
1103 static void pr_out_port_handle_end(struct dl
*dl
)
1105 if (dl
->json_output
)
1106 jsonw_end_object(dl
->jw
);
1112 static void pr_out_str(struct dl
*dl
, const char *name
, const char *val
)
1114 if (dl
->json_output
)
1115 jsonw_string_field(dl
->jw
, name
, val
);
1117 pr_out(" %s %s", name
, val
);
1120 static void pr_out_uint(struct dl
*dl
, const char *name
, unsigned int val
)
1122 if (dl
->json_output
)
1123 jsonw_uint_field(dl
->jw
, name
, val
);
1125 pr_out(" %s %u", name
, val
);
1128 static void pr_out_dev(struct dl
*dl
, struct nlattr
**tb
)
1130 pr_out_handle(dl
, tb
);
1133 static void pr_out_section_start(struct dl
*dl
, const char *name
)
1135 if (dl
->json_output
) {
1136 jsonw_start_object(dl
->jw
);
1137 jsonw_name(dl
->jw
, name
);
1138 jsonw_start_object(dl
->jw
);
1142 static void pr_out_section_end(struct dl
*dl
)
1144 if (dl
->json_output
) {
1145 if (dl
->arr_last
.present
)
1146 jsonw_end_array(dl
->jw
);
1147 jsonw_end_object(dl
->jw
);
1148 jsonw_end_object(dl
->jw
);
1152 static int cmd_dev_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1154 struct dl
*dl
= data
;
1155 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1156 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1158 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1159 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
1160 return MNL_CB_ERROR
;
1165 static int cmd_dev_show(struct dl
*dl
)
1167 struct nlmsghdr
*nlh
;
1168 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1171 if (dl_argc(dl
) == 0)
1172 flags
|= NLM_F_DUMP
;
1174 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_GET
, flags
);
1176 if (dl_argc(dl
) > 0) {
1177 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, 0);
1182 pr_out_section_start(dl
, "dev");
1183 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_dev_show_cb
, dl
);
1184 pr_out_section_end(dl
);
1188 static int cmd_dev(struct dl
*dl
)
1190 if (dl_argv_match(dl
, "help")) {
1193 } else if (dl_argv_match(dl
, "show") ||
1194 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1196 return cmd_dev_show(dl
);
1198 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1202 static void cmd_port_help(void)
1204 pr_err("Usage: devlink port show [ DEV/PORT_INDEX ]\n");
1205 pr_err(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
1206 pr_err(" devlink port split DEV/PORT_INDEX count COUNT\n");
1207 pr_err(" devlink port unsplit DEV/PORT_INDEX\n");
1210 static const char *port_type_name(uint32_t type
)
1213 case DEVLINK_PORT_TYPE_NOTSET
: return "notset";
1214 case DEVLINK_PORT_TYPE_AUTO
: return "auto";
1215 case DEVLINK_PORT_TYPE_ETH
: return "eth";
1216 case DEVLINK_PORT_TYPE_IB
: return "ib";
1217 default: return "<unknown type>";
1221 static void pr_out_port(struct dl
*dl
, struct nlattr
**tb
)
1223 struct nlattr
*pt_attr
= tb
[DEVLINK_ATTR_PORT_TYPE
];
1224 struct nlattr
*dpt_attr
= tb
[DEVLINK_ATTR_PORT_DESIRED_TYPE
];
1226 pr_out_port_handle_start(dl
, tb
, false);
1228 uint16_t port_type
= mnl_attr_get_u16(pt_attr
);
1230 pr_out_str(dl
, "type", port_type_name(port_type
));
1232 uint16_t des_port_type
= mnl_attr_get_u16(dpt_attr
);
1234 if (port_type
!= des_port_type
)
1235 pr_out_str(dl
, "des_type",
1236 port_type_name(des_port_type
));
1239 if (tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
1240 pr_out_str(dl
, "netdev",
1241 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]));
1242 if (tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
])
1243 pr_out_str(dl
, "ibdev",
1244 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
]));
1245 if (tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
])
1246 pr_out_uint(dl
, "split_group",
1247 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
]));
1248 pr_out_port_handle_end(dl
);
1251 static int cmd_port_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1253 struct dl
*dl
= data
;
1254 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1255 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1257 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1258 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1259 !tb
[DEVLINK_ATTR_PORT_INDEX
])
1260 return MNL_CB_ERROR
;
1261 pr_out_port(dl
, tb
);
1265 static int cmd_port_show(struct dl
*dl
)
1267 struct nlmsghdr
*nlh
;
1268 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1271 if (dl_argc(dl
) == 0)
1272 flags
|= NLM_F_DUMP
;
1274 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
, flags
);
1276 if (dl_argc(dl
) > 0) {
1277 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
1282 pr_out_section_start(dl
, "port");
1283 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_port_show_cb
, dl
);
1284 pr_out_section_end(dl
);
1288 static int cmd_port_set(struct dl
*dl
)
1290 struct nlmsghdr
*nlh
;
1293 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SET
,
1294 NLM_F_REQUEST
| NLM_F_ACK
);
1296 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_TYPE
, 0);
1300 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1303 static int cmd_port_split(struct dl
*dl
)
1305 struct nlmsghdr
*nlh
;
1308 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SPLIT
,
1309 NLM_F_REQUEST
| NLM_F_ACK
);
1311 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_COUNT
, 0);
1315 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1318 static int cmd_port_unsplit(struct dl
*dl
)
1320 struct nlmsghdr
*nlh
;
1323 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_UNSPLIT
,
1324 NLM_F_REQUEST
| NLM_F_ACK
);
1326 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
1330 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1333 static int cmd_port(struct dl
*dl
)
1335 if (dl_argv_match(dl
, "help")) {
1338 } else if (dl_argv_match(dl
, "show") ||
1339 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1341 return cmd_port_show(dl
);
1342 } else if (dl_argv_match(dl
, "set")) {
1344 return cmd_port_set(dl
);
1345 } else if (dl_argv_match(dl
, "split")) {
1347 return cmd_port_split(dl
);
1348 } else if (dl_argv_match(dl
, "unsplit")) {
1350 return cmd_port_unsplit(dl
);
1352 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1356 static void cmd_sb_help(void)
1358 pr_err("Usage: devlink sb show [ DEV [ sb SB_INDEX ] ]\n");
1359 pr_err(" devlink sb pool show [ DEV [ sb SB_INDEX ] pool POOL_INDEX ]\n");
1360 pr_err(" devlink sb pool set DEV [ sb SB_INDEX ] pool POOL_INDEX\n");
1361 pr_err(" size POOL_SIZE thtype { static | dynamic }\n");
1362 pr_err(" devlink sb port pool show [ DEV/PORT_INDEX [ sb SB_INDEX ]\n");
1363 pr_err(" pool POOL_INDEX ]\n");
1364 pr_err(" devlink sb port pool set DEV/PORT_INDEX [ sb SB_INDEX ]\n");
1365 pr_err(" pool POOL_INDEX th THRESHOLD\n");
1366 pr_err(" devlink sb tc bind show [ DEV/PORT_INDEX [ sb SB_INDEX ] tc TC_INDEX\n");
1367 pr_err(" type { ingress | egress } ]\n");
1368 pr_err(" devlink sb tc bind set DEV/PORT_INDEX [ sb SB_INDEX ] tc TC_INDEX\n");
1369 pr_err(" type { ingress | egress } pool POOL_INDEX\n");
1370 pr_err(" th THRESHOLD\n");
1371 pr_err(" devlink sb occupancy show { DEV | DEV/PORT_INDEX } [ sb SB_INDEX ]\n");
1372 pr_err(" devlink sb occupancy snapshot DEV [ sb SB_INDEX ]\n");
1373 pr_err(" devlink sb occupancy clearmax DEV [ sb SB_INDEX ]\n");
1376 static void pr_out_sb(struct dl
*dl
, struct nlattr
**tb
)
1378 pr_out_handle_start_arr(dl
, tb
);
1379 pr_out_uint(dl
, "sb",
1380 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]));
1381 pr_out_uint(dl
, "size",
1382 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_SIZE
]));
1383 pr_out_uint(dl
, "ing_pools",
1384 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_INGRESS_POOL_COUNT
]));
1385 pr_out_uint(dl
, "eg_pools",
1386 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_EGRESS_POOL_COUNT
]));
1387 pr_out_uint(dl
, "ing_tcs",
1388 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_INGRESS_TC_COUNT
]));
1389 pr_out_uint(dl
, "eg_tcs",
1390 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_EGRESS_TC_COUNT
]));
1391 pr_out_handle_end(dl
);
1394 static int cmd_sb_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1396 struct dl
*dl
= data
;
1397 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1398 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1400 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1401 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1402 !tb
[DEVLINK_ATTR_SB_INDEX
] || !tb
[DEVLINK_ATTR_SB_SIZE
] ||
1403 !tb
[DEVLINK_ATTR_SB_INGRESS_POOL_COUNT
] ||
1404 !tb
[DEVLINK_ATTR_SB_EGRESS_POOL_COUNT
] ||
1405 !tb
[DEVLINK_ATTR_SB_INGRESS_TC_COUNT
] ||
1406 !tb
[DEVLINK_ATTR_SB_EGRESS_TC_COUNT
])
1407 return MNL_CB_ERROR
;
1412 static int cmd_sb_show(struct dl
*dl
)
1414 struct nlmsghdr
*nlh
;
1415 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1418 if (dl_argc(dl
) == 0)
1419 flags
|= NLM_F_DUMP
;
1421 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_GET
, flags
);
1423 if (dl_argc(dl
) > 0) {
1424 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, DL_OPT_SB
);
1429 pr_out_section_start(dl
, "sb");
1430 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_show_cb
, dl
);
1431 pr_out_section_end(dl
);
1435 static const char *pool_type_name(uint8_t type
)
1438 case DEVLINK_SB_POOL_TYPE_INGRESS
: return "ingress";
1439 case DEVLINK_SB_POOL_TYPE_EGRESS
: return "egress";
1440 default: return "<unknown type>";
1444 static const char *threshold_type_name(uint8_t type
)
1447 case DEVLINK_SB_THRESHOLD_TYPE_STATIC
: return "static";
1448 case DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC
: return "dynamic";
1449 default: return "<unknown type>";
1453 static void pr_out_sb_pool(struct dl
*dl
, struct nlattr
**tb
)
1455 pr_out_handle_start_arr(dl
, tb
);
1456 pr_out_uint(dl
, "sb",
1457 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]));
1458 pr_out_uint(dl
, "pool",
1459 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]));
1460 pr_out_str(dl
, "type",
1461 pool_type_name(mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_TYPE
])));
1462 pr_out_uint(dl
, "size",
1463 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_POOL_SIZE
]));
1464 pr_out_str(dl
, "thtype",
1465 threshold_type_name(mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
])));
1466 pr_out_handle_end(dl
);
1469 static int cmd_sb_pool_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1471 struct dl
*dl
= data
;
1472 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1473 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1475 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1476 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1477 !tb
[DEVLINK_ATTR_SB_INDEX
] || !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] ||
1478 !tb
[DEVLINK_ATTR_SB_POOL_TYPE
] || !tb
[DEVLINK_ATTR_SB_POOL_SIZE
] ||
1479 !tb
[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
])
1480 return MNL_CB_ERROR
;
1481 pr_out_sb_pool(dl
, tb
);
1485 static int cmd_sb_pool_show(struct dl
*dl
)
1487 struct nlmsghdr
*nlh
;
1488 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1491 if (dl_argc(dl
) == 0)
1492 flags
|= NLM_F_DUMP
;
1494 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_POOL_GET
, flags
);
1496 if (dl_argc(dl
) > 0) {
1497 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
| DL_OPT_SB_POOL
,
1503 pr_out_section_start(dl
, "pool");
1504 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_pool_show_cb
, dl
);
1505 pr_out_section_end(dl
);
1509 static int cmd_sb_pool_set(struct dl
*dl
)
1511 struct nlmsghdr
*nlh
;
1514 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_POOL_SET
,
1515 NLM_F_REQUEST
| NLM_F_ACK
);
1517 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
| DL_OPT_SB_POOL
|
1518 DL_OPT_SB_SIZE
| DL_OPT_SB_THTYPE
, DL_OPT_SB
);
1522 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1525 static int cmd_sb_pool(struct dl
*dl
)
1527 if (dl_argv_match(dl
, "help")) {
1530 } else if (dl_argv_match(dl
, "show") ||
1531 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1533 return cmd_sb_pool_show(dl
);
1534 } else if (dl_argv_match(dl
, "set")) {
1536 return cmd_sb_pool_set(dl
);
1538 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1542 static void pr_out_sb_port_pool(struct dl
*dl
, struct nlattr
**tb
)
1544 pr_out_port_handle_start_arr(dl
, tb
, true);
1545 pr_out_uint(dl
, "sb",
1546 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]));
1547 pr_out_uint(dl
, "pool",
1548 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]));
1549 pr_out_uint(dl
, "threshold",
1550 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_THRESHOLD
]));
1551 pr_out_port_handle_end(dl
);
1554 static int cmd_sb_port_pool_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1556 struct dl
*dl
= data
;
1557 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1558 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1560 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1561 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1562 !tb
[DEVLINK_ATTR_PORT_INDEX
] || !tb
[DEVLINK_ATTR_SB_INDEX
] ||
1563 !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] || !tb
[DEVLINK_ATTR_SB_THRESHOLD
])
1564 return MNL_CB_ERROR
;
1565 pr_out_sb_port_pool(dl
, tb
);
1569 static int cmd_sb_port_pool_show(struct dl
*dl
)
1571 struct nlmsghdr
*nlh
;
1572 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1575 if (dl_argc(dl
) == 0)
1576 flags
|= NLM_F_DUMP
;
1578 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_PORT_POOL_GET
, flags
);
1580 if (dl_argc(dl
) > 0) {
1581 err
= dl_argv_parse_put(nlh
, dl
,
1582 DL_OPT_HANDLEP
| DL_OPT_SB_POOL
,
1588 pr_out_section_start(dl
, "port_pool");
1589 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_port_pool_show_cb
, dl
);
1590 pr_out_section_end(dl
);
1594 static int cmd_sb_port_pool_set(struct dl
*dl
)
1596 struct nlmsghdr
*nlh
;
1599 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_PORT_POOL_SET
,
1600 NLM_F_REQUEST
| NLM_F_ACK
);
1602 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_SB_POOL
|
1603 DL_OPT_SB_TH
, DL_OPT_SB
);
1607 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1610 static int cmd_sb_port_pool(struct dl
*dl
)
1612 if (dl_argv_match(dl
, "help")) {
1615 } else if (dl_argv_match(dl
, "show") ||
1616 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1618 return cmd_sb_port_pool_show(dl
);
1619 } else if (dl_argv_match(dl
, "set")) {
1621 return cmd_sb_port_pool_set(dl
);
1623 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1627 static int cmd_sb_port(struct dl
*dl
)
1629 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
1632 } else if (dl_argv_match(dl
, "pool")) {
1634 return cmd_sb_port_pool(dl
);
1636 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1640 static void pr_out_sb_tc_bind(struct dl
*dl
, struct nlattr
**tb
)
1642 pr_out_port_handle_start_arr(dl
, tb
, true);
1643 pr_out_uint(dl
, "sb",
1644 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]));
1645 pr_out_uint(dl
, "tc",
1646 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_TC_INDEX
]));
1647 pr_out_str(dl
, "type",
1648 pool_type_name(mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_TYPE
])));
1649 pr_out_uint(dl
, "pool",
1650 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]));
1651 pr_out_uint(dl
, "threshold",
1652 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_THRESHOLD
]));
1653 pr_out_port_handle_end(dl
);
1656 static int cmd_sb_tc_bind_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1658 struct dl
*dl
= data
;
1659 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1660 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1662 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1663 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1664 !tb
[DEVLINK_ATTR_PORT_INDEX
] || !tb
[DEVLINK_ATTR_SB_INDEX
] ||
1665 !tb
[DEVLINK_ATTR_SB_TC_INDEX
] || !tb
[DEVLINK_ATTR_SB_POOL_TYPE
] ||
1666 !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] || !tb
[DEVLINK_ATTR_SB_THRESHOLD
])
1667 return MNL_CB_ERROR
;
1668 pr_out_sb_tc_bind(dl
, tb
);
1672 static int cmd_sb_tc_bind_show(struct dl
*dl
)
1674 struct nlmsghdr
*nlh
;
1675 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1678 if (dl_argc(dl
) == 0)
1679 flags
|= NLM_F_DUMP
;
1681 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_TC_POOL_BIND_GET
, flags
);
1683 if (dl_argc(dl
) > 0) {
1684 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_SB_TC
|
1685 DL_OPT_SB_TYPE
, DL_OPT_SB
);
1690 pr_out_section_start(dl
, "tc_bind");
1691 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_tc_bind_show_cb
, dl
);
1692 pr_out_section_end(dl
);
1696 static int cmd_sb_tc_bind_set(struct dl
*dl
)
1698 struct nlmsghdr
*nlh
;
1701 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_TC_POOL_BIND_SET
,
1702 NLM_F_REQUEST
| NLM_F_ACK
);
1704 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_SB_TC
|
1705 DL_OPT_SB_TYPE
| DL_OPT_SB_POOL
| DL_OPT_SB_TH
,
1710 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1713 static int cmd_sb_tc_bind(struct dl
*dl
)
1715 if (dl_argv_match(dl
, "help")) {
1718 } else if (dl_argv_match(dl
, "show") ||
1719 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1721 return cmd_sb_tc_bind_show(dl
);
1722 } else if (dl_argv_match(dl
, "set")) {
1724 return cmd_sb_tc_bind_set(dl
);
1726 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1730 static int cmd_sb_tc(struct dl
*dl
)
1732 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
1735 } else if (dl_argv_match(dl
, "bind")) {
1737 return cmd_sb_tc_bind(dl
);
1739 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1744 struct list_head list
;
1748 uint32_t bound_pool_index
;
1752 struct list_head list
;
1755 uint32_t port_index
;
1757 struct list_head pool_list
;
1758 struct list_head ing_tc_list
;
1759 struct list_head eg_tc_list
;
1765 struct list_head port_list
;
1768 static struct occ_item
*occ_item_alloc(void)
1770 return calloc(1, sizeof(struct occ_item
));
1773 static void occ_item_free(struct occ_item
*occ_item
)
1778 static struct occ_port
*occ_port_alloc(uint32_t port_index
)
1780 struct occ_port
*occ_port
;
1782 occ_port
= calloc(1, sizeof(*occ_port
));
1785 occ_port
->port_index
= port_index
;
1786 INIT_LIST_HEAD(&occ_port
->pool_list
);
1787 INIT_LIST_HEAD(&occ_port
->ing_tc_list
);
1788 INIT_LIST_HEAD(&occ_port
->eg_tc_list
);
1792 static void occ_port_free(struct occ_port
*occ_port
)
1794 struct occ_item
*occ_item
, *tmp
;
1796 list_for_each_entry_safe(occ_item
, tmp
, &occ_port
->pool_list
, list
)
1797 occ_item_free(occ_item
);
1798 list_for_each_entry_safe(occ_item
, tmp
, &occ_port
->ing_tc_list
, list
)
1799 occ_item_free(occ_item
);
1800 list_for_each_entry_safe(occ_item
, tmp
, &occ_port
->eg_tc_list
, list
)
1801 occ_item_free(occ_item
);
1804 static struct occ_show
*occ_show_alloc(struct dl
*dl
)
1806 struct occ_show
*occ_show
;
1808 occ_show
= calloc(1, sizeof(*occ_show
));
1812 INIT_LIST_HEAD(&occ_show
->port_list
);
1816 static void occ_show_free(struct occ_show
*occ_show
)
1818 struct occ_port
*occ_port
, *tmp
;
1820 list_for_each_entry_safe(occ_port
, tmp
, &occ_show
->port_list
, list
)
1821 occ_port_free(occ_port
);
1824 static struct occ_port
*occ_port_get(struct occ_show
*occ_show
,
1827 struct occ_port
*occ_port
;
1828 uint32_t port_index
;
1830 port_index
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
1832 list_for_each_entry_reverse(occ_port
, &occ_show
->port_list
, list
) {
1833 if (occ_port
->port_index
== port_index
)
1836 occ_port
= occ_port_alloc(port_index
);
1839 list_add_tail(&occ_port
->list
, &occ_show
->port_list
);
1843 static void pr_out_occ_show_item_list(const char *label
, struct list_head
*list
,
1846 struct occ_item
*occ_item
;
1849 pr_out_sp(7, " %s:", label
);
1850 list_for_each_entry(occ_item
, list
, list
) {
1851 if ((i
- 1) % 4 == 0 && i
!= 1)
1854 pr_out_sp(7, "%2u(%u):", occ_item
->index
,
1855 occ_item
->bound_pool_index
);
1857 pr_out_sp(7, "%2u:", occ_item
->index
);
1858 pr_out_sp(15, "%7u/%u", occ_item
->cur
, occ_item
->max
);
1862 if ((i
- 1) % 4 != 0)
1866 static void pr_out_json_occ_show_item_list(struct dl
*dl
, const char *label
,
1867 struct list_head
*list
,
1870 struct occ_item
*occ_item
;
1873 jsonw_name(dl
->jw
, label
);
1874 jsonw_start_object(dl
->jw
);
1875 list_for_each_entry(occ_item
, list
, list
) {
1876 sprintf(buf
, "%u", occ_item
->index
);
1877 jsonw_name(dl
->jw
, buf
);
1878 jsonw_start_object(dl
->jw
);
1880 jsonw_uint_field(dl
->jw
, "bound_pool",
1881 occ_item
->bound_pool_index
);
1882 jsonw_uint_field(dl
->jw
, "current", occ_item
->cur
);
1883 jsonw_uint_field(dl
->jw
, "max", occ_item
->max
);
1884 jsonw_end_object(dl
->jw
);
1886 jsonw_end_object(dl
->jw
);
1889 static void pr_out_occ_show_port(struct dl
*dl
, struct occ_port
*occ_port
)
1891 if (dl
->json_output
) {
1892 pr_out_json_occ_show_item_list(dl
, "pool",
1893 &occ_port
->pool_list
, false);
1894 pr_out_json_occ_show_item_list(dl
, "itc",
1895 &occ_port
->ing_tc_list
, true);
1896 pr_out_json_occ_show_item_list(dl
, "etc",
1897 &occ_port
->eg_tc_list
, true);
1900 pr_out_occ_show_item_list("pool", &occ_port
->pool_list
, false);
1901 pr_out_occ_show_item_list("itc", &occ_port
->ing_tc_list
, true);
1902 pr_out_occ_show_item_list("etc", &occ_port
->eg_tc_list
, true);
1906 static void pr_out_occ_show(struct occ_show
*occ_show
)
1908 struct dl
*dl
= occ_show
->dl
;
1909 struct dl_opts
*opts
= &dl
->opts
;
1910 struct occ_port
*occ_port
;
1912 list_for_each_entry(occ_port
, &occ_show
->port_list
, list
) {
1913 __pr_out_port_handle_start(dl
, opts
->bus_name
, opts
->dev_name
,
1914 occ_port
->port_index
, true, false);
1915 pr_out_occ_show_port(dl
, occ_port
);
1916 pr_out_port_handle_end(dl
);
1920 static void cmd_sb_occ_port_pool_process(struct occ_show
*occ_show
,
1923 struct occ_port
*occ_port
;
1924 struct occ_item
*occ_item
;
1926 if (occ_show
->err
|| !dl_dump_filter(occ_show
->dl
, tb
))
1929 occ_port
= occ_port_get(occ_show
, tb
);
1931 occ_show
->err
= -ENOMEM
;
1935 occ_item
= occ_item_alloc();
1937 occ_show
->err
= -ENOMEM
;
1940 occ_item
->index
= mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]);
1941 occ_item
->cur
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_OCC_CUR
]);
1942 occ_item
->max
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_OCC_MAX
]);
1943 list_add_tail(&occ_item
->list
, &occ_port
->pool_list
);
1946 static int cmd_sb_occ_port_pool_process_cb(const struct nlmsghdr
*nlh
, void *data
)
1948 struct occ_show
*occ_show
= data
;
1949 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1950 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1952 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1953 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1954 !tb
[DEVLINK_ATTR_PORT_INDEX
] || !tb
[DEVLINK_ATTR_SB_INDEX
] ||
1955 !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] ||
1956 !tb
[DEVLINK_ATTR_SB_OCC_CUR
] || !tb
[DEVLINK_ATTR_SB_OCC_MAX
])
1957 return MNL_CB_ERROR
;
1958 cmd_sb_occ_port_pool_process(occ_show
, tb
);
1962 static void cmd_sb_occ_tc_pool_process(struct occ_show
*occ_show
,
1965 struct occ_port
*occ_port
;
1966 struct occ_item
*occ_item
;
1969 if (occ_show
->err
|| !dl_dump_filter(occ_show
->dl
, tb
))
1972 occ_port
= occ_port_get(occ_show
, tb
);
1974 occ_show
->err
= -ENOMEM
;
1978 occ_item
= occ_item_alloc();
1980 occ_show
->err
= -ENOMEM
;
1983 occ_item
->index
= mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_TC_INDEX
]);
1984 occ_item
->cur
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_OCC_CUR
]);
1985 occ_item
->max
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_OCC_MAX
]);
1986 occ_item
->bound_pool_index
=
1987 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]);
1988 pool_type
= mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_TYPE
]);
1989 if (pool_type
== DEVLINK_SB_POOL_TYPE_INGRESS
)
1990 list_add_tail(&occ_item
->list
, &occ_port
->ing_tc_list
);
1991 else if (pool_type
== DEVLINK_SB_POOL_TYPE_EGRESS
)
1992 list_add_tail(&occ_item
->list
, &occ_port
->eg_tc_list
);
1994 occ_item_free(occ_item
);
1997 static int cmd_sb_occ_tc_pool_process_cb(const struct nlmsghdr
*nlh
, void *data
)
1999 struct occ_show
*occ_show
= data
;
2000 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
2001 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
2003 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
2004 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
2005 !tb
[DEVLINK_ATTR_PORT_INDEX
] || !tb
[DEVLINK_ATTR_SB_INDEX
] ||
2006 !tb
[DEVLINK_ATTR_SB_TC_INDEX
] || !tb
[DEVLINK_ATTR_SB_POOL_TYPE
] ||
2007 !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] ||
2008 !tb
[DEVLINK_ATTR_SB_OCC_CUR
] || !tb
[DEVLINK_ATTR_SB_OCC_MAX
])
2009 return MNL_CB_ERROR
;
2010 cmd_sb_occ_tc_pool_process(occ_show
, tb
);
2014 static int cmd_sb_occ_show(struct dl
*dl
)
2016 struct nlmsghdr
*nlh
;
2017 struct occ_show
*occ_show
;
2018 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
;
2021 err
= dl_argv_parse(dl
, DL_OPT_HANDLE
| DL_OPT_HANDLEP
, DL_OPT_SB
);
2025 occ_show
= occ_show_alloc(dl
);
2029 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_PORT_POOL_GET
, flags
);
2031 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
,
2032 cmd_sb_occ_port_pool_process_cb
, occ_show
);
2036 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_TC_POOL_BIND_GET
, flags
);
2038 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
,
2039 cmd_sb_occ_tc_pool_process_cb
, occ_show
);
2043 pr_out_section_start(dl
, "occupancy");
2044 pr_out_occ_show(occ_show
);
2045 pr_out_section_end(dl
);
2048 occ_show_free(occ_show
);
2052 static int cmd_sb_occ_snapshot(struct dl
*dl
)
2054 struct nlmsghdr
*nlh
;
2057 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_OCC_SNAPSHOT
,
2058 NLM_F_REQUEST
| NLM_F_ACK
);
2060 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, DL_OPT_SB
);
2064 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
2067 static int cmd_sb_occ_clearmax(struct dl
*dl
)
2069 struct nlmsghdr
*nlh
;
2072 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_OCC_MAX_CLEAR
,
2073 NLM_F_REQUEST
| NLM_F_ACK
);
2075 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, DL_OPT_SB
);
2079 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
2082 static int cmd_sb_occ(struct dl
*dl
)
2084 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
2087 } else if (dl_argv_match(dl
, "show") ||
2088 dl_argv_match(dl
, "list")) {
2090 return cmd_sb_occ_show(dl
);
2091 } else if (dl_argv_match(dl
, "snapshot")) {
2093 return cmd_sb_occ_snapshot(dl
);
2094 } else if (dl_argv_match(dl
, "clearmax")) {
2096 return cmd_sb_occ_clearmax(dl
);
2098 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
2102 static int cmd_sb(struct dl
*dl
)
2104 if (dl_argv_match(dl
, "help")) {
2107 } else if (dl_argv_match(dl
, "show") ||
2108 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
2110 return cmd_sb_show(dl
);
2111 } else if (dl_argv_match(dl
, "pool")) {
2113 return cmd_sb_pool(dl
);
2114 } else if (dl_argv_match(dl
, "port")) {
2116 return cmd_sb_port(dl
);
2117 } else if (dl_argv_match(dl
, "tc")) {
2119 return cmd_sb_tc(dl
);
2120 } else if (dl_argv_match(dl
, "occupancy")) {
2122 return cmd_sb_occ(dl
);
2124 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
2128 static const char *cmd_name(uint8_t cmd
)
2131 case DEVLINK_CMD_UNSPEC
: return "unspec";
2132 case DEVLINK_CMD_GET
: return "get";
2133 case DEVLINK_CMD_SET
: return "set";
2134 case DEVLINK_CMD_NEW
: return "new";
2135 case DEVLINK_CMD_DEL
: return "del";
2136 case DEVLINK_CMD_PORT_GET
: return "get";
2137 case DEVLINK_CMD_PORT_SET
: return "set";
2138 case DEVLINK_CMD_PORT_NEW
: return "net";
2139 case DEVLINK_CMD_PORT_DEL
: return "del";
2140 default: return "<unknown cmd>";
2144 static const char *cmd_obj(uint8_t cmd
)
2147 case DEVLINK_CMD_UNSPEC
: return "unspec";
2148 case DEVLINK_CMD_GET
:
2149 case DEVLINK_CMD_SET
:
2150 case DEVLINK_CMD_NEW
:
2151 case DEVLINK_CMD_DEL
:
2153 case DEVLINK_CMD_PORT_GET
:
2154 case DEVLINK_CMD_PORT_SET
:
2155 case DEVLINK_CMD_PORT_NEW
:
2156 case DEVLINK_CMD_PORT_DEL
:
2158 default: return "<unknown obj>";
2162 static void pr_out_mon_header(uint8_t cmd
)
2164 pr_out("[%s,%s] ", cmd_obj(cmd
), cmd_name(cmd
));
2167 static bool cmd_filter_check(struct dl
*dl
, uint8_t cmd
)
2169 const char *obj
= cmd_obj(cmd
);
2170 unsigned int index
= 0;
2171 const char *cur_obj
;
2175 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
2176 if (strcmp(cur_obj
, obj
) == 0 || strcmp(cur_obj
, "all") == 0)
2182 static int cmd_mon_show_cb(const struct nlmsghdr
*nlh
, void *data
)
2184 struct dl
*dl
= data
;
2185 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
2186 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
2187 uint8_t cmd
= genl
->cmd
;
2189 if (!cmd_filter_check(dl
, cmd
))
2193 case DEVLINK_CMD_GET
: /* fall through */
2194 case DEVLINK_CMD_SET
: /* fall through */
2195 case DEVLINK_CMD_NEW
: /* fall through */
2196 case DEVLINK_CMD_DEL
:
2197 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
2198 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
2199 return MNL_CB_ERROR
;
2200 pr_out_mon_header(genl
->cmd
);
2203 case DEVLINK_CMD_PORT_GET
: /* fall through */
2204 case DEVLINK_CMD_PORT_SET
: /* fall through */
2205 case DEVLINK_CMD_PORT_NEW
: /* fall through */
2206 case DEVLINK_CMD_PORT_DEL
:
2207 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
2208 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
2209 !tb
[DEVLINK_ATTR_PORT_INDEX
])
2210 return MNL_CB_ERROR
;
2211 pr_out_mon_header(genl
->cmd
);
2212 pr_out_port(dl
, tb
);
2218 static int cmd_mon_show(struct dl
*dl
)
2221 unsigned int index
= 0;
2222 const char *cur_obj
;
2224 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
2225 if (strcmp(cur_obj
, "all") != 0 &&
2226 strcmp(cur_obj
, "dev") != 0 &&
2227 strcmp(cur_obj
, "port") != 0) {
2228 pr_err("Unknown object \"%s\"\n", cur_obj
);
2232 err
= _mnlg_socket_group_add(dl
->nlg
, DEVLINK_GENL_MCGRP_CONFIG_NAME
);
2235 err
= _mnlg_socket_recv_run(dl
->nlg
, cmd_mon_show_cb
, dl
);
2241 static void cmd_mon_help(void)
2243 pr_err("Usage: devlink monitor [ all | OBJECT-LIST ]\n"
2244 "where OBJECT-LIST := { dev | port }\n");
2247 static int cmd_mon(struct dl
*dl
)
2249 if (dl_argv_match(dl
, "help")) {
2252 } else if (dl_no_arg(dl
)) {
2254 return cmd_mon_show(dl
);
2256 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
2260 static void help(void)
2262 pr_err("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
2263 "where OBJECT := { dev | port | sb | monitor }\n"
2264 " OPTIONS := { -V[ersion] | -n[no-nice-names] }\n");
2267 static int dl_cmd(struct dl
*dl
)
2269 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
2272 } else if (dl_argv_match(dl
, "dev")) {
2275 } else if (dl_argv_match(dl
, "port")) {
2277 return cmd_port(dl
);
2278 } else if (dl_argv_match(dl
, "sb")) {
2281 } else if (dl_argv_match(dl
, "monitor")) {
2285 pr_err("Object \"%s\" not found\n", dl_argv(dl
));
2289 static int dl_init(struct dl
*dl
, int argc
, char **argv
)
2296 dl
->nlg
= mnlg_socket_open(DEVLINK_GENL_NAME
, DEVLINK_GENL_VERSION
);
2298 pr_err("Failed to connect to devlink Netlink\n");
2302 err
= ifname_map_init(dl
);
2304 pr_err("Failed to create index map\n");
2305 goto err_ifname_map_create
;
2307 if (dl
->json_output
) {
2308 dl
->jw
= jsonw_new(stdout
);
2310 pr_err("Failed to create JSON writer\n");
2313 jsonw_pretty(dl
->jw
, dl
->pretty_output
);
2318 ifname_map_fini(dl
);
2319 err_ifname_map_create
:
2320 mnlg_socket_close(dl
->nlg
);
2324 static void dl_fini(struct dl
*dl
)
2326 if (dl
->json_output
)
2327 jsonw_destroy(&dl
->jw
);
2328 ifname_map_fini(dl
);
2329 mnlg_socket_close(dl
->nlg
);
2332 static struct dl
*dl_alloc(void)
2336 dl
= calloc(1, sizeof(*dl
));
2342 static void dl_free(struct dl
*dl
)
2347 int main(int argc
, char **argv
)
2349 static const struct option long_options
[] = {
2350 { "Version", no_argument
, NULL
, 'V' },
2351 { "no-nice-names", no_argument
, NULL
, 'n' },
2352 { "json", no_argument
, NULL
, 'j' },
2353 { "pretty", no_argument
, NULL
, 'p' },
2354 { NULL
, 0, NULL
, 0 }
2363 pr_err("Failed to allocate memory for devlink\n");
2364 return EXIT_FAILURE
;
2367 while ((opt
= getopt_long(argc
, argv
, "Vnjp",
2368 long_options
, NULL
)) >= 0) {
2372 printf("devlink utility, iproute2-ss%s\n", SNAPSHOT
);
2373 return EXIT_SUCCESS
;
2375 dl
->no_nice_names
= true;
2378 dl
->json_output
= true;
2381 dl
->pretty_output
= true;
2384 pr_err("Unknown option.\n");
2386 return EXIT_FAILURE
;
2393 err
= dl_init(dl
, argc
, argv
);