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)
119 uint32_t present
; /* flags of present items */
123 enum devlink_port_type port_type
;
128 struct mnlg_socket
*nlg
;
129 struct list_head ifname_map_list
;
136 static int dl_argc(struct dl
*dl
)
141 static char *dl_argv(struct dl
*dl
)
143 if (dl_argc(dl
) == 0)
148 static void dl_arg_inc(struct dl
*dl
)
150 if (dl_argc(dl
) == 0)
156 static char *dl_argv_next(struct dl
*dl
)
160 if (dl_argc(dl
) == 0)
168 static char *dl_argv_index(struct dl
*dl
, unsigned int index
)
170 if (index
>= dl_argc(dl
))
172 return dl
->argv
[index
];
175 static int strcmpx(const char *str1
, const char *str2
)
177 if (strlen(str1
) > strlen(str2
))
179 return strncmp(str1
, str2
, strlen(str1
));
182 static bool dl_argv_match(struct dl
*dl
, const char *pattern
)
184 if (dl_argc(dl
) == 0)
186 return strcmpx(dl_argv(dl
), pattern
) == 0;
189 static bool dl_no_arg(struct dl
*dl
)
191 return dl_argc(dl
) == 0;
194 static int attr_cb(const struct nlattr
*attr
, void *data
)
196 const struct nlattr
**tb
= data
;
199 type
= mnl_attr_get_type(attr
);
201 if (mnl_attr_type_valid(attr
, DEVLINK_ATTR_MAX
) < 0)
204 if (type
== DEVLINK_ATTR_BUS_NAME
&&
205 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
207 if (type
== DEVLINK_ATTR_DEV_NAME
&&
208 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
210 if (type
== DEVLINK_ATTR_PORT_INDEX
&&
211 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
213 if (type
== DEVLINK_ATTR_PORT_TYPE
&&
214 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
216 if (type
== DEVLINK_ATTR_PORT_DESIRED_TYPE
&&
217 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
219 if (type
== DEVLINK_ATTR_PORT_NETDEV_IFINDEX
&&
220 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
222 if (type
== DEVLINK_ATTR_PORT_NETDEV_NAME
&&
223 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
225 if (type
== DEVLINK_ATTR_PORT_IBDEV_NAME
&&
226 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
232 static int ifname_map_cb(const struct nlmsghdr
*nlh
, void *data
)
234 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
235 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
236 struct dl
*dl
= data
;
237 struct ifname_map
*ifname_map
;
238 const char *bus_name
;
239 const char *dev_name
;
240 uint32_t port_ifindex
;
241 const char *port_ifname
;
243 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
244 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
245 !tb
[DEVLINK_ATTR_PORT_INDEX
])
248 if (!tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
251 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
252 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
253 port_ifindex
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
254 port_ifname
= mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]);
255 ifname_map
= ifname_map_alloc(bus_name
, dev_name
,
256 port_ifindex
, port_ifname
);
259 list_add(&ifname_map
->list
, &dl
->ifname_map_list
);
264 static void ifname_map_fini(struct dl
*dl
)
266 struct ifname_map
*ifname_map
, *tmp
;
268 list_for_each_entry_safe(ifname_map
, tmp
,
269 &dl
->ifname_map_list
, list
) {
270 list_del(&ifname_map
->list
);
271 ifname_map_free(ifname_map
);
275 static int ifname_map_init(struct dl
*dl
)
277 struct nlmsghdr
*nlh
;
280 INIT_LIST_HEAD(&dl
->ifname_map_list
);
282 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
,
283 NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
);
285 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, ifname_map_cb
, dl
);
293 static int ifname_map_lookup(struct dl
*dl
, const char *ifname
,
294 char **p_bus_name
, char **p_dev_name
,
295 uint32_t *p_port_index
)
297 struct ifname_map
*ifname_map
;
299 list_for_each_entry(ifname_map
, &dl
->ifname_map_list
, list
) {
300 if (strcmp(ifname
, ifname_map
->ifname
) == 0) {
301 *p_bus_name
= ifname_map
->bus_name
;
302 *p_dev_name
= ifname_map
->dev_name
;
303 *p_port_index
= ifname_map
->port_index
;
310 static unsigned int strslashcount(char *str
)
312 unsigned int count
= 0;
315 while ((pos
= strchr(pos
, '/'))) {
322 static int strslashrsplit(char *str
, char **before
, char **after
)
326 slash
= strrchr(str
, '/');
335 static int strtouint32_t(const char *str
, uint32_t *p_val
)
338 unsigned long int val
;
340 val
= strtoul(str
, &endptr
, 10);
341 if (endptr
== str
|| *endptr
!= '\0')
349 static int __dl_argv_handle(char *str
, char **p_bus_name
, char **p_dev_name
)
351 strslashrsplit(str
, p_bus_name
, p_dev_name
);
355 static int dl_argv_handle(struct dl
*dl
, char **p_bus_name
, char **p_dev_name
)
357 char *str
= dl_argv_next(dl
);
360 pr_err("Devlink identification (\"bus_name/dev_name\") expected\n");
363 if (strslashcount(str
) != 1) {
364 pr_err("Wrong devlink identification string format.\n");
365 pr_err("Expected \"bus_name/dev_name\".\n");
368 return __dl_argv_handle(str
, p_bus_name
, p_dev_name
);
371 static int __dl_argv_handle_port(char *str
,
372 char **p_bus_name
, char **p_dev_name
,
373 uint32_t *p_port_index
)
375 char *handlestr
= handlestr
;
376 char *portstr
= portstr
;
379 strslashrsplit(str
, &handlestr
, &portstr
);
380 err
= strtouint32_t(portstr
, p_port_index
);
382 pr_err("Port index \"%s\" is not a number or not within range\n",
386 strslashrsplit(handlestr
, p_bus_name
, p_dev_name
);
390 static int __dl_argv_handle_port_ifname(struct dl
*dl
, char *str
,
391 char **p_bus_name
, char **p_dev_name
,
392 uint32_t *p_port_index
)
396 err
= ifname_map_lookup(dl
, str
, p_bus_name
, p_dev_name
,
399 pr_err("Netdevice \"%s\" not found\n", str
);
405 static int dl_argv_handle_port(struct dl
*dl
, char **p_bus_name
,
406 char **p_dev_name
, uint32_t *p_port_index
)
408 char *str
= dl_argv_next(dl
);
409 unsigned int slash_count
;
412 pr_err("Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\") expected.\n");
415 slash_count
= strslashcount(str
);
416 if (slash_count
!= 2 && slash_count
!= 0) {
417 pr_err("Wrong port identification string format.\n");
418 pr_err("Expected \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
421 if (slash_count
== 2) {
422 return __dl_argv_handle_port(str
, p_bus_name
,
423 p_dev_name
, p_port_index
);
424 } else if (slash_count
== 0) {
425 return __dl_argv_handle_port_ifname(dl
, str
, p_bus_name
,
426 p_dev_name
, p_port_index
);
431 static int dl_argv_handle_both(struct dl
*dl
, char **p_bus_name
,
432 char **p_dev_name
, uint32_t *p_port_index
,
433 uint32_t *p_handle_bit
)
435 char *str
= dl_argv_next(dl
);
436 unsigned int slash_count
;
440 pr_err("One of following identifications expected:\n"
441 "Devlink identification (\"bus_name/dev_name\")\n"
442 "Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\")\n");
445 slash_count
= strslashcount(str
);
446 if (slash_count
== 1) {
447 err
= __dl_argv_handle(str
, p_bus_name
, p_dev_name
);
450 *p_handle_bit
= DL_OPT_HANDLE
;
451 } else if (slash_count
== 2) {
452 err
= __dl_argv_handle_port(str
, p_bus_name
,
453 p_dev_name
, p_port_index
);
456 *p_handle_bit
= DL_OPT_HANDLEP
;
457 } else if (slash_count
== 0) {
458 err
= __dl_argv_handle_port_ifname(dl
, str
, p_bus_name
,
459 p_dev_name
, p_port_index
);
462 *p_handle_bit
= DL_OPT_HANDLEP
;
464 pr_err("Wrong port identification string format.\n");
465 pr_err("Expected \"bus_name/dev_name\" or \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
471 static int dl_argv_uint32_t(struct dl
*dl
, uint32_t *p_val
)
473 char *str
= dl_argv_next(dl
);
477 pr_err("Unsigned number argument expected\n");
481 err
= strtouint32_t(str
, p_val
);
483 pr_err("\"%s\" is not a number or not within range\n", str
);
489 static int dl_argv_str(struct dl
*dl
, const char **p_str
)
491 const char *str
= dl_argv_next(dl
);
494 pr_err("String parameter expected\n");
501 static int port_type_get(const char *typestr
, enum devlink_port_type
*p_type
)
503 if (strcmp(typestr
, "auto") == 0) {
504 *p_type
= DEVLINK_PORT_TYPE_AUTO
;
505 } else if (strcmp(typestr
, "eth") == 0) {
506 *p_type
= DEVLINK_PORT_TYPE_ETH
;
507 } else if (strcmp(typestr
, "ib") == 0) {
508 *p_type
= DEVLINK_PORT_TYPE_IB
;
510 pr_err("Unknown port type \"%s\"\n", typestr
);
516 static int dl_argv_parse(struct dl
*dl
, uint32_t o_required
,
519 struct dl_opts
*opts
= &dl
->opts
;
520 uint32_t o_all
= o_required
| o_optional
;
521 uint32_t o_found
= 0;
524 if (o_required
& DL_OPT_HANDLE
&& o_required
& DL_OPT_HANDLEP
) {
525 uint32_t handle_bit
= handle_bit
;
527 err
= dl_argv_handle_both(dl
, &opts
->bus_name
, &opts
->dev_name
,
528 &opts
->port_index
, &handle_bit
);
531 o_found
|= handle_bit
;
532 } else if (o_required
& DL_OPT_HANDLE
) {
533 err
= dl_argv_handle(dl
, &opts
->bus_name
, &opts
->dev_name
);
536 o_found
|= DL_OPT_HANDLE
;
537 } else if (o_required
& DL_OPT_HANDLEP
) {
538 err
= dl_argv_handle_port(dl
, &opts
->bus_name
, &opts
->dev_name
,
542 o_found
|= DL_OPT_HANDLEP
;
545 while (dl_argc(dl
)) {
546 if (dl_argv_match(dl
, "type") &&
547 (o_all
& DL_OPT_PORT_TYPE
)) {
551 err
= dl_argv_str(dl
, &typestr
);
554 err
= port_type_get(typestr
, &opts
->port_type
);
557 o_found
|= DL_OPT_PORT_TYPE
;
558 } else if (dl_argv_match(dl
, "count") &&
559 (o_all
& DL_OPT_PORT_COUNT
)) {
561 err
= dl_argv_uint32_t(dl
, &opts
->port_count
);
564 o_found
|= DL_OPT_PORT_COUNT
;
566 pr_err("Unknown option \"%s\"\n", dl_argv(dl
));
571 opts
->present
= o_found
;
573 if ((o_required
& DL_OPT_PORT_TYPE
) && !(o_found
& DL_OPT_PORT_TYPE
)) {
574 pr_err("Port type option expected.\n");
578 if ((o_required
& DL_OPT_PORT_COUNT
) &&
579 !(o_found
& DL_OPT_PORT_COUNT
)) {
580 pr_err("Port split count option expected.\n");
587 static void dl_opts_put(struct nlmsghdr
*nlh
, struct dl
*dl
)
589 struct dl_opts
*opts
= &dl
->opts
;
591 if (opts
->present
& DL_OPT_HANDLE
) {
592 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, opts
->bus_name
);
593 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, opts
->dev_name
);
594 } else if (opts
->present
& DL_OPT_HANDLEP
) {
595 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, opts
->bus_name
);
596 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, opts
->dev_name
);
597 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_INDEX
,
600 if (opts
->present
& DL_OPT_PORT_TYPE
)
601 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_PORT_TYPE
,
603 if (opts
->present
& DL_OPT_PORT_COUNT
)
604 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_SPLIT_COUNT
,
608 static int dl_argv_parse_put(struct nlmsghdr
*nlh
, struct dl
*dl
,
609 uint32_t o_required
, uint32_t o_optional
)
613 err
= dl_argv_parse(dl
, o_required
, o_optional
);
616 dl_opts_put(nlh
, dl
);
621 static void cmd_dev_help(void)
623 pr_out("Usage: devlink dev show [ DEV ]\n");
626 static void __pr_out_handle(const char *bus_name
, const char *dev_name
)
628 pr_out("%s/%s", bus_name
, dev_name
);
631 static void pr_out_handle(struct nlattr
**tb
)
633 __pr_out_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
634 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]));
637 static void __pr_out_port_handle(const char *bus_name
, const char *dev_name
,
640 __pr_out_handle(bus_name
, dev_name
);
641 pr_out("/%d", port_index
);
644 static void pr_out_port_handle(struct nlattr
**tb
)
646 __pr_out_port_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
647 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]),
648 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]));
651 static void pr_out_dev(struct nlattr
**tb
)
657 static int cmd_dev_show_cb(const struct nlmsghdr
*nlh
, void *data
)
659 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
660 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
662 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
663 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
669 static int cmd_dev_show(struct dl
*dl
)
671 struct nlmsghdr
*nlh
;
672 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
675 if (dl_argc(dl
) == 0)
678 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_GET
, flags
);
680 if (dl_argc(dl
) > 0) {
681 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, 0);
686 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_dev_show_cb
, NULL
);
689 static int cmd_dev(struct dl
*dl
)
691 if (dl_argv_match(dl
, "help")) {
694 } else if (dl_argv_match(dl
, "show") ||
695 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
697 return cmd_dev_show(dl
);
699 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
703 static void cmd_port_help(void)
705 pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n");
706 pr_out(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
707 pr_out(" devlink port split DEV/PORT_INDEX count COUNT\n");
708 pr_out(" devlink port unsplit DEV/PORT_INDEX\n");
711 static const char *port_type_name(uint32_t type
)
714 case DEVLINK_PORT_TYPE_NOTSET
: return "notset";
715 case DEVLINK_PORT_TYPE_AUTO
: return "auto";
716 case DEVLINK_PORT_TYPE_ETH
: return "eth";
717 case DEVLINK_PORT_TYPE_IB
: return "ib";
718 default: return "<unknown type>";
722 static void pr_out_port(struct nlattr
**tb
)
724 struct nlattr
*pt_attr
= tb
[DEVLINK_ATTR_PORT_TYPE
];
725 struct nlattr
*dpt_attr
= tb
[DEVLINK_ATTR_PORT_DESIRED_TYPE
];
727 pr_out_port_handle(tb
);
730 uint16_t port_type
= mnl_attr_get_u16(pt_attr
);
732 pr_out(" type %s", port_type_name(port_type
));
734 uint16_t des_port_type
= mnl_attr_get_u16(dpt_attr
);
736 if (port_type
!= des_port_type
)
737 pr_out("(%s)", port_type_name(des_port_type
));
740 if (tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
742 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]));
743 if (tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
])
745 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
]));
746 if (tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
])
747 pr_out(" split_group %u",
748 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
]));
752 static int cmd_port_show_cb(const struct nlmsghdr
*nlh
, void *data
)
754 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
755 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
757 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
758 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
759 !tb
[DEVLINK_ATTR_PORT_INDEX
])
765 static int cmd_port_show(struct dl
*dl
)
767 struct nlmsghdr
*nlh
;
768 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
771 if (dl_argc(dl
) == 0)
774 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
, flags
);
776 if (dl_argc(dl
) > 0) {
777 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
782 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_port_show_cb
, NULL
);
785 static int cmd_port_set(struct dl
*dl
)
787 struct nlmsghdr
*nlh
;
790 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SET
,
791 NLM_F_REQUEST
| NLM_F_ACK
);
793 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_TYPE
, 0);
797 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
800 static int cmd_port_split(struct dl
*dl
)
802 struct nlmsghdr
*nlh
;
805 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SPLIT
,
806 NLM_F_REQUEST
| NLM_F_ACK
);
808 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_COUNT
, 0);
812 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
815 static int cmd_port_unsplit(struct dl
*dl
)
817 struct nlmsghdr
*nlh
;
820 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_UNSPLIT
,
821 NLM_F_REQUEST
| NLM_F_ACK
);
823 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
827 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
830 static int cmd_port(struct dl
*dl
)
832 if (dl_argv_match(dl
, "help")) {
835 } else if (dl_argv_match(dl
, "show") ||
836 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
838 return cmd_port_show(dl
);
839 } else if (dl_argv_match(dl
, "set")) {
841 return cmd_port_set(dl
);
842 } else if (dl_argv_match(dl
, "split")) {
844 return cmd_port_split(dl
);
845 } else if (dl_argv_match(dl
, "unsplit")) {
847 return cmd_port_unsplit(dl
);
849 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
853 static const char *cmd_name(uint8_t cmd
)
856 case DEVLINK_CMD_UNSPEC
: return "unspec";
857 case DEVLINK_CMD_GET
: return "get";
858 case DEVLINK_CMD_SET
: return "set";
859 case DEVLINK_CMD_NEW
: return "new";
860 case DEVLINK_CMD_DEL
: return "del";
861 case DEVLINK_CMD_PORT_GET
: return "get";
862 case DEVLINK_CMD_PORT_SET
: return "set";
863 case DEVLINK_CMD_PORT_NEW
: return "net";
864 case DEVLINK_CMD_PORT_DEL
: return "del";
865 default: return "<unknown cmd>";
869 static const char *cmd_obj(uint8_t cmd
)
872 case DEVLINK_CMD_UNSPEC
: return "unspec";
873 case DEVLINK_CMD_GET
:
874 case DEVLINK_CMD_SET
:
875 case DEVLINK_CMD_NEW
:
876 case DEVLINK_CMD_DEL
:
878 case DEVLINK_CMD_PORT_GET
:
879 case DEVLINK_CMD_PORT_SET
:
880 case DEVLINK_CMD_PORT_NEW
:
881 case DEVLINK_CMD_PORT_DEL
:
883 default: return "<unknown obj>";
887 static void pr_out_mon_header(uint8_t cmd
)
889 pr_out("[%s,%s] ", cmd_obj(cmd
), cmd_name(cmd
));
892 static bool cmd_filter_check(struct dl
*dl
, uint8_t cmd
)
894 const char *obj
= cmd_obj(cmd
);
895 unsigned int index
= 0;
900 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
901 if (strcmp(cur_obj
, obj
) == 0 || strcmp(cur_obj
, "all") == 0)
907 static int cmd_mon_show_cb(const struct nlmsghdr
*nlh
, void *data
)
909 struct dl
*dl
= data
;
910 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
911 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
912 uint8_t cmd
= genl
->cmd
;
914 if (!cmd_filter_check(dl
, cmd
))
918 case DEVLINK_CMD_GET
: /* fall through */
919 case DEVLINK_CMD_SET
: /* fall through */
920 case DEVLINK_CMD_NEW
: /* fall through */
921 case DEVLINK_CMD_DEL
:
922 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
923 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
925 pr_out_mon_header(genl
->cmd
);
928 case DEVLINK_CMD_PORT_GET
: /* fall through */
929 case DEVLINK_CMD_PORT_SET
: /* fall through */
930 case DEVLINK_CMD_PORT_NEW
: /* fall through */
931 case DEVLINK_CMD_PORT_DEL
:
932 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
933 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
934 !tb
[DEVLINK_ATTR_PORT_INDEX
])
936 pr_out_mon_header(genl
->cmd
);
943 static int cmd_mon_show(struct dl
*dl
)
946 unsigned int index
= 0;
949 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
950 if (strcmp(cur_obj
, "all") != 0 &&
951 strcmp(cur_obj
, "dev") != 0 &&
952 strcmp(cur_obj
, "port") != 0) {
953 pr_err("Unknown object \"%s\"\n", cur_obj
);
957 err
= _mnlg_socket_group_add(dl
->nlg
, DEVLINK_GENL_MCGRP_CONFIG_NAME
);
960 err
= _mnlg_socket_recv_run(dl
->nlg
, cmd_mon_show_cb
, dl
);
966 static void cmd_mon_help(void)
968 pr_out("Usage: devlink monitor [ all | OBJECT-LIST ]\n"
969 "where OBJECT-LIST := { dev | port }\n");
972 static int cmd_mon(struct dl
*dl
)
974 if (dl_argv_match(dl
, "help")) {
977 } else if (dl_no_arg(dl
)) {
979 return cmd_mon_show(dl
);
981 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
985 static void help(void)
987 pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
988 "where OBJECT := { dev | port | monitor }\n"
989 " OPTIONS := { -V[ersion] | -n[no-nice-names] }\n");
992 static int dl_cmd(struct dl
*dl
)
994 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
997 } else if (dl_argv_match(dl
, "dev")) {
1000 } else if (dl_argv_match(dl
, "port")) {
1002 return cmd_port(dl
);
1003 } else if (dl_argv_match(dl
, "monitor")) {
1007 pr_err("Object \"%s\" not found\n", dl_argv(dl
));
1011 static int dl_init(struct dl
*dl
, int argc
, char **argv
)
1018 dl
->nlg
= mnlg_socket_open(DEVLINK_GENL_NAME
, DEVLINK_GENL_VERSION
);
1020 pr_err("Failed to connect to devlink Netlink\n");
1024 err
= ifname_map_init(dl
);
1026 pr_err("Failed to create index map\n");
1027 goto err_ifname_map_create
;
1031 err_ifname_map_create
:
1032 mnlg_socket_close(dl
->nlg
);
1036 static void dl_fini(struct dl
*dl
)
1038 ifname_map_fini(dl
);
1039 mnlg_socket_close(dl
->nlg
);
1042 static struct dl
*dl_alloc(void)
1046 dl
= calloc(1, sizeof(*dl
));
1052 static void dl_free(struct dl
*dl
)
1057 int main(int argc
, char **argv
)
1059 static const struct option long_options
[] = {
1060 { "Version", no_argument
, NULL
, 'V' },
1061 { "no-nice-names", no_argument
, NULL
, 'n' },
1062 { NULL
, 0, NULL
, 0 }
1071 pr_err("Failed to allocate memory for devlink\n");
1072 return EXIT_FAILURE
;
1075 while ((opt
= getopt_long(argc
, argv
, "Vn",
1076 long_options
, NULL
)) >= 0) {
1080 printf("devlink utility, iproute2-ss%s\n", SNAPSHOT
);
1081 return EXIT_SUCCESS
;
1083 dl
->no_nice_names
= true;
1086 pr_err("Unknown option.\n");
1088 return EXIT_FAILURE
;
1095 err
= dl_init(dl
, argc
, argv
);