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
);
862 static void cmd_dev_help(void)
864 pr_out("Usage: devlink dev show [ DEV ]\n");
867 static void __pr_out_handle(const char *bus_name
, const char *dev_name
)
869 pr_out("%s/%s", bus_name
, dev_name
);
872 static void pr_out_handle(struct nlattr
**tb
)
874 __pr_out_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
875 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]));
878 static void __pr_out_port_handle(const char *bus_name
, const char *dev_name
,
881 __pr_out_handle(bus_name
, dev_name
);
882 pr_out("/%d", port_index
);
885 static void pr_out_port_handle(struct nlattr
**tb
)
887 __pr_out_port_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
888 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]),
889 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]));
892 static void __pr_out_port_handle_nice(struct dl
*dl
, const char *bus_name
,
893 const char *dev_name
, uint32_t port_index
)
898 if (dl
->no_nice_names
)
901 err
= ifname_map_rev_lookup(dl
, bus_name
, dev_name
,
902 port_index
, &ifname
);
905 pr_out("%s", ifname
);
909 __pr_out_port_handle(bus_name
, dev_name
, port_index
);
912 static void pr_out_port_handle_nice(struct dl
*dl
, struct nlattr
**tb
)
914 const char *bus_name
;
915 const char *dev_name
;
918 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
919 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
920 port_index
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
922 __pr_out_port_handle_nice(dl
, bus_name
, dev_name
, port_index
);
925 static void pr_out_dev(struct nlattr
**tb
)
931 static int cmd_dev_show_cb(const struct nlmsghdr
*nlh
, void *data
)
933 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
934 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
936 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
937 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
943 static int cmd_dev_show(struct dl
*dl
)
945 struct nlmsghdr
*nlh
;
946 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
949 if (dl_argc(dl
) == 0)
952 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_GET
, flags
);
954 if (dl_argc(dl
) > 0) {
955 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, 0);
960 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_dev_show_cb
, NULL
);
963 static int cmd_dev(struct dl
*dl
)
965 if (dl_argv_match(dl
, "help")) {
968 } else if (dl_argv_match(dl
, "show") ||
969 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
971 return cmd_dev_show(dl
);
973 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
977 static void cmd_port_help(void)
979 pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n");
980 pr_out(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
981 pr_out(" devlink port split DEV/PORT_INDEX count COUNT\n");
982 pr_out(" devlink port unsplit DEV/PORT_INDEX\n");
985 static const char *port_type_name(uint32_t type
)
988 case DEVLINK_PORT_TYPE_NOTSET
: return "notset";
989 case DEVLINK_PORT_TYPE_AUTO
: return "auto";
990 case DEVLINK_PORT_TYPE_ETH
: return "eth";
991 case DEVLINK_PORT_TYPE_IB
: return "ib";
992 default: return "<unknown type>";
996 static void pr_out_port(struct nlattr
**tb
)
998 struct nlattr
*pt_attr
= tb
[DEVLINK_ATTR_PORT_TYPE
];
999 struct nlattr
*dpt_attr
= tb
[DEVLINK_ATTR_PORT_DESIRED_TYPE
];
1001 pr_out_port_handle(tb
);
1004 uint16_t port_type
= mnl_attr_get_u16(pt_attr
);
1006 pr_out(" type %s", port_type_name(port_type
));
1008 uint16_t des_port_type
= mnl_attr_get_u16(dpt_attr
);
1010 if (port_type
!= des_port_type
)
1011 pr_out("(%s)", port_type_name(des_port_type
));
1014 if (tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
1015 pr_out(" netdev %s",
1016 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]));
1017 if (tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
])
1019 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
]));
1020 if (tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
])
1021 pr_out(" split_group %u",
1022 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
]));
1026 static int cmd_port_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1028 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1029 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1031 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1032 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1033 !tb
[DEVLINK_ATTR_PORT_INDEX
])
1034 return MNL_CB_ERROR
;
1039 static int cmd_port_show(struct dl
*dl
)
1041 struct nlmsghdr
*nlh
;
1042 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1045 if (dl_argc(dl
) == 0)
1046 flags
|= NLM_F_DUMP
;
1048 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
, flags
);
1050 if (dl_argc(dl
) > 0) {
1051 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
1056 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_port_show_cb
, NULL
);
1059 static int cmd_port_set(struct dl
*dl
)
1061 struct nlmsghdr
*nlh
;
1064 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SET
,
1065 NLM_F_REQUEST
| NLM_F_ACK
);
1067 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_TYPE
, 0);
1071 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1074 static int cmd_port_split(struct dl
*dl
)
1076 struct nlmsghdr
*nlh
;
1079 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SPLIT
,
1080 NLM_F_REQUEST
| NLM_F_ACK
);
1082 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_COUNT
, 0);
1086 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1089 static int cmd_port_unsplit(struct dl
*dl
)
1091 struct nlmsghdr
*nlh
;
1094 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_UNSPLIT
,
1095 NLM_F_REQUEST
| NLM_F_ACK
);
1097 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
1101 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1104 static int cmd_port(struct dl
*dl
)
1106 if (dl_argv_match(dl
, "help")) {
1109 } else if (dl_argv_match(dl
, "show") ||
1110 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1112 return cmd_port_show(dl
);
1113 } else if (dl_argv_match(dl
, "set")) {
1115 return cmd_port_set(dl
);
1116 } else if (dl_argv_match(dl
, "split")) {
1118 return cmd_port_split(dl
);
1119 } else if (dl_argv_match(dl
, "unsplit")) {
1121 return cmd_port_unsplit(dl
);
1123 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1127 static void cmd_sb_help(void)
1129 pr_out("Usage: devlink sb show [ DEV [ sb SB_INDEX ] ]\n");
1130 pr_out(" devlink sb pool show [ DEV [ sb SB_INDEX ] pool POOL_INDEX ]\n");
1131 pr_out(" devlink sb pool set DEV [ sb SB_INDEX ] pool POOL_INDEX\n");
1132 pr_out(" size POOL_SIZE thtype { static | dynamic }\n");
1133 pr_out(" devlink sb port pool show [ DEV/PORT_INDEX [ sb SB_INDEX ]\n");
1134 pr_out(" pool POOL_INDEX ]\n");
1135 pr_out(" devlink sb port pool set DEV/PORT_INDEX [ sb SB_INDEX ]\n");
1136 pr_out(" pool POOL_INDEX th THRESHOLD\n");
1137 pr_out(" devlink sb tc bind show [ DEV/PORT_INDEX [ sb SB_INDEX ] tc TC_INDEX\n");
1138 pr_out(" type { ingress | egress } ]\n");
1139 pr_out(" devlink sb tc bind set DEV/PORT_INDEX [ sb SB_INDEX ] tc TC_INDEX\n");
1140 pr_out(" type { ingress | egress } pool POOL_INDEX\n");
1141 pr_out(" th THRESHOLD\n");
1144 static void pr_out_sb(struct nlattr
**tb
)
1147 pr_out(": sb %u size %u ing_pools %u eg_pools %u ing_tcs %u eg_tcs %u\n",
1148 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]),
1149 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_SIZE
]),
1150 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_INGRESS_POOL_COUNT
]),
1151 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_EGRESS_POOL_COUNT
]),
1152 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_INGRESS_TC_COUNT
]),
1153 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_EGRESS_TC_COUNT
]));
1156 static int cmd_sb_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1158 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1159 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1161 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1162 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1163 !tb
[DEVLINK_ATTR_SB_INDEX
] || !tb
[DEVLINK_ATTR_SB_SIZE
] ||
1164 !tb
[DEVLINK_ATTR_SB_INGRESS_POOL_COUNT
] ||
1165 !tb
[DEVLINK_ATTR_SB_EGRESS_POOL_COUNT
] ||
1166 !tb
[DEVLINK_ATTR_SB_INGRESS_TC_COUNT
] ||
1167 !tb
[DEVLINK_ATTR_SB_EGRESS_TC_COUNT
])
1168 return MNL_CB_ERROR
;
1173 static int cmd_sb_show(struct dl
*dl
)
1175 struct nlmsghdr
*nlh
;
1176 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1179 if (dl_argc(dl
) == 0)
1180 flags
|= NLM_F_DUMP
;
1182 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_GET
, flags
);
1184 if (dl_argc(dl
) > 0) {
1185 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, DL_OPT_SB
);
1190 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_show_cb
, NULL
);
1193 static const char *pool_type_name(uint8_t type
)
1196 case DEVLINK_SB_POOL_TYPE_INGRESS
: return "ingress";
1197 case DEVLINK_SB_POOL_TYPE_EGRESS
: return "egress";
1198 default: return "<unknown type>";
1202 static const char *threshold_type_name(uint8_t type
)
1205 case DEVLINK_SB_THRESHOLD_TYPE_STATIC
: return "static";
1206 case DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC
: return "dynamic";
1207 default: return "<unknown type>";
1211 static void pr_out_sb_pool(struct nlattr
**tb
)
1214 pr_out(": sb %u pool %u type %s size %u thtype %s\n",
1215 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]),
1216 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]),
1217 pool_type_name(mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_TYPE
])),
1218 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_POOL_SIZE
]),
1219 threshold_type_name(mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
])));
1222 static int cmd_sb_pool_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1224 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1225 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1227 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1228 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1229 !tb
[DEVLINK_ATTR_SB_INDEX
] || !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] ||
1230 !tb
[DEVLINK_ATTR_SB_POOL_TYPE
] || !tb
[DEVLINK_ATTR_SB_POOL_SIZE
] ||
1231 !tb
[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE
])
1232 return MNL_CB_ERROR
;
1237 static int cmd_sb_pool_show(struct dl
*dl
)
1239 struct nlmsghdr
*nlh
;
1240 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1243 if (dl_argc(dl
) == 0)
1244 flags
|= NLM_F_DUMP
;
1246 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_POOL_GET
, flags
);
1248 if (dl_argc(dl
) > 0) {
1249 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
| DL_OPT_SB_POOL
,
1255 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_pool_show_cb
, NULL
);
1258 static int cmd_sb_pool_set(struct dl
*dl
)
1260 struct nlmsghdr
*nlh
;
1263 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_POOL_SET
,
1264 NLM_F_REQUEST
| NLM_F_ACK
);
1266 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
| DL_OPT_SB_POOL
|
1267 DL_OPT_SB_SIZE
| DL_OPT_SB_THTYPE
, DL_OPT_SB
);
1271 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1274 static int cmd_sb_pool(struct dl
*dl
)
1276 if (dl_argv_match(dl
, "help")) {
1279 } else if (dl_argv_match(dl
, "show") ||
1280 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1282 return cmd_sb_pool_show(dl
);
1283 } else if (dl_argv_match(dl
, "set")) {
1285 return cmd_sb_pool_set(dl
);
1287 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1291 static void pr_out_sb_port_pool(struct dl
*dl
, struct nlattr
**tb
)
1293 pr_out_port_handle_nice(dl
, tb
);
1294 pr_out(": sb %u pool %u threshold %u\n",
1295 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]),
1296 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]),
1297 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_THRESHOLD
]));
1300 static int cmd_sb_port_pool_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1302 struct dl
*dl
= data
;
1303 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1304 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1306 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1307 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1308 !tb
[DEVLINK_ATTR_PORT_INDEX
] || !tb
[DEVLINK_ATTR_SB_INDEX
] ||
1309 !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] || !tb
[DEVLINK_ATTR_SB_THRESHOLD
])
1310 return MNL_CB_ERROR
;
1311 pr_out_sb_port_pool(dl
, tb
);
1315 static int cmd_sb_port_pool_show(struct dl
*dl
)
1317 struct nlmsghdr
*nlh
;
1318 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1321 if (dl_argc(dl
) == 0)
1322 flags
|= NLM_F_DUMP
;
1324 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_PORT_POOL_GET
, flags
);
1326 if (dl_argc(dl
) > 0) {
1327 err
= dl_argv_parse_put(nlh
, dl
,
1328 DL_OPT_HANDLEP
| DL_OPT_SB_POOL
,
1334 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_port_pool_show_cb
, dl
);
1337 static int cmd_sb_port_pool_set(struct dl
*dl
)
1339 struct nlmsghdr
*nlh
;
1342 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_PORT_POOL_SET
,
1343 NLM_F_REQUEST
| NLM_F_ACK
);
1345 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_SB_POOL
|
1346 DL_OPT_SB_TH
, DL_OPT_SB
);
1350 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1353 static int cmd_sb_port_pool(struct dl
*dl
)
1355 if (dl_argv_match(dl
, "help")) {
1358 } else if (dl_argv_match(dl
, "show") ||
1359 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1361 return cmd_sb_port_pool_show(dl
);
1362 } else if (dl_argv_match(dl
, "set")) {
1364 return cmd_sb_port_pool_set(dl
);
1366 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1370 static int cmd_sb_port(struct dl
*dl
)
1372 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
1375 } else if (dl_argv_match(dl
, "pool")) {
1377 return cmd_sb_port_pool(dl
);
1379 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1383 static void pr_out_sb_tc_bind(struct dl
*dl
, struct nlattr
**tb
)
1385 pr_out_port_handle_nice(dl
, tb
);
1386 pr_out(": sb %u tc %u type %s pool %u threshold %u\n",
1387 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_INDEX
]),
1388 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_TC_INDEX
]),
1389 pool_type_name(mnl_attr_get_u8(tb
[DEVLINK_ATTR_SB_POOL_TYPE
])),
1390 mnl_attr_get_u16(tb
[DEVLINK_ATTR_SB_POOL_INDEX
]),
1391 mnl_attr_get_u32(tb
[DEVLINK_ATTR_SB_THRESHOLD
]));
1394 static int cmd_sb_tc_bind_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_PORT_INDEX
] || !tb
[DEVLINK_ATTR_SB_INDEX
] ||
1403 !tb
[DEVLINK_ATTR_SB_TC_INDEX
] || !tb
[DEVLINK_ATTR_SB_POOL_TYPE
] ||
1404 !tb
[DEVLINK_ATTR_SB_POOL_INDEX
] || !tb
[DEVLINK_ATTR_SB_THRESHOLD
])
1405 return MNL_CB_ERROR
;
1406 pr_out_sb_tc_bind(dl
, tb
);
1410 static int cmd_sb_tc_bind_show(struct dl
*dl
)
1412 struct nlmsghdr
*nlh
;
1413 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
1416 if (dl_argc(dl
) == 0)
1417 flags
|= NLM_F_DUMP
;
1419 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_TC_POOL_BIND_GET
, flags
);
1421 if (dl_argc(dl
) > 0) {
1422 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_SB_TC
|
1423 DL_OPT_SB_TYPE
, DL_OPT_SB
);
1428 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_sb_tc_bind_show_cb
, dl
);
1431 static int cmd_sb_tc_bind_set(struct dl
*dl
)
1433 struct nlmsghdr
*nlh
;
1436 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_SB_TC_POOL_BIND_SET
,
1437 NLM_F_REQUEST
| NLM_F_ACK
);
1439 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_SB_TC
|
1440 DL_OPT_SB_TYPE
| DL_OPT_SB_POOL
| DL_OPT_SB_TH
,
1445 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
1448 static int cmd_sb_tc_bind(struct dl
*dl
)
1450 if (dl_argv_match(dl
, "help")) {
1453 } else if (dl_argv_match(dl
, "show") ||
1454 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1456 return cmd_sb_tc_bind_show(dl
);
1457 } else if (dl_argv_match(dl
, "set")) {
1459 return cmd_sb_tc_bind_set(dl
);
1461 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1465 static int cmd_sb_tc(struct dl
*dl
)
1467 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
1470 } else if (dl_argv_match(dl
, "bind")) {
1472 return cmd_sb_tc_bind(dl
);
1474 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1478 static int cmd_sb(struct dl
*dl
)
1480 if (dl_argv_match(dl
, "help")) {
1483 } else if (dl_argv_match(dl
, "show") ||
1484 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
1486 return cmd_sb_show(dl
);
1487 } else if (dl_argv_match(dl
, "pool")) {
1489 return cmd_sb_pool(dl
);
1490 } else if (dl_argv_match(dl
, "port")) {
1492 return cmd_sb_port(dl
);
1493 } else if (dl_argv_match(dl
, "tc")) {
1495 return cmd_sb_tc(dl
);
1497 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1501 static const char *cmd_name(uint8_t cmd
)
1504 case DEVLINK_CMD_UNSPEC
: return "unspec";
1505 case DEVLINK_CMD_GET
: return "get";
1506 case DEVLINK_CMD_SET
: return "set";
1507 case DEVLINK_CMD_NEW
: return "new";
1508 case DEVLINK_CMD_DEL
: return "del";
1509 case DEVLINK_CMD_PORT_GET
: return "get";
1510 case DEVLINK_CMD_PORT_SET
: return "set";
1511 case DEVLINK_CMD_PORT_NEW
: return "net";
1512 case DEVLINK_CMD_PORT_DEL
: return "del";
1513 default: return "<unknown cmd>";
1517 static const char *cmd_obj(uint8_t cmd
)
1520 case DEVLINK_CMD_UNSPEC
: return "unspec";
1521 case DEVLINK_CMD_GET
:
1522 case DEVLINK_CMD_SET
:
1523 case DEVLINK_CMD_NEW
:
1524 case DEVLINK_CMD_DEL
:
1526 case DEVLINK_CMD_PORT_GET
:
1527 case DEVLINK_CMD_PORT_SET
:
1528 case DEVLINK_CMD_PORT_NEW
:
1529 case DEVLINK_CMD_PORT_DEL
:
1531 default: return "<unknown obj>";
1535 static void pr_out_mon_header(uint8_t cmd
)
1537 pr_out("[%s,%s] ", cmd_obj(cmd
), cmd_name(cmd
));
1540 static bool cmd_filter_check(struct dl
*dl
, uint8_t cmd
)
1542 const char *obj
= cmd_obj(cmd
);
1543 unsigned int index
= 0;
1544 const char *cur_obj
;
1548 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
1549 if (strcmp(cur_obj
, obj
) == 0 || strcmp(cur_obj
, "all") == 0)
1555 static int cmd_mon_show_cb(const struct nlmsghdr
*nlh
, void *data
)
1557 struct dl
*dl
= data
;
1558 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
1559 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
1560 uint8_t cmd
= genl
->cmd
;
1562 if (!cmd_filter_check(dl
, cmd
))
1566 case DEVLINK_CMD_GET
: /* fall through */
1567 case DEVLINK_CMD_SET
: /* fall through */
1568 case DEVLINK_CMD_NEW
: /* fall through */
1569 case DEVLINK_CMD_DEL
:
1570 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1571 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
1572 return MNL_CB_ERROR
;
1573 pr_out_mon_header(genl
->cmd
);
1576 case DEVLINK_CMD_PORT_GET
: /* fall through */
1577 case DEVLINK_CMD_PORT_SET
: /* fall through */
1578 case DEVLINK_CMD_PORT_NEW
: /* fall through */
1579 case DEVLINK_CMD_PORT_DEL
:
1580 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
1581 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
1582 !tb
[DEVLINK_ATTR_PORT_INDEX
])
1583 return MNL_CB_ERROR
;
1584 pr_out_mon_header(genl
->cmd
);
1591 static int cmd_mon_show(struct dl
*dl
)
1594 unsigned int index
= 0;
1595 const char *cur_obj
;
1597 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
1598 if (strcmp(cur_obj
, "all") != 0 &&
1599 strcmp(cur_obj
, "dev") != 0 &&
1600 strcmp(cur_obj
, "port") != 0) {
1601 pr_err("Unknown object \"%s\"\n", cur_obj
);
1605 err
= _mnlg_socket_group_add(dl
->nlg
, DEVLINK_GENL_MCGRP_CONFIG_NAME
);
1608 err
= _mnlg_socket_recv_run(dl
->nlg
, cmd_mon_show_cb
, dl
);
1614 static void cmd_mon_help(void)
1616 pr_out("Usage: devlink monitor [ all | OBJECT-LIST ]\n"
1617 "where OBJECT-LIST := { dev | port }\n");
1620 static int cmd_mon(struct dl
*dl
)
1622 if (dl_argv_match(dl
, "help")) {
1625 } else if (dl_no_arg(dl
)) {
1627 return cmd_mon_show(dl
);
1629 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1633 static void help(void)
1635 pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
1636 "where OBJECT := { dev | port | sb | monitor }\n"
1637 " OPTIONS := { -V[ersion] | -n[no-nice-names] }\n");
1640 static int dl_cmd(struct dl
*dl
)
1642 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
1645 } else if (dl_argv_match(dl
, "dev")) {
1648 } else if (dl_argv_match(dl
, "port")) {
1650 return cmd_port(dl
);
1651 } else if (dl_argv_match(dl
, "sb")) {
1654 } else if (dl_argv_match(dl
, "monitor")) {
1658 pr_err("Object \"%s\" not found\n", dl_argv(dl
));
1662 static int dl_init(struct dl
*dl
, int argc
, char **argv
)
1669 dl
->nlg
= mnlg_socket_open(DEVLINK_GENL_NAME
, DEVLINK_GENL_VERSION
);
1671 pr_err("Failed to connect to devlink Netlink\n");
1675 err
= ifname_map_init(dl
);
1677 pr_err("Failed to create index map\n");
1678 goto err_ifname_map_create
;
1682 err_ifname_map_create
:
1683 mnlg_socket_close(dl
->nlg
);
1687 static void dl_fini(struct dl
*dl
)
1689 ifname_map_fini(dl
);
1690 mnlg_socket_close(dl
->nlg
);
1693 static struct dl
*dl_alloc(void)
1697 dl
= calloc(1, sizeof(*dl
));
1703 static void dl_free(struct dl
*dl
)
1708 int main(int argc
, char **argv
)
1710 static const struct option long_options
[] = {
1711 { "Version", no_argument
, NULL
, 'V' },
1712 { "no-nice-names", no_argument
, NULL
, 'n' },
1713 { NULL
, 0, NULL
, 0 }
1722 pr_err("Failed to allocate memory for devlink\n");
1723 return EXIT_FAILURE
;
1726 while ((opt
= getopt_long(argc
, argv
, "Vn",
1727 long_options
, NULL
)) >= 0) {
1731 printf("devlink utility, iproute2-ss%s\n", SNAPSHOT
);
1732 return EXIT_SUCCESS
;
1734 dl
->no_nice_names
= true;
1737 pr_err("Unknown option.\n");
1739 return EXIT_FAILURE
;
1746 err
= dl_init(dl
, argc
, argv
);