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>
28 #define pr_err(args...) fprintf(stderr, ##args)
29 #define pr_out(args...) fprintf(stdout, ##args)
31 static int _mnlg_socket_recv_run(struct mnlg_socket
*nlg
,
32 mnl_cb_t data_cb
, void *data
)
36 err
= mnlg_socket_recv_run(nlg
, data_cb
, data
);
38 pr_err("devlink answers: %s\n", strerror(errno
));
44 static int _mnlg_socket_sndrcv(struct mnlg_socket
*nlg
,
45 const struct nlmsghdr
*nlh
,
46 mnl_cb_t data_cb
, void *data
)
50 err
= mnlg_socket_send(nlg
, nlh
);
52 pr_err("Failed to call mnlg_socket_send\n");
55 return _mnlg_socket_recv_run(nlg
, data_cb
, data
);
58 static int _mnlg_socket_group_add(struct mnlg_socket
*nlg
,
59 const char *group_name
)
63 err
= mnlg_socket_group_add(nlg
, group_name
);
65 pr_err("Failed to call mnlg_socket_group_add\n");
72 struct list_head list
;
79 static struct ifname_map
*ifname_map_alloc(const char *bus_name
,
84 struct ifname_map
*ifname_map
;
86 ifname_map
= calloc(1, sizeof(*ifname_map
));
89 ifname_map
->bus_name
= strdup(bus_name
);
90 ifname_map
->dev_name
= strdup(dev_name
);
91 ifname_map
->port_index
= port_index
;
92 ifname_map
->ifname
= strdup(ifname
);
93 if (!ifname_map
->bus_name
|| !ifname_map
->dev_name
||
94 !ifname_map
->ifname
) {
95 free(ifname_map
->ifname
);
96 free(ifname_map
->dev_name
);
97 free(ifname_map
->bus_name
);
104 static void ifname_map_free(struct ifname_map
*ifname_map
)
106 free(ifname_map
->ifname
);
107 free(ifname_map
->dev_name
);
108 free(ifname_map
->bus_name
);
112 #define BIT(nr) (1UL << (nr))
113 #define DL_OPT_HANDLE BIT(0)
114 #define DL_OPT_HANDLEP BIT(1)
115 #define DL_OPT_PORT_TYPE BIT(2)
116 #define DL_OPT_PORT_COUNT BIT(3)
117 #define DL_OPT_SB BIT(4)
118 #define DL_OPT_SB_POOL BIT(5)
119 #define DL_OPT_SB_SIZE BIT(6)
120 #define DL_OPT_SB_TYPE BIT(7)
121 #define DL_OPT_SB_THTYPE BIT(8)
122 #define DL_OPT_SB_TH BIT(9)
123 #define DL_OPT_SB_TC BIT(10)
126 uint32_t present
; /* flags of present items */
130 enum devlink_port_type port_type
;
133 uint16_t sb_pool_index
;
134 uint32_t sb_pool_size
;
135 enum devlink_sb_pool_type sb_pool_type
;
136 enum devlink_sb_threshold_type sb_pool_thtype
;
137 uint32_t sb_threshold
;
138 uint16_t sb_tc_index
;
142 struct mnlg_socket
*nlg
;
143 struct list_head ifname_map_list
;
150 static int dl_argc(struct dl
*dl
)
155 static char *dl_argv(struct dl
*dl
)
157 if (dl_argc(dl
) == 0)
162 static void dl_arg_inc(struct dl
*dl
)
164 if (dl_argc(dl
) == 0)
170 static char *dl_argv_next(struct dl
*dl
)
174 if (dl_argc(dl
) == 0)
182 static char *dl_argv_index(struct dl
*dl
, unsigned int index
)
184 if (index
>= dl_argc(dl
))
186 return dl
->argv
[index
];
189 static int strcmpx(const char *str1
, const char *str2
)
191 if (strlen(str1
) > strlen(str2
))
193 return strncmp(str1
, str2
, strlen(str1
));
196 static bool dl_argv_match(struct dl
*dl
, const char *pattern
)
198 if (dl_argc(dl
) == 0)
200 return strcmpx(dl_argv(dl
), pattern
) == 0;
203 static bool dl_no_arg(struct dl
*dl
)
205 return dl_argc(dl
) == 0;
208 static int attr_cb(const struct nlattr
*attr
, void *data
)
210 const struct nlattr
**tb
= data
;
213 type
= mnl_attr_get_type(attr
);
215 if (mnl_attr_type_valid(attr
, DEVLINK_ATTR_MAX
) < 0)
218 if (type
== DEVLINK_ATTR_BUS_NAME
&&
219 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
221 if (type
== DEVLINK_ATTR_DEV_NAME
&&
222 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
224 if (type
== DEVLINK_ATTR_PORT_INDEX
&&
225 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
227 if (type
== DEVLINK_ATTR_PORT_TYPE
&&
228 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
230 if (type
== DEVLINK_ATTR_PORT_DESIRED_TYPE
&&
231 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
233 if (type
== DEVLINK_ATTR_PORT_NETDEV_IFINDEX
&&
234 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
236 if (type
== DEVLINK_ATTR_PORT_NETDEV_NAME
&&
237 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
239 if (type
== DEVLINK_ATTR_PORT_IBDEV_NAME
&&
240 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
242 if (type
== DEVLINK_ATTR_SB_INDEX
&&
243 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
245 if (type
== DEVLINK_ATTR_SB_SIZE
&&
246 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
248 if (type
== DEVLINK_ATTR_SB_INGRESS_POOL_COUNT
&&
249 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
251 if (type
== DEVLINK_ATTR_SB_EGRESS_POOL_COUNT
&&
252 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
254 if (type
== DEVLINK_ATTR_SB_INGRESS_TC_COUNT
&&
255 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
257 if (type
== DEVLINK_ATTR_SB_EGRESS_TC_COUNT
&&
258 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
260 if (type
== DEVLINK_ATTR_SB_POOL_INDEX
&&
261 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
263 if (type
== DEVLINK_ATTR_SB_POOL_TYPE
&&
264 mnl_attr_validate(attr
, MNL_TYPE_U8
) < 0)
266 if (type
== DEVLINK_ATTR_SB_POOL_SIZE
&&
267 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
269 if (type
== DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
&&
270 mnl_attr_validate(attr
, MNL_TYPE_U8
) < 0)
272 if (type
== DEVLINK_ATTR_SB_THRESHOLD
&&
273 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
275 if (type
== DEVLINK_ATTR_SB_TC_INDEX
&&
276 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
282 static int ifname_map_cb(const struct nlmsghdr
*nlh
, void *data
)
284 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
285 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
286 struct dl
*dl
= data
;
287 struct ifname_map
*ifname_map
;
288 const char *bus_name
;
289 const char *dev_name
;
290 uint32_t port_ifindex
;
291 const char *port_ifname
;
293 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
294 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
295 !tb
[DEVLINK_ATTR_PORT_INDEX
])
298 if (!tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
301 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
302 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
303 port_ifindex
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
304 port_ifname
= mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]);
305 ifname_map
= ifname_map_alloc(bus_name
, dev_name
,
306 port_ifindex
, port_ifname
);
309 list_add(&ifname_map
->list
, &dl
->ifname_map_list
);
314 static void ifname_map_fini(struct dl
*dl
)
316 struct ifname_map
*ifname_map
, *tmp
;
318 list_for_each_entry_safe(ifname_map
, tmp
,
319 &dl
->ifname_map_list
, list
) {
320 list_del(&ifname_map
->list
);
321 ifname_map_free(ifname_map
);
325 static int ifname_map_init(struct dl
*dl
)
327 struct nlmsghdr
*nlh
;
330 INIT_LIST_HEAD(&dl
->ifname_map_list
);
332 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
,
333 NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
);
335 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, ifname_map_cb
, dl
);
343 static int ifname_map_lookup(struct dl
*dl
, const char *ifname
,
344 char **p_bus_name
, char **p_dev_name
,
345 uint32_t *p_port_index
)
347 struct ifname_map
*ifname_map
;
349 list_for_each_entry(ifname_map
, &dl
->ifname_map_list
, list
) {
350 if (strcmp(ifname
, ifname_map
->ifname
) == 0) {
351 *p_bus_name
= ifname_map
->bus_name
;
352 *p_dev_name
= ifname_map
->dev_name
;
353 *p_port_index
= ifname_map
->port_index
;
360 static int ifname_map_rev_lookup(struct dl
*dl
, const char *bus_name
,
361 const char *dev_name
, uint32_t port_index
,
364 struct ifname_map
*ifname_map
;
366 list_for_each_entry(ifname_map
, &dl
->ifname_map_list
, list
) {
367 if (strcmp(bus_name
, ifname_map
->bus_name
) == 0 &&
368 strcmp(dev_name
, ifname_map
->dev_name
) == 0 &&
369 port_index
== ifname_map
->port_index
) {
370 *p_ifname
= ifname_map
->ifname
;
377 static unsigned int strslashcount(char *str
)
379 unsigned int count
= 0;
382 while ((pos
= strchr(pos
, '/'))) {
389 static int strslashrsplit(char *str
, char **before
, char **after
)
393 slash
= strrchr(str
, '/');
402 static int strtouint32_t(const char *str
, uint32_t *p_val
)
405 unsigned long int val
;
407 val
= strtoul(str
, &endptr
, 10);
408 if (endptr
== str
|| *endptr
!= '\0')
416 static int strtouint16_t(const char *str
, uint16_t *p_val
)
419 unsigned long int val
;
421 val
= strtoul(str
, &endptr
, 10);
422 if (endptr
== str
|| *endptr
!= '\0')
430 static int __dl_argv_handle(char *str
, char **p_bus_name
, char **p_dev_name
)
432 strslashrsplit(str
, p_bus_name
, p_dev_name
);
436 static int dl_argv_handle(struct dl
*dl
, char **p_bus_name
, char **p_dev_name
)
438 char *str
= dl_argv_next(dl
);
441 pr_err("Devlink identification (\"bus_name/dev_name\") expected\n");
444 if (strslashcount(str
) != 1) {
445 pr_err("Wrong devlink identification string format.\n");
446 pr_err("Expected \"bus_name/dev_name\".\n");
449 return __dl_argv_handle(str
, p_bus_name
, p_dev_name
);
452 static int __dl_argv_handle_port(char *str
,
453 char **p_bus_name
, char **p_dev_name
,
454 uint32_t *p_port_index
)
456 char *handlestr
= handlestr
;
457 char *portstr
= portstr
;
460 strslashrsplit(str
, &handlestr
, &portstr
);
461 err
= strtouint32_t(portstr
, p_port_index
);
463 pr_err("Port index \"%s\" is not a number or not within range\n",
467 strslashrsplit(handlestr
, p_bus_name
, p_dev_name
);
471 static int __dl_argv_handle_port_ifname(struct dl
*dl
, char *str
,
472 char **p_bus_name
, char **p_dev_name
,
473 uint32_t *p_port_index
)
477 err
= ifname_map_lookup(dl
, str
, p_bus_name
, p_dev_name
,
480 pr_err("Netdevice \"%s\" not found\n", str
);
486 static int dl_argv_handle_port(struct dl
*dl
, char **p_bus_name
,
487 char **p_dev_name
, uint32_t *p_port_index
)
489 char *str
= dl_argv_next(dl
);
490 unsigned int slash_count
;
493 pr_err("Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\") expected.\n");
496 slash_count
= strslashcount(str
);
497 if (slash_count
!= 2 && slash_count
!= 0) {
498 pr_err("Wrong port identification string format.\n");
499 pr_err("Expected \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
502 if (slash_count
== 2) {
503 return __dl_argv_handle_port(str
, p_bus_name
,
504 p_dev_name
, p_port_index
);
505 } else if (slash_count
== 0) {
506 return __dl_argv_handle_port_ifname(dl
, str
, p_bus_name
,
507 p_dev_name
, p_port_index
);
512 static int dl_argv_handle_both(struct dl
*dl
, char **p_bus_name
,
513 char **p_dev_name
, uint32_t *p_port_index
,
514 uint32_t *p_handle_bit
)
516 char *str
= dl_argv_next(dl
);
517 unsigned int slash_count
;
521 pr_err("One of following identifications expected:\n"
522 "Devlink identification (\"bus_name/dev_name\")\n"
523 "Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\")\n");
526 slash_count
= strslashcount(str
);
527 if (slash_count
== 1) {
528 err
= __dl_argv_handle(str
, p_bus_name
, p_dev_name
);
531 *p_handle_bit
= DL_OPT_HANDLE
;
532 } else if (slash_count
== 2) {
533 err
= __dl_argv_handle_port(str
, p_bus_name
,
534 p_dev_name
, p_port_index
);
537 *p_handle_bit
= DL_OPT_HANDLEP
;
538 } else if (slash_count
== 0) {
539 err
= __dl_argv_handle_port_ifname(dl
, str
, p_bus_name
,
540 p_dev_name
, p_port_index
);
543 *p_handle_bit
= DL_OPT_HANDLEP
;
545 pr_err("Wrong port identification string format.\n");
546 pr_err("Expected \"bus_name/dev_name\" or \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
552 static int dl_argv_uint32_t(struct dl
*dl
, uint32_t *p_val
)
554 char *str
= dl_argv_next(dl
);
558 pr_err("Unsigned number argument expected\n");
562 err
= strtouint32_t(str
, p_val
);
564 pr_err("\"%s\" is not a number or not within range\n", str
);
570 static int dl_argv_uint16_t(struct dl
*dl
, uint16_t *p_val
)
572 char *str
= dl_argv_next(dl
);
576 pr_err("Unsigned number argument expected\n");
580 err
= strtouint16_t(str
, p_val
);
582 pr_err("\"%s\" is not a number or not within range\n", str
);
588 static int dl_argv_str(struct dl
*dl
, const char **p_str
)
590 const char *str
= dl_argv_next(dl
);
593 pr_err("String parameter expected\n");
600 static int port_type_get(const char *typestr
, enum devlink_port_type
*p_type
)
602 if (strcmp(typestr
, "auto") == 0) {
603 *p_type
= DEVLINK_PORT_TYPE_AUTO
;
604 } else if (strcmp(typestr
, "eth") == 0) {
605 *p_type
= DEVLINK_PORT_TYPE_ETH
;
606 } else if (strcmp(typestr
, "ib") == 0) {
607 *p_type
= DEVLINK_PORT_TYPE_IB
;
609 pr_err("Unknown port type \"%s\"\n", typestr
);
615 static int pool_type_get(const char *typestr
, enum devlink_sb_pool_type
*p_type
)
617 if (strcmp(typestr
, "ingress") == 0) {
618 *p_type
= DEVLINK_SB_POOL_TYPE_INGRESS
;
619 } else if (strcmp(typestr
, "egress") == 0) {
620 *p_type
= DEVLINK_SB_POOL_TYPE_EGRESS
;
622 pr_err("Unknown pool type \"%s\"\n", typestr
);
628 static int threshold_type_get(const char *typestr
,
629 enum devlink_sb_threshold_type
*p_type
)
631 if (strcmp(typestr
, "static") == 0) {
632 *p_type
= DEVLINK_SB_THRESHOLD_TYPE_STATIC
;
633 } else if (strcmp(typestr
, "dynamic") == 0) {
634 *p_type
= DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC
;
636 pr_err("Unknown threshold type \"%s\"\n", typestr
);
642 static int dl_argv_parse(struct dl
*dl
, uint32_t o_required
,
645 struct dl_opts
*opts
= &dl
->opts
;
646 uint32_t o_all
= o_required
| o_optional
;
647 uint32_t o_found
= 0;
650 if (o_required
& DL_OPT_HANDLE
&& o_required
& DL_OPT_HANDLEP
) {
651 uint32_t handle_bit
= handle_bit
;
653 err
= dl_argv_handle_both(dl
, &opts
->bus_name
, &opts
->dev_name
,
654 &opts
->port_index
, &handle_bit
);
657 o_found
|= handle_bit
;
658 } else if (o_required
& DL_OPT_HANDLE
) {
659 err
= dl_argv_handle(dl
, &opts
->bus_name
, &opts
->dev_name
);
662 o_found
|= DL_OPT_HANDLE
;
663 } else if (o_required
& DL_OPT_HANDLEP
) {
664 err
= dl_argv_handle_port(dl
, &opts
->bus_name
, &opts
->dev_name
,
668 o_found
|= DL_OPT_HANDLEP
;
671 while (dl_argc(dl
)) {
672 if (dl_argv_match(dl
, "type") &&
673 (o_all
& DL_OPT_PORT_TYPE
)) {
677 err
= dl_argv_str(dl
, &typestr
);
680 err
= port_type_get(typestr
, &opts
->port_type
);
683 o_found
|= DL_OPT_PORT_TYPE
;
684 } else if (dl_argv_match(dl
, "count") &&
685 (o_all
& DL_OPT_PORT_COUNT
)) {
687 err
= dl_argv_uint32_t(dl
, &opts
->port_count
);
690 o_found
|= DL_OPT_PORT_COUNT
;
691 } else if (dl_argv_match(dl
, "sb") &&
692 (o_all
& DL_OPT_SB
)) {
694 err
= dl_argv_uint32_t(dl
, &opts
->sb_index
);
697 o_found
|= DL_OPT_SB
;
698 } else if (dl_argv_match(dl
, "pool") &&
699 (o_all
& DL_OPT_SB_POOL
)) {
701 err
= dl_argv_uint16_t(dl
, &opts
->sb_pool_index
);
704 o_found
|= DL_OPT_SB_POOL
;
705 } else if (dl_argv_match(dl
, "size") &&
706 (o_all
& DL_OPT_SB_SIZE
)) {
708 err
= dl_argv_uint32_t(dl
, &opts
->sb_pool_size
);
711 o_found
|= DL_OPT_SB_SIZE
;
712 } else if (dl_argv_match(dl
, "type") &&
713 (o_all
& DL_OPT_SB_TYPE
)) {
717 err
= dl_argv_str(dl
, &typestr
);
720 err
= pool_type_get(typestr
, &opts
->sb_pool_type
);
723 o_found
|= DL_OPT_SB_TYPE
;
724 } else if (dl_argv_match(dl
, "thtype") &&
725 (o_all
& DL_OPT_SB_THTYPE
)) {
729 err
= dl_argv_str(dl
, &typestr
);
732 err
= threshold_type_get(typestr
,
733 &opts
->sb_pool_thtype
);
736 o_found
|= DL_OPT_SB_THTYPE
;
737 } else if (dl_argv_match(dl
, "th") &&
738 (o_all
& DL_OPT_SB_TH
)) {
740 err
= dl_argv_uint32_t(dl
, &opts
->sb_threshold
);
743 o_found
|= DL_OPT_SB_TH
;
744 } else if (dl_argv_match(dl
, "tc") &&
745 (o_all
& DL_OPT_SB_TC
)) {
747 err
= dl_argv_uint16_t(dl
, &opts
->sb_tc_index
);
750 o_found
|= DL_OPT_SB_TC
;
752 pr_err("Unknown option \"%s\"\n", dl_argv(dl
));
757 opts
->present
= o_found
;
759 if ((o_optional
& DL_OPT_SB
) && !(o_found
& DL_OPT_SB
)) {
761 opts
->present
|= DL_OPT_SB
;
764 if ((o_required
& DL_OPT_PORT_TYPE
) && !(o_found
& DL_OPT_PORT_TYPE
)) {
765 pr_err("Port type option expected.\n");
769 if ((o_required
& DL_OPT_PORT_COUNT
) &&
770 !(o_found
& DL_OPT_PORT_COUNT
)) {
771 pr_err("Port split count option expected.\n");
775 if ((o_required
& DL_OPT_SB_POOL
) && !(o_found
& DL_OPT_SB_POOL
)) {
776 pr_err("Pool index option expected.\n");
780 if ((o_required
& DL_OPT_SB_SIZE
) && !(o_found
& DL_OPT_SB_SIZE
)) {
781 pr_err("Pool size option expected.\n");
785 if ((o_required
& DL_OPT_SB_TYPE
) && !(o_found
& DL_OPT_SB_TYPE
)) {
786 pr_err("Pool type option expected.\n");
790 if ((o_required
& DL_OPT_SB_THTYPE
) && !(o_found
& DL_OPT_SB_THTYPE
)) {
791 pr_err("Pool threshold type option expected.\n");
795 if ((o_required
& DL_OPT_SB_TH
) && !(o_found
& DL_OPT_SB_TH
)) {
796 pr_err("Threshold option expected.\n");
800 if ((o_required
& DL_OPT_SB_TC
) && !(o_found
& DL_OPT_SB_TC
)) {
801 pr_err("TC index option expected.\n");
807 static void dl_opts_put(struct nlmsghdr
*nlh
, struct dl
*dl
)
809 struct dl_opts
*opts
= &dl
->opts
;
811 if (opts
->present
& DL_OPT_HANDLE
) {
812 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, opts
->bus_name
);
813 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, opts
->dev_name
);
814 } else if (opts
->present
& DL_OPT_HANDLEP
) {
815 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, opts
->bus_name
);
816 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, opts
->dev_name
);
817 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_INDEX
,
820 if (opts
->present
& DL_OPT_PORT_TYPE
)
821 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_PORT_TYPE
,
823 if (opts
->present
& DL_OPT_PORT_COUNT
)
824 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_SPLIT_COUNT
,
826 if (opts
->present
& DL_OPT_SB
)
827 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_SB_INDEX
,
829 if (opts
->present
& DL_OPT_SB_POOL
)
830 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_SB_POOL_INDEX
,
831 opts
->sb_pool_index
);
832 if (opts
->present
& DL_OPT_SB_SIZE
)
833 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_SB_POOL_SIZE
,
835 if (opts
->present
& DL_OPT_SB_TYPE
)
836 mnl_attr_put_u8(nlh
, DEVLINK_ATTR_SB_POOL_TYPE
,
838 if (opts
->present
& DL_OPT_SB_THTYPE
)
839 mnl_attr_put_u8(nlh
, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
,
840 opts
->sb_pool_thtype
);
841 if (opts
->present
& DL_OPT_SB_TH
)
842 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_SB_THRESHOLD
,
844 if (opts
->present
& DL_OPT_SB_TC
)
845 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_SB_TC_INDEX
,
849 static int dl_argv_parse_put(struct nlmsghdr
*nlh
, struct dl
*dl
,
850 uint32_t o_required
, uint32_t o_optional
)
854 err
= dl_argv_parse(dl
, o_required
, o_optional
);
857 dl_opts_put(nlh
, dl
);
861 static bool dl_dump_filter(struct dl
*dl
, struct nlattr
**tb
)
863 struct dl_opts
*opts
= &dl
->opts
;
864 struct nlattr
*attr_bus_name
= tb
[DEVLINK_ATTR_BUS_NAME
];
865 struct nlattr
*attr_dev_name
= tb
[DEVLINK_ATTR_DEV_NAME
];
866 struct nlattr
*attr_port_index
= tb
[DEVLINK_ATTR_PORT_INDEX
];
868 if (opts
->present
& DL_OPT_HANDLE
&&
869 attr_bus_name
&& attr_dev_name
) {
870 const char *bus_name
= mnl_attr_get_str(attr_bus_name
);
871 const char *dev_name
= mnl_attr_get_str(attr_dev_name
);
873 if (strcmp(bus_name
, opts
->bus_name
) != 0 ||
874 strcmp(dev_name
, opts
->dev_name
) != 0)
877 if (opts
->present
& DL_OPT_HANDLEP
&&
878 attr_bus_name
&& attr_dev_name
&& attr_port_index
) {
879 const char *bus_name
= mnl_attr_get_str(attr_bus_name
);
880 const char *dev_name
= mnl_attr_get_str(attr_dev_name
);
881 uint32_t port_index
= mnl_attr_get_u32(attr_port_index
);
883 if (strcmp(bus_name
, opts
->bus_name
) != 0 ||
884 strcmp(dev_name
, opts
->dev_name
) != 0 ||
885 port_index
!= opts
->port_index
)
891 static void cmd_dev_help(void)
893 pr_out("Usage: devlink dev show [ DEV ]\n");
896 static void __pr_out_handle(const char *bus_name
, const char *dev_name
)
898 pr_out("%s/%s", bus_name
, dev_name
);
901 static void pr_out_handle(struct nlattr
**tb
)
903 __pr_out_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
904 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]));
907 static void __pr_out_port_handle(const char *bus_name
, const char *dev_name
,
910 __pr_out_handle(bus_name
, dev_name
);
911 pr_out("/%d", port_index
);
914 static void pr_out_port_handle(struct nlattr
**tb
)
916 __pr_out_port_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
917 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]),
918 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]));
921 static void __pr_out_port_handle_nice(struct dl
*dl
, const char *bus_name
,
922 const char *dev_name
, uint32_t port_index
)
927 if (dl
->no_nice_names
)
930 err
= ifname_map_rev_lookup(dl
, bus_name
, dev_name
,
931 port_index
, &ifname
);
934 pr_out("%s", ifname
);
938 __pr_out_port_handle(bus_name
, dev_name
, port_index
);
941 static void pr_out_port_handle_nice(struct dl
*dl
, struct nlattr
**tb
)
943 const char *bus_name
;
944 const char *dev_name
;
947 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
948 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
949 port_index
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
951 __pr_out_port_handle_nice(dl
, bus_name
, dev_name
, port_index
);
954 static void pr_out_dev(struct nlattr
**tb
)
960 static int cmd_dev_show_cb(const struct nlmsghdr
*nlh
, void *data
)
962 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
963 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
965 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
966 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
972 static int cmd_dev_show(struct dl
*dl
)
974 struct nlmsghdr
*nlh
;
975 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
978 if (dl_argc(dl
) == 0)
981 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_GET
, flags
);
983 if (dl_argc(dl
) > 0) {
984 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, 0);
989 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_dev_show_cb
, NULL
);
992 static int cmd_dev(struct dl
*dl
)
994 if (dl_argv_match(dl
, "help")) {
997 } else if (dl_argv_match(dl
, "show") ||
998 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1000 return cmd_dev_show(dl
);
1002 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1006 static void cmd_port_help(void)
1008 pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n");
1009 pr_out(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
1010 pr_out(" devlink port split DEV/PORT_INDEX count COUNT\n");
1011 pr_out(" devlink port unsplit DEV/PORT_INDEX\n");
1014 static const char *port_type_name(uint32_t type
)
1017 case DEVLINK_PORT_TYPE_NOTSET
: return "notset";
1018 case DEVLINK_PORT_TYPE_AUTO
: return "auto";
1019 case DEVLINK_PORT_TYPE_ETH
: return "eth";
1020 case DEVLINK_PORT_TYPE_IB
: return "ib";
1021 default: return "<unknown type>";
1025 static void pr_out_port(struct nlattr
**tb
)
1027 struct nlattr
*pt_attr
= tb
[DEVLINK_ATTR_PORT_TYPE
];
1028 struct nlattr
*dpt_attr
= tb
[DEVLINK_ATTR_PORT_DESIRED_TYPE
];
1030 pr_out_port_handle(tb
);
1033 uint16_t port_type
= mnl_attr_get_u16(pt_attr
);
1035 pr_out(" type %s", port_type_name(port_type
));
1037 uint16_t des_port_type
= mnl_attr_get_u16(dpt_attr
);
1039 if (port_type
!= des_port_type
)
1040 pr_out("(%s)", port_type_name(des_port_type
));
1043 if (tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
1044 pr_out(" netdev %s",
1045 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]));
1046 if (tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
])
1048 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
]));
1049 if (tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
])
1050 pr_out(" split_group %u",
1051 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
]));
1055 static int cmd_port_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1057 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1058 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1060 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1061 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1062 !tb
[DEVLINK_ATTR_PORT_INDEX
])
1063 return MNL_CB_ERROR
;
1068 static int cmd_port_show(struct dl
*dl
)
1070 struct nlmsghdr
*nlh
;
1071 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1074 if (dl_argc(dl
) == 0)
1075 flags
|= NLM_F_DUMP
;
1077 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
, flags
);
1079 if (dl_argc(dl
) > 0) {
1080 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
1085 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_port_show_cb
, NULL
);
1088 static int cmd_port_set(struct dl
*dl
)
1090 struct nlmsghdr
*nlh
;
1093 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SET
,
1094 NLM_F_REQUEST
| NLM_F_ACK
);
1096 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_TYPE
, 0);
1100 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1103 static int cmd_port_split(struct dl
*dl
)
1105 struct nlmsghdr
*nlh
;
1108 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SPLIT
,
1109 NLM_F_REQUEST
| NLM_F_ACK
);
1111 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_COUNT
, 0);
1115 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1118 static int cmd_port_unsplit(struct dl
*dl
)
1120 struct nlmsghdr
*nlh
;
1123 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_UNSPLIT
,
1124 NLM_F_REQUEST
| NLM_F_ACK
);
1126 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
1130 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1133 static int cmd_port(struct dl
*dl
)
1135 if (dl_argv_match(dl
, "help")) {
1138 } else if (dl_argv_match(dl
, "show") ||
1139 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1141 return cmd_port_show(dl
);
1142 } else if (dl_argv_match(dl
, "set")) {
1144 return cmd_port_set(dl
);
1145 } else if (dl_argv_match(dl
, "split")) {
1147 return cmd_port_split(dl
);
1148 } else if (dl_argv_match(dl
, "unsplit")) {
1150 return cmd_port_unsplit(dl
);
1152 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1156 static void cmd_sb_help(void)
1158 pr_out("Usage: devlink sb show [ DEV [ sb SB_INDEX ] ]\n");
1159 pr_out(" devlink sb pool show [ DEV [ sb SB_INDEX ] pool POOL_INDEX ]\n");
1160 pr_out(" devlink sb pool set DEV [ sb SB_INDEX ] pool POOL_INDEX\n");
1161 pr_out(" size POOL_SIZE thtype { static | dynamic }\n");
1162 pr_out(" devlink sb port pool show [ DEV/PORT_INDEX [ sb SB_INDEX ]\n");
1163 pr_out(" pool POOL_INDEX ]\n");
1164 pr_out(" devlink sb port pool set DEV/PORT_INDEX [ sb SB_INDEX ]\n");
1165 pr_out(" pool POOL_INDEX th THRESHOLD\n");
1166 pr_out(" devlink sb tc bind show [ DEV/PORT_INDEX [ sb SB_INDEX ] tc TC_INDEX\n");
1167 pr_out(" type { ingress | egress } ]\n");
1168 pr_out(" devlink sb tc bind set DEV/PORT_INDEX [ sb SB_INDEX ] tc TC_INDEX\n");
1169 pr_out(" type { ingress | egress } pool POOL_INDEX\n");
1170 pr_out(" th THRESHOLD\n");
1173 static void pr_out_sb(struct nlattr
**tb
)
1176 pr_out(": sb %u size %u ing_pools %u eg_pools %u ing_tcs %u eg_tcs %u\n",
1177 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]),
1178 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_SIZE
]),
1179 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_INGRESS_POOL_COUNT
]),
1180 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_EGRESS_POOL_COUNT
]),
1181 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_INGRESS_TC_COUNT
]),
1182 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_EGRESS_TC_COUNT
]));
1185 static int cmd_sb_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1187 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1188 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1190 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1191 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1192 !tb
[DEVLINK_ATTR_SB_INDEX
] || !tb
[DEVLINK_ATTR_SB_SIZE
] ||
1193 !tb
[DEVLINK_ATTR_SB_INGRESS_POOL_COUNT
] ||
1194 !tb
[DEVLINK_ATTR_SB_EGRESS_POOL_COUNT
] ||
1195 !tb
[DEVLINK_ATTR_SB_INGRESS_TC_COUNT
] ||
1196 !tb
[DEVLINK_ATTR_SB_EGRESS_TC_COUNT
])
1197 return MNL_CB_ERROR
;
1202 static int cmd_sb_show(struct dl
*dl
)
1204 struct nlmsghdr
*nlh
;
1205 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1208 if (dl_argc(dl
) == 0)
1209 flags
|= NLM_F_DUMP
;
1211 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_GET
, flags
);
1213 if (dl_argc(dl
) > 0) {
1214 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, DL_OPT_SB
);
1219 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_show_cb
, NULL
);
1222 static const char *pool_type_name(uint8_t type
)
1225 case DEVLINK_SB_POOL_TYPE_INGRESS
: return "ingress";
1226 case DEVLINK_SB_POOL_TYPE_EGRESS
: return "egress";
1227 default: return "<unknown type>";
1231 static const char *threshold_type_name(uint8_t type
)
1234 case DEVLINK_SB_THRESHOLD_TYPE_STATIC
: return "static";
1235 case DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC
: return "dynamic";
1236 default: return "<unknown type>";
1240 static void pr_out_sb_pool(struct nlattr
**tb
)
1243 pr_out(": sb %u pool %u type %s size %u thtype %s\n",
1244 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]),
1245 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]),
1246 pool_type_name(mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_TYPE
])),
1247 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_POOL_SIZE
]),
1248 threshold_type_name(mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
])));
1251 static int cmd_sb_pool_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1253 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1254 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1256 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1257 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1258 !tb
[DEVLINK_ATTR_SB_INDEX
] || !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] ||
1259 !tb
[DEVLINK_ATTR_SB_POOL_TYPE
] || !tb
[DEVLINK_ATTR_SB_POOL_SIZE
] ||
1260 !tb
[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
])
1261 return MNL_CB_ERROR
;
1266 static int cmd_sb_pool_show(struct dl
*dl
)
1268 struct nlmsghdr
*nlh
;
1269 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1272 if (dl_argc(dl
) == 0)
1273 flags
|= NLM_F_DUMP
;
1275 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_POOL_GET
, flags
);
1277 if (dl_argc(dl
) > 0) {
1278 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
| DL_OPT_SB_POOL
,
1284 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_pool_show_cb
, NULL
);
1287 static int cmd_sb_pool_set(struct dl
*dl
)
1289 struct nlmsghdr
*nlh
;
1292 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_POOL_SET
,
1293 NLM_F_REQUEST
| NLM_F_ACK
);
1295 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
| DL_OPT_SB_POOL
|
1296 DL_OPT_SB_SIZE
| DL_OPT_SB_THTYPE
, DL_OPT_SB
);
1300 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1303 static int cmd_sb_pool(struct dl
*dl
)
1305 if (dl_argv_match(dl
, "help")) {
1308 } else if (dl_argv_match(dl
, "show") ||
1309 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1311 return cmd_sb_pool_show(dl
);
1312 } else if (dl_argv_match(dl
, "set")) {
1314 return cmd_sb_pool_set(dl
);
1316 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1320 static void pr_out_sb_port_pool(struct dl
*dl
, struct nlattr
**tb
)
1322 pr_out_port_handle_nice(dl
, tb
);
1323 pr_out(": sb %u pool %u threshold %u\n",
1324 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]),
1325 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]),
1326 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_THRESHOLD
]));
1329 static int cmd_sb_port_pool_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1331 struct dl
*dl
= data
;
1332 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1333 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1335 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1336 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1337 !tb
[DEVLINK_ATTR_PORT_INDEX
] || !tb
[DEVLINK_ATTR_SB_INDEX
] ||
1338 !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] || !tb
[DEVLINK_ATTR_SB_THRESHOLD
])
1339 return MNL_CB_ERROR
;
1340 pr_out_sb_port_pool(dl
, tb
);
1344 static int cmd_sb_port_pool_show(struct dl
*dl
)
1346 struct nlmsghdr
*nlh
;
1347 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1350 if (dl_argc(dl
) == 0)
1351 flags
|= NLM_F_DUMP
;
1353 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_PORT_POOL_GET
, flags
);
1355 if (dl_argc(dl
) > 0) {
1356 err
= dl_argv_parse_put(nlh
, dl
,
1357 DL_OPT_HANDLEP
| DL_OPT_SB_POOL
,
1363 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_port_pool_show_cb
, dl
);
1366 static int cmd_sb_port_pool_set(struct dl
*dl
)
1368 struct nlmsghdr
*nlh
;
1371 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_PORT_POOL_SET
,
1372 NLM_F_REQUEST
| NLM_F_ACK
);
1374 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_SB_POOL
|
1375 DL_OPT_SB_TH
, DL_OPT_SB
);
1379 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1382 static int cmd_sb_port_pool(struct dl
*dl
)
1384 if (dl_argv_match(dl
, "help")) {
1387 } else if (dl_argv_match(dl
, "show") ||
1388 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1390 return cmd_sb_port_pool_show(dl
);
1391 } else if (dl_argv_match(dl
, "set")) {
1393 return cmd_sb_port_pool_set(dl
);
1395 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1399 static int cmd_sb_port(struct dl
*dl
)
1401 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
1404 } else if (dl_argv_match(dl
, "pool")) {
1406 return cmd_sb_port_pool(dl
);
1408 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1412 static void pr_out_sb_tc_bind(struct dl
*dl
, struct nlattr
**tb
)
1414 pr_out_port_handle_nice(dl
, tb
);
1415 pr_out(": sb %u tc %u type %s pool %u threshold %u\n",
1416 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]),
1417 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_TC_INDEX
]),
1418 pool_type_name(mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_TYPE
])),
1419 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]),
1420 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_THRESHOLD
]));
1423 static int cmd_sb_tc_bind_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1425 struct dl
*dl
= data
;
1426 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1427 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1429 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1430 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1431 !tb
[DEVLINK_ATTR_PORT_INDEX
] || !tb
[DEVLINK_ATTR_SB_INDEX
] ||
1432 !tb
[DEVLINK_ATTR_SB_TC_INDEX
] || !tb
[DEVLINK_ATTR_SB_POOL_TYPE
] ||
1433 !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] || !tb
[DEVLINK_ATTR_SB_THRESHOLD
])
1434 return MNL_CB_ERROR
;
1435 pr_out_sb_tc_bind(dl
, tb
);
1439 static int cmd_sb_tc_bind_show(struct dl
*dl
)
1441 struct nlmsghdr
*nlh
;
1442 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1445 if (dl_argc(dl
) == 0)
1446 flags
|= NLM_F_DUMP
;
1448 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_TC_POOL_BIND_GET
, flags
);
1450 if (dl_argc(dl
) > 0) {
1451 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_SB_TC
|
1452 DL_OPT_SB_TYPE
, DL_OPT_SB
);
1457 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_tc_bind_show_cb
, dl
);
1460 static int cmd_sb_tc_bind_set(struct dl
*dl
)
1462 struct nlmsghdr
*nlh
;
1465 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_TC_POOL_BIND_SET
,
1466 NLM_F_REQUEST
| NLM_F_ACK
);
1468 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_SB_TC
|
1469 DL_OPT_SB_TYPE
| DL_OPT_SB_POOL
| DL_OPT_SB_TH
,
1474 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1477 static int cmd_sb_tc_bind(struct dl
*dl
)
1479 if (dl_argv_match(dl
, "help")) {
1482 } else if (dl_argv_match(dl
, "show") ||
1483 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1485 return cmd_sb_tc_bind_show(dl
);
1486 } else if (dl_argv_match(dl
, "set")) {
1488 return cmd_sb_tc_bind_set(dl
);
1490 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1494 static int cmd_sb_tc(struct dl
*dl
)
1496 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
1499 } else if (dl_argv_match(dl
, "bind")) {
1501 return cmd_sb_tc_bind(dl
);
1503 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1507 static int cmd_sb(struct dl
*dl
)
1509 if (dl_argv_match(dl
, "help")) {
1512 } else if (dl_argv_match(dl
, "show") ||
1513 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1515 return cmd_sb_show(dl
);
1516 } else if (dl_argv_match(dl
, "pool")) {
1518 return cmd_sb_pool(dl
);
1519 } else if (dl_argv_match(dl
, "port")) {
1521 return cmd_sb_port(dl
);
1522 } else if (dl_argv_match(dl
, "tc")) {
1524 return cmd_sb_tc(dl
);
1526 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1530 static const char *cmd_name(uint8_t cmd
)
1533 case DEVLINK_CMD_UNSPEC
: return "unspec";
1534 case DEVLINK_CMD_GET
: return "get";
1535 case DEVLINK_CMD_SET
: return "set";
1536 case DEVLINK_CMD_NEW
: return "new";
1537 case DEVLINK_CMD_DEL
: return "del";
1538 case DEVLINK_CMD_PORT_GET
: return "get";
1539 case DEVLINK_CMD_PORT_SET
: return "set";
1540 case DEVLINK_CMD_PORT_NEW
: return "net";
1541 case DEVLINK_CMD_PORT_DEL
: return "del";
1542 default: return "<unknown cmd>";
1546 static const char *cmd_obj(uint8_t cmd
)
1549 case DEVLINK_CMD_UNSPEC
: return "unspec";
1550 case DEVLINK_CMD_GET
:
1551 case DEVLINK_CMD_SET
:
1552 case DEVLINK_CMD_NEW
:
1553 case DEVLINK_CMD_DEL
:
1555 case DEVLINK_CMD_PORT_GET
:
1556 case DEVLINK_CMD_PORT_SET
:
1557 case DEVLINK_CMD_PORT_NEW
:
1558 case DEVLINK_CMD_PORT_DEL
:
1560 default: return "<unknown obj>";
1564 static void pr_out_mon_header(uint8_t cmd
)
1566 pr_out("[%s,%s] ", cmd_obj(cmd
), cmd_name(cmd
));
1569 static bool cmd_filter_check(struct dl
*dl
, uint8_t cmd
)
1571 const char *obj
= cmd_obj(cmd
);
1572 unsigned int index
= 0;
1573 const char *cur_obj
;
1577 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
1578 if (strcmp(cur_obj
, obj
) == 0 || strcmp(cur_obj
, "all") == 0)
1584 static int cmd_mon_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1586 struct dl
*dl
= data
;
1587 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1588 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1589 uint8_t cmd
= genl
->cmd
;
1591 if (!cmd_filter_check(dl
, cmd
))
1595 case DEVLINK_CMD_GET
: /* fall through */
1596 case DEVLINK_CMD_SET
: /* fall through */
1597 case DEVLINK_CMD_NEW
: /* fall through */
1598 case DEVLINK_CMD_DEL
:
1599 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1600 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
1601 return MNL_CB_ERROR
;
1602 pr_out_mon_header(genl
->cmd
);
1605 case DEVLINK_CMD_PORT_GET
: /* fall through */
1606 case DEVLINK_CMD_PORT_SET
: /* fall through */
1607 case DEVLINK_CMD_PORT_NEW
: /* fall through */
1608 case DEVLINK_CMD_PORT_DEL
:
1609 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1610 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1611 !tb
[DEVLINK_ATTR_PORT_INDEX
])
1612 return MNL_CB_ERROR
;
1613 pr_out_mon_header(genl
->cmd
);
1620 static int cmd_mon_show(struct dl
*dl
)
1623 unsigned int index
= 0;
1624 const char *cur_obj
;
1626 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
1627 if (strcmp(cur_obj
, "all") != 0 &&
1628 strcmp(cur_obj
, "dev") != 0 &&
1629 strcmp(cur_obj
, "port") != 0) {
1630 pr_err("Unknown object \"%s\"\n", cur_obj
);
1634 err
= _mnlg_socket_group_add(dl
->nlg
, DEVLINK_GENL_MCGRP_CONFIG_NAME
);
1637 err
= _mnlg_socket_recv_run(dl
->nlg
, cmd_mon_show_cb
, dl
);
1643 static void cmd_mon_help(void)
1645 pr_out("Usage: devlink monitor [ all | OBJECT-LIST ]\n"
1646 "where OBJECT-LIST := { dev | port }\n");
1649 static int cmd_mon(struct dl
*dl
)
1651 if (dl_argv_match(dl
, "help")) {
1654 } else if (dl_no_arg(dl
)) {
1656 return cmd_mon_show(dl
);
1658 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1662 static void help(void)
1664 pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
1665 "where OBJECT := { dev | port | sb | monitor }\n"
1666 " OPTIONS := { -V[ersion] | -n[no-nice-names] }\n");
1669 static int dl_cmd(struct dl
*dl
)
1671 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
1674 } else if (dl_argv_match(dl
, "dev")) {
1677 } else if (dl_argv_match(dl
, "port")) {
1679 return cmd_port(dl
);
1680 } else if (dl_argv_match(dl
, "sb")) {
1683 } else if (dl_argv_match(dl
, "monitor")) {
1687 pr_err("Object \"%s\" not found\n", dl_argv(dl
));
1691 static int dl_init(struct dl
*dl
, int argc
, char **argv
)
1698 dl
->nlg
= mnlg_socket_open(DEVLINK_GENL_NAME
, DEVLINK_GENL_VERSION
);
1700 pr_err("Failed to connect to devlink Netlink\n");
1704 err
= ifname_map_init(dl
);
1706 pr_err("Failed to create index map\n");
1707 goto err_ifname_map_create
;
1711 err_ifname_map_create
:
1712 mnlg_socket_close(dl
->nlg
);
1716 static void dl_fini(struct dl
*dl
)
1718 ifname_map_fini(dl
);
1719 mnlg_socket_close(dl
->nlg
);
1722 static struct dl
*dl_alloc(void)
1726 dl
= calloc(1, sizeof(*dl
));
1732 static void dl_free(struct dl
*dl
)
1737 int main(int argc
, char **argv
)
1739 static const struct option long_options
[] = {
1740 { "Version", no_argument
, NULL
, 'V' },
1741 { "no-nice-names", no_argument
, NULL
, 'n' },
1742 { NULL
, 0, NULL
, 0 }
1751 pr_err("Failed to allocate memory for devlink\n");
1752 return EXIT_FAILURE
;
1755 while ((opt
= getopt_long(argc
, argv
, "Vn",
1756 long_options
, NULL
)) >= 0) {
1760 printf("devlink utility, iproute2-ss%s\n", SNAPSHOT
);
1761 return EXIT_SUCCESS
;
1763 dl
->no_nice_names
= true;
1766 pr_err("Unknown option.\n");
1768 return EXIT_FAILURE
;
1775 err
= dl_init(dl
, argc
, argv
);