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 int ifname_map_rev_lookup(struct dl
*dl
, const char *bus_name
,
311 const char *dev_name
, uint32_t port_index
,
314 struct ifname_map
*ifname_map
;
316 list_for_each_entry(ifname_map
, &dl
->ifname_map_list
, list
) {
317 if (strcmp(bus_name
, ifname_map
->bus_name
) == 0 &&
318 strcmp(dev_name
, ifname_map
->dev_name
) == 0 &&
319 port_index
== ifname_map
->port_index
) {
320 *p_ifname
= ifname_map
->ifname
;
327 static unsigned int strslashcount(char *str
)
329 unsigned int count
= 0;
332 while ((pos
= strchr(pos
, '/'))) {
339 static int strslashrsplit(char *str
, char **before
, char **after
)
343 slash
= strrchr(str
, '/');
352 static int strtouint32_t(const char *str
, uint32_t *p_val
)
355 unsigned long int val
;
357 val
= strtoul(str
, &endptr
, 10);
358 if (endptr
== str
|| *endptr
!= '\0')
366 static int __dl_argv_handle(char *str
, char **p_bus_name
, char **p_dev_name
)
368 strslashrsplit(str
, p_bus_name
, p_dev_name
);
372 static int dl_argv_handle(struct dl
*dl
, char **p_bus_name
, char **p_dev_name
)
374 char *str
= dl_argv_next(dl
);
377 pr_err("Devlink identification (\"bus_name/dev_name\") expected\n");
380 if (strslashcount(str
) != 1) {
381 pr_err("Wrong devlink identification string format.\n");
382 pr_err("Expected \"bus_name/dev_name\".\n");
385 return __dl_argv_handle(str
, p_bus_name
, p_dev_name
);
388 static int __dl_argv_handle_port(char *str
,
389 char **p_bus_name
, char **p_dev_name
,
390 uint32_t *p_port_index
)
392 char *handlestr
= handlestr
;
393 char *portstr
= portstr
;
396 strslashrsplit(str
, &handlestr
, &portstr
);
397 err
= strtouint32_t(portstr
, p_port_index
);
399 pr_err("Port index \"%s\" is not a number or not within range\n",
403 strslashrsplit(handlestr
, p_bus_name
, p_dev_name
);
407 static int __dl_argv_handle_port_ifname(struct dl
*dl
, char *str
,
408 char **p_bus_name
, char **p_dev_name
,
409 uint32_t *p_port_index
)
413 err
= ifname_map_lookup(dl
, str
, p_bus_name
, p_dev_name
,
416 pr_err("Netdevice \"%s\" not found\n", str
);
422 static int dl_argv_handle_port(struct dl
*dl
, char **p_bus_name
,
423 char **p_dev_name
, uint32_t *p_port_index
)
425 char *str
= dl_argv_next(dl
);
426 unsigned int slash_count
;
429 pr_err("Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\") expected.\n");
432 slash_count
= strslashcount(str
);
433 if (slash_count
!= 2 && slash_count
!= 0) {
434 pr_err("Wrong port identification string format.\n");
435 pr_err("Expected \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
438 if (slash_count
== 2) {
439 return __dl_argv_handle_port(str
, p_bus_name
,
440 p_dev_name
, p_port_index
);
441 } else if (slash_count
== 0) {
442 return __dl_argv_handle_port_ifname(dl
, str
, p_bus_name
,
443 p_dev_name
, p_port_index
);
448 static int dl_argv_handle_both(struct dl
*dl
, char **p_bus_name
,
449 char **p_dev_name
, uint32_t *p_port_index
,
450 uint32_t *p_handle_bit
)
452 char *str
= dl_argv_next(dl
);
453 unsigned int slash_count
;
457 pr_err("One of following identifications expected:\n"
458 "Devlink identification (\"bus_name/dev_name\")\n"
459 "Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\")\n");
462 slash_count
= strslashcount(str
);
463 if (slash_count
== 1) {
464 err
= __dl_argv_handle(str
, p_bus_name
, p_dev_name
);
467 *p_handle_bit
= DL_OPT_HANDLE
;
468 } else if (slash_count
== 2) {
469 err
= __dl_argv_handle_port(str
, p_bus_name
,
470 p_dev_name
, p_port_index
);
473 *p_handle_bit
= DL_OPT_HANDLEP
;
474 } else if (slash_count
== 0) {
475 err
= __dl_argv_handle_port_ifname(dl
, str
, p_bus_name
,
476 p_dev_name
, p_port_index
);
479 *p_handle_bit
= DL_OPT_HANDLEP
;
481 pr_err("Wrong port identification string format.\n");
482 pr_err("Expected \"bus_name/dev_name\" or \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
488 static int dl_argv_uint32_t(struct dl
*dl
, uint32_t *p_val
)
490 char *str
= dl_argv_next(dl
);
494 pr_err("Unsigned number argument expected\n");
498 err
= strtouint32_t(str
, p_val
);
500 pr_err("\"%s\" is not a number or not within range\n", str
);
506 static int dl_argv_str(struct dl
*dl
, const char **p_str
)
508 const char *str
= dl_argv_next(dl
);
511 pr_err("String parameter expected\n");
518 static int port_type_get(const char *typestr
, enum devlink_port_type
*p_type
)
520 if (strcmp(typestr
, "auto") == 0) {
521 *p_type
= DEVLINK_PORT_TYPE_AUTO
;
522 } else if (strcmp(typestr
, "eth") == 0) {
523 *p_type
= DEVLINK_PORT_TYPE_ETH
;
524 } else if (strcmp(typestr
, "ib") == 0) {
525 *p_type
= DEVLINK_PORT_TYPE_IB
;
527 pr_err("Unknown port type \"%s\"\n", typestr
);
533 static int dl_argv_parse(struct dl
*dl
, uint32_t o_required
,
536 struct dl_opts
*opts
= &dl
->opts
;
537 uint32_t o_all
= o_required
| o_optional
;
538 uint32_t o_found
= 0;
541 if (o_required
& DL_OPT_HANDLE
&& o_required
& DL_OPT_HANDLEP
) {
542 uint32_t handle_bit
= handle_bit
;
544 err
= dl_argv_handle_both(dl
, &opts
->bus_name
, &opts
->dev_name
,
545 &opts
->port_index
, &handle_bit
);
548 o_found
|= handle_bit
;
549 } else if (o_required
& DL_OPT_HANDLE
) {
550 err
= dl_argv_handle(dl
, &opts
->bus_name
, &opts
->dev_name
);
553 o_found
|= DL_OPT_HANDLE
;
554 } else if (o_required
& DL_OPT_HANDLEP
) {
555 err
= dl_argv_handle_port(dl
, &opts
->bus_name
, &opts
->dev_name
,
559 o_found
|= DL_OPT_HANDLEP
;
562 while (dl_argc(dl
)) {
563 if (dl_argv_match(dl
, "type") &&
564 (o_all
& DL_OPT_PORT_TYPE
)) {
568 err
= dl_argv_str(dl
, &typestr
);
571 err
= port_type_get(typestr
, &opts
->port_type
);
574 o_found
|= DL_OPT_PORT_TYPE
;
575 } else if (dl_argv_match(dl
, "count") &&
576 (o_all
& DL_OPT_PORT_COUNT
)) {
578 err
= dl_argv_uint32_t(dl
, &opts
->port_count
);
581 o_found
|= DL_OPT_PORT_COUNT
;
583 pr_err("Unknown option \"%s\"\n", dl_argv(dl
));
588 opts
->present
= o_found
;
590 if ((o_required
& DL_OPT_PORT_TYPE
) && !(o_found
& DL_OPT_PORT_TYPE
)) {
591 pr_err("Port type option expected.\n");
595 if ((o_required
& DL_OPT_PORT_COUNT
) &&
596 !(o_found
& DL_OPT_PORT_COUNT
)) {
597 pr_err("Port split count option expected.\n");
604 static void dl_opts_put(struct nlmsghdr
*nlh
, struct dl
*dl
)
606 struct dl_opts
*opts
= &dl
->opts
;
608 if (opts
->present
& DL_OPT_HANDLE
) {
609 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, opts
->bus_name
);
610 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, opts
->dev_name
);
611 } else if (opts
->present
& DL_OPT_HANDLEP
) {
612 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, opts
->bus_name
);
613 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, opts
->dev_name
);
614 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_INDEX
,
617 if (opts
->present
& DL_OPT_PORT_TYPE
)
618 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_PORT_TYPE
,
620 if (opts
->present
& DL_OPT_PORT_COUNT
)
621 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_SPLIT_COUNT
,
625 static int dl_argv_parse_put(struct nlmsghdr
*nlh
, struct dl
*dl
,
626 uint32_t o_required
, uint32_t o_optional
)
630 err
= dl_argv_parse(dl
, o_required
, o_optional
);
633 dl_opts_put(nlh
, dl
);
638 static void cmd_dev_help(void)
640 pr_out("Usage: devlink dev show [ DEV ]\n");
643 static void __pr_out_handle(const char *bus_name
, const char *dev_name
)
645 pr_out("%s/%s", bus_name
, dev_name
);
648 static void pr_out_handle(struct nlattr
**tb
)
650 __pr_out_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
651 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]));
654 static void __pr_out_port_handle(const char *bus_name
, const char *dev_name
,
657 __pr_out_handle(bus_name
, dev_name
);
658 pr_out("/%d", port_index
);
661 static void pr_out_port_handle(struct nlattr
**tb
)
663 __pr_out_port_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
664 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]),
665 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]));
668 static void __pr_out_port_handle_nice(struct dl
*dl
, const char *bus_name
,
669 const char *dev_name
, uint32_t port_index
)
674 if (dl
->no_nice_names
)
677 err
= ifname_map_rev_lookup(dl
, bus_name
, dev_name
,
678 port_index
, &ifname
);
681 pr_out("%s", ifname
);
685 __pr_out_port_handle(bus_name
, dev_name
, port_index
);
688 static void pr_out_dev(struct nlattr
**tb
)
694 static int cmd_dev_show_cb(const struct nlmsghdr
*nlh
, void *data
)
696 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
697 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
699 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
700 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
706 static int cmd_dev_show(struct dl
*dl
)
708 struct nlmsghdr
*nlh
;
709 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
712 if (dl_argc(dl
) == 0)
715 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_GET
, flags
);
717 if (dl_argc(dl
) > 0) {
718 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, 0);
723 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_dev_show_cb
, NULL
);
726 static int cmd_dev(struct dl
*dl
)
728 if (dl_argv_match(dl
, "help")) {
731 } else if (dl_argv_match(dl
, "show") ||
732 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
734 return cmd_dev_show(dl
);
736 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
740 static void cmd_port_help(void)
742 pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n");
743 pr_out(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
744 pr_out(" devlink port split DEV/PORT_INDEX count COUNT\n");
745 pr_out(" devlink port unsplit DEV/PORT_INDEX\n");
748 static const char *port_type_name(uint32_t type
)
751 case DEVLINK_PORT_TYPE_NOTSET
: return "notset";
752 case DEVLINK_PORT_TYPE_AUTO
: return "auto";
753 case DEVLINK_PORT_TYPE_ETH
: return "eth";
754 case DEVLINK_PORT_TYPE_IB
: return "ib";
755 default: return "<unknown type>";
759 static void pr_out_port(struct nlattr
**tb
)
761 struct nlattr
*pt_attr
= tb
[DEVLINK_ATTR_PORT_TYPE
];
762 struct nlattr
*dpt_attr
= tb
[DEVLINK_ATTR_PORT_DESIRED_TYPE
];
764 pr_out_port_handle(tb
);
767 uint16_t port_type
= mnl_attr_get_u16(pt_attr
);
769 pr_out(" type %s", port_type_name(port_type
));
771 uint16_t des_port_type
= mnl_attr_get_u16(dpt_attr
);
773 if (port_type
!= des_port_type
)
774 pr_out("(%s)", port_type_name(des_port_type
));
777 if (tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
779 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]));
780 if (tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
])
782 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
]));
783 if (tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
])
784 pr_out(" split_group %u",
785 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
]));
789 static int cmd_port_show_cb(const struct nlmsghdr
*nlh
, void *data
)
791 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
792 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
794 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
795 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
796 !tb
[DEVLINK_ATTR_PORT_INDEX
])
802 static int cmd_port_show(struct dl
*dl
)
804 struct nlmsghdr
*nlh
;
805 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
808 if (dl_argc(dl
) == 0)
811 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
, flags
);
813 if (dl_argc(dl
) > 0) {
814 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
819 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_port_show_cb
, NULL
);
822 static int cmd_port_set(struct dl
*dl
)
824 struct nlmsghdr
*nlh
;
827 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SET
,
828 NLM_F_REQUEST
| NLM_F_ACK
);
830 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_TYPE
, 0);
834 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
837 static int cmd_port_split(struct dl
*dl
)
839 struct nlmsghdr
*nlh
;
842 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SPLIT
,
843 NLM_F_REQUEST
| NLM_F_ACK
);
845 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_COUNT
, 0);
849 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
852 static int cmd_port_unsplit(struct dl
*dl
)
854 struct nlmsghdr
*nlh
;
857 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_UNSPLIT
,
858 NLM_F_REQUEST
| NLM_F_ACK
);
860 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
864 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
867 static int cmd_port(struct dl
*dl
)
869 if (dl_argv_match(dl
, "help")) {
872 } else if (dl_argv_match(dl
, "show") ||
873 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
875 return cmd_port_show(dl
);
876 } else if (dl_argv_match(dl
, "set")) {
878 return cmd_port_set(dl
);
879 } else if (dl_argv_match(dl
, "split")) {
881 return cmd_port_split(dl
);
882 } else if (dl_argv_match(dl
, "unsplit")) {
884 return cmd_port_unsplit(dl
);
886 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
890 static const char *cmd_name(uint8_t cmd
)
893 case DEVLINK_CMD_UNSPEC
: return "unspec";
894 case DEVLINK_CMD_GET
: return "get";
895 case DEVLINK_CMD_SET
: return "set";
896 case DEVLINK_CMD_NEW
: return "new";
897 case DEVLINK_CMD_DEL
: return "del";
898 case DEVLINK_CMD_PORT_GET
: return "get";
899 case DEVLINK_CMD_PORT_SET
: return "set";
900 case DEVLINK_CMD_PORT_NEW
: return "net";
901 case DEVLINK_CMD_PORT_DEL
: return "del";
902 default: return "<unknown cmd>";
906 static const char *cmd_obj(uint8_t cmd
)
909 case DEVLINK_CMD_UNSPEC
: return "unspec";
910 case DEVLINK_CMD_GET
:
911 case DEVLINK_CMD_SET
:
912 case DEVLINK_CMD_NEW
:
913 case DEVLINK_CMD_DEL
:
915 case DEVLINK_CMD_PORT_GET
:
916 case DEVLINK_CMD_PORT_SET
:
917 case DEVLINK_CMD_PORT_NEW
:
918 case DEVLINK_CMD_PORT_DEL
:
920 default: return "<unknown obj>";
924 static void pr_out_mon_header(uint8_t cmd
)
926 pr_out("[%s,%s] ", cmd_obj(cmd
), cmd_name(cmd
));
929 static bool cmd_filter_check(struct dl
*dl
, uint8_t cmd
)
931 const char *obj
= cmd_obj(cmd
);
932 unsigned int index
= 0;
937 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
938 if (strcmp(cur_obj
, obj
) == 0 || strcmp(cur_obj
, "all") == 0)
944 static int cmd_mon_show_cb(const struct nlmsghdr
*nlh
, void *data
)
946 struct dl
*dl
= data
;
947 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
948 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
949 uint8_t cmd
= genl
->cmd
;
951 if (!cmd_filter_check(dl
, cmd
))
955 case DEVLINK_CMD_GET
: /* fall through */
956 case DEVLINK_CMD_SET
: /* fall through */
957 case DEVLINK_CMD_NEW
: /* fall through */
958 case DEVLINK_CMD_DEL
:
959 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
960 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
962 pr_out_mon_header(genl
->cmd
);
965 case DEVLINK_CMD_PORT_GET
: /* fall through */
966 case DEVLINK_CMD_PORT_SET
: /* fall through */
967 case DEVLINK_CMD_PORT_NEW
: /* fall through */
968 case DEVLINK_CMD_PORT_DEL
:
969 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
970 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
971 !tb
[DEVLINK_ATTR_PORT_INDEX
])
973 pr_out_mon_header(genl
->cmd
);
980 static int cmd_mon_show(struct dl
*dl
)
983 unsigned int index
= 0;
986 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
987 if (strcmp(cur_obj
, "all") != 0 &&
988 strcmp(cur_obj
, "dev") != 0 &&
989 strcmp(cur_obj
, "port") != 0) {
990 pr_err("Unknown object \"%s\"\n", cur_obj
);
994 err
= _mnlg_socket_group_add(dl
->nlg
, DEVLINK_GENL_MCGRP_CONFIG_NAME
);
997 err
= _mnlg_socket_recv_run(dl
->nlg
, cmd_mon_show_cb
, dl
);
1003 static void cmd_mon_help(void)
1005 pr_out("Usage: devlink monitor [ all | OBJECT-LIST ]\n"
1006 "where OBJECT-LIST := { dev | port }\n");
1009 static int cmd_mon(struct dl
*dl
)
1011 if (dl_argv_match(dl
, "help")) {
1014 } else if (dl_no_arg(dl
)) {
1016 return cmd_mon_show(dl
);
1018 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
1022 static void help(void)
1024 pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
1025 "where OBJECT := { dev | port | monitor }\n"
1026 " OPTIONS := { -V[ersion] | -n[no-nice-names] }\n");
1029 static int dl_cmd(struct dl
*dl
)
1031 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
1034 } else if (dl_argv_match(dl
, "dev")) {
1037 } else if (dl_argv_match(dl
, "port")) {
1039 return cmd_port(dl
);
1040 } else if (dl_argv_match(dl
, "monitor")) {
1044 pr_err("Object \"%s\" not found\n", dl_argv(dl
));
1048 static int dl_init(struct dl
*dl
, int argc
, char **argv
)
1055 dl
->nlg
= mnlg_socket_open(DEVLINK_GENL_NAME
, DEVLINK_GENL_VERSION
);
1057 pr_err("Failed to connect to devlink Netlink\n");
1061 err
= ifname_map_init(dl
);
1063 pr_err("Failed to create index map\n");
1064 goto err_ifname_map_create
;
1068 err_ifname_map_create
:
1069 mnlg_socket_close(dl
->nlg
);
1073 static void dl_fini(struct dl
*dl
)
1075 ifname_map_fini(dl
);
1076 mnlg_socket_close(dl
->nlg
);
1079 static struct dl
*dl_alloc(void)
1083 dl
= calloc(1, sizeof(*dl
));
1089 static void dl_free(struct dl
*dl
)
1094 int main(int argc
, char **argv
)
1096 static const struct option long_options
[] = {
1097 { "Version", no_argument
, NULL
, 'V' },
1098 { "no-nice-names", no_argument
, NULL
, 'n' },
1099 { NULL
, 0, NULL
, 0 }
1108 pr_err("Failed to allocate memory for devlink\n");
1109 return EXIT_FAILURE
;
1112 while ((opt
= getopt_long(argc
, argv
, "Vn",
1113 long_options
, NULL
)) >= 0) {
1117 printf("devlink utility, iproute2-ss%s\n", SNAPSHOT
);
1118 return EXIT_SUCCESS
;
1120 dl
->no_nice_names
= true;
1123 pr_err("Unknown option.\n");
1125 return EXIT_FAILURE
;
1132 err
= dl_init(dl
, argc
, argv
);