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
);
113 struct mnlg_socket
*nlg
;
114 struct list_head ifname_map_list
;
120 static int dl_argc(struct dl
*dl
)
125 static char *dl_argv(struct dl
*dl
)
127 if (dl_argc(dl
) == 0)
132 static void dl_arg_inc(struct dl
*dl
)
134 if (dl_argc(dl
) == 0)
140 static char *dl_argv_next(struct dl
*dl
)
144 if (dl_argc(dl
) == 0)
152 static char *dl_argv_index(struct dl
*dl
, unsigned int index
)
154 if (index
>= dl_argc(dl
))
156 return dl
->argv
[index
];
159 static int strcmpx(const char *str1
, const char *str2
)
161 if (strlen(str1
) > strlen(str2
))
163 return strncmp(str1
, str2
, strlen(str1
));
166 static bool dl_argv_match(struct dl
*dl
, const char *pattern
)
168 if (dl_argc(dl
) == 0)
170 return strcmpx(dl_argv(dl
), pattern
) == 0;
173 static bool dl_no_arg(struct dl
*dl
)
175 return dl_argc(dl
) == 0;
178 static int attr_cb(const struct nlattr
*attr
, void *data
)
180 const struct nlattr
**tb
= data
;
183 type
= mnl_attr_get_type(attr
);
185 if (mnl_attr_type_valid(attr
, DEVLINK_ATTR_MAX
) < 0)
188 if (type
== DEVLINK_ATTR_BUS_NAME
&&
189 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
191 if (type
== DEVLINK_ATTR_DEV_NAME
&&
192 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
194 if (type
== DEVLINK_ATTR_PORT_INDEX
&&
195 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
197 if (type
== DEVLINK_ATTR_PORT_TYPE
&&
198 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
200 if (type
== DEVLINK_ATTR_PORT_DESIRED_TYPE
&&
201 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
203 if (type
== DEVLINK_ATTR_PORT_NETDEV_IFINDEX
&&
204 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
206 if (type
== DEVLINK_ATTR_PORT_NETDEV_NAME
&&
207 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
209 if (type
== DEVLINK_ATTR_PORT_IBDEV_NAME
&&
210 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
216 static int ifname_map_cb(const struct nlmsghdr
*nlh
, void *data
)
218 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
219 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
220 struct dl
*dl
= data
;
221 struct ifname_map
*ifname_map
;
222 const char *bus_name
;
223 const char *dev_name
;
224 uint32_t port_ifindex
;
225 const char *port_ifname
;
227 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
228 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
229 !tb
[DEVLINK_ATTR_PORT_INDEX
])
232 if (!tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
235 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
236 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
237 port_ifindex
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
238 port_ifname
= mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]);
239 ifname_map
= ifname_map_alloc(bus_name
, dev_name
,
240 port_ifindex
, port_ifname
);
243 list_add(&ifname_map
->list
, &dl
->ifname_map_list
);
248 static void ifname_map_fini(struct dl
*dl
)
250 struct ifname_map
*ifname_map
, *tmp
;
252 list_for_each_entry_safe(ifname_map
, tmp
,
253 &dl
->ifname_map_list
, list
) {
254 list_del(&ifname_map
->list
);
255 ifname_map_free(ifname_map
);
259 static int ifname_map_init(struct dl
*dl
)
261 struct nlmsghdr
*nlh
;
264 INIT_LIST_HEAD(&dl
->ifname_map_list
);
266 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
,
267 NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
);
269 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, ifname_map_cb
, dl
);
277 static int ifname_map_lookup(struct dl
*dl
, const char *ifname
,
278 char **p_bus_name
, char **p_dev_name
,
279 uint32_t *p_port_index
)
281 struct ifname_map
*ifname_map
;
283 list_for_each_entry(ifname_map
, &dl
->ifname_map_list
, list
) {
284 if (strcmp(ifname
, ifname_map
->ifname
) == 0) {
285 *p_bus_name
= ifname_map
->bus_name
;
286 *p_dev_name
= ifname_map
->dev_name
;
287 *p_port_index
= ifname_map
->port_index
;
294 static int ifname_map_rev_lookup(struct dl
*dl
, const char *bus_name
,
295 const char *dev_name
, uint32_t port_index
,
298 struct ifname_map
*ifname_map
;
300 list_for_each_entry(ifname_map
, &dl
->ifname_map_list
, list
) {
301 if (strcmp(bus_name
, ifname_map
->bus_name
) == 0 &&
302 strcmp(dev_name
, ifname_map
->dev_name
) == 0 &&
303 port_index
== ifname_map
->port_index
) {
304 *p_ifname
= ifname_map
->ifname
;
311 static unsigned int strslashcount(char *str
)
313 unsigned int count
= 0;
316 while ((pos
= strchr(pos
, '/'))) {
323 static int strslashrsplit(char *str
, char **before
, char **after
)
327 slash
= strrchr(str
, '/');
336 static int strtouint32_t(const char *str
, uint32_t *p_val
)
339 unsigned long int val
;
341 val
= strtoul(str
, &endptr
, 10);
342 if (endptr
== str
|| *endptr
!= '\0')
350 static int dl_argv_put_handle(struct nlmsghdr
*nlh
, struct dl
*dl
)
352 char *str
= dl_argv_next(dl
);
353 char *bus_name
= bus_name
;
354 char *dev_name
= dev_name
;
357 pr_err("Devlink identification (\"bus_name/dev_name\") expected\n");
360 if (strslashcount(str
) != 1) {
361 pr_err("Wrong devlink identification string format.\n");
362 pr_err("Expected \"bus_name/dev_name\".\n");
366 strslashrsplit(str
, &bus_name
, &dev_name
);
367 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, bus_name
);
368 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, dev_name
);
372 static int dl_argv_put_handle_port(struct nlmsghdr
*nlh
, struct dl
*dl
)
374 char *str
= dl_argv_next(dl
);
375 unsigned int slash_count
;
376 char *bus_name
= bus_name
;
377 char *dev_name
= dev_name
;
378 uint32_t port_index
= port_index
;
382 pr_err("Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\") expected.\n");
385 slash_count
= strslashcount(str
);
386 if (slash_count
!= 2 && slash_count
!= 0) {
387 pr_err("Wrong port identification string format.\n");
388 pr_err("Expected \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
392 if (slash_count
== 2) {
393 char *handlestr
= handlestr
;
394 char *portstr
= portstr
;
396 err
= strslashrsplit(str
, &handlestr
, &portstr
);
397 err
= strtouint32_t(portstr
, &port_index
);
399 pr_err("Port index \"%s\" is not a number or not within range\n",
403 strslashrsplit(handlestr
, &bus_name
, &dev_name
);
404 } else if (slash_count
== 0) {
405 err
= ifname_map_lookup(dl
, str
, &bus_name
, &dev_name
,
408 pr_err("Netdevice \"%s\" not found\n", str
);
412 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, bus_name
);
413 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, dev_name
);
414 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_INDEX
, port_index
);
418 static int dl_argv_uint32_t(struct dl
*dl
, uint32_t *p_val
)
420 char *str
= dl_argv_next(dl
);
424 pr_err("Unsigned number argument expected\n");
428 err
= strtouint32_t(str
, p_val
);
430 pr_err("\"%s\" is not a number or not within range\n", str
);
436 static int dl_argv_str(struct dl
*dl
, const char **p_str
)
438 const char *str
= dl_argv_next(dl
);
441 pr_err("String parameter expected\n");
448 static int port_type_get(const char *typestr
, enum devlink_port_type
*p_type
)
450 if (strcmp(typestr
, "auto") == 0) {
451 *p_type
= DEVLINK_PORT_TYPE_AUTO
;
452 } else if (strcmp(typestr
, "eth") == 0) {
453 *p_type
= DEVLINK_PORT_TYPE_ETH
;
454 } else if (strcmp(typestr
, "ib") == 0) {
455 *p_type
= DEVLINK_PORT_TYPE_IB
;
457 pr_err("Unknown port type \"%s\"\n", typestr
);
463 #define BIT(nr) (1UL << (nr))
464 #define DL_OPT_HANDLE BIT(0)
465 #define DL_OPT_HANDLEP BIT(1)
466 #define DL_OPT_PORT_TYPE BIT(2)
467 #define DL_OPT_PORT_COUNT BIT(3)
469 static int dl_argv_parse_put(struct nlmsghdr
*nlh
, struct dl
*dl
,
470 uint32_t o_required
, uint32_t o_optional
)
472 uint32_t o_all
= o_required
| o_optional
;
473 uint32_t o_found
= 0;
476 if (o_required
& DL_OPT_HANDLE
) {
477 err
= dl_argv_put_handle(nlh
, dl
);
480 } else if (o_required
& DL_OPT_HANDLEP
) {
481 err
= dl_argv_put_handle_port(nlh
, dl
);
486 while (dl_argc(dl
)) {
487 if (dl_argv_match(dl
, "type") &&
488 (o_all
& DL_OPT_PORT_TYPE
)) {
489 enum devlink_port_type port_type
;
493 err
= dl_argv_str(dl
, &typestr
);
496 err
= port_type_get(typestr
, &port_type
);
499 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_PORT_TYPE
,
501 o_found
|= DL_OPT_PORT_TYPE
;
502 } else if (dl_argv_match(dl
, "count") &&
503 (o_all
& DL_OPT_PORT_COUNT
)) {
507 err
= dl_argv_uint32_t(dl
, &count
);
510 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_SPLIT_COUNT
,
512 o_found
|= DL_OPT_PORT_COUNT
;
514 pr_err("Unknown option \"%s\"\n", dl_argv(dl
));
519 if ((o_required
& DL_OPT_PORT_TYPE
) && !(o_found
& DL_OPT_PORT_TYPE
)) {
520 pr_err("Port type option expected.\n");
524 if ((o_required
& DL_OPT_PORT_COUNT
) &&
525 !(o_found
& DL_OPT_PORT_COUNT
)) {
526 pr_err("Port split count option expected.\n");
533 static void cmd_dev_help(void)
535 pr_out("Usage: devlink dev show [ DEV ]\n");
538 static void __pr_out_handle(const char *bus_name
, const char *dev_name
)
540 pr_out("%s/%s", bus_name
, dev_name
);
543 static void pr_out_handle(struct nlattr
**tb
)
545 __pr_out_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
546 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]));
549 static void __pr_out_port_handle(const char *bus_name
, const char *dev_name
,
552 __pr_out_handle(bus_name
, dev_name
);
553 pr_out("/%d", port_index
);
556 static void pr_out_port_handle(struct nlattr
**tb
)
558 __pr_out_port_handle(mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
559 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]),
560 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]));
563 static void __pr_out_port_handle_nice(struct dl
*dl
, const char *bus_name
,
564 const char *dev_name
, uint32_t port_index
)
569 if (dl
->no_nice_names
)
572 err
= ifname_map_rev_lookup(dl
, bus_name
, dev_name
,
573 port_index
, &ifname
);
576 pr_out("%s", ifname
);
580 __pr_out_port_handle(bus_name
, dev_name
, port_index
);
583 static void pr_out_port_handle_nice(struct dl
*dl
, struct nlattr
**tb
)
585 const char *bus_name
;
586 const char *dev_name
;
589 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
590 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
591 port_index
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
593 __pr_out_port_handle_nice(dl
, bus_name
, dev_name
, port_index
);
596 static void pr_out_dev(struct nlattr
**tb
)
602 static int cmd_dev_show_cb(const struct nlmsghdr
*nlh
, void *data
)
604 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
605 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
607 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
608 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
614 static int cmd_dev_show(struct dl
*dl
)
616 struct nlmsghdr
*nlh
;
617 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
620 if (dl_argc(dl
) == 0)
623 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_GET
, flags
);
625 if (dl_argc(dl
) > 0) {
626 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, 0);
631 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_dev_show_cb
, NULL
);
634 static int cmd_dev(struct dl
*dl
)
636 if (dl_argv_match(dl
, "help")) {
639 } else if (dl_argv_match(dl
, "show") ||
640 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
642 return cmd_dev_show(dl
);
644 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
648 static void cmd_port_help(void)
650 pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n");
651 pr_out(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
652 pr_out(" devlink port split DEV/PORT_INDEX count COUNT\n");
653 pr_out(" devlink port unsplit DEV/PORT_INDEX\n");
656 static const char *port_type_name(uint32_t type
)
659 case DEVLINK_PORT_TYPE_NOTSET
: return "notset";
660 case DEVLINK_PORT_TYPE_AUTO
: return "auto";
661 case DEVLINK_PORT_TYPE_ETH
: return "eth";
662 case DEVLINK_PORT_TYPE_IB
: return "ib";
663 default: return "<unknown type>";
667 static void pr_out_port(struct nlattr
**tb
)
669 struct nlattr
*pt_attr
= tb
[DEVLINK_ATTR_PORT_TYPE
];
670 struct nlattr
*dpt_attr
= tb
[DEVLINK_ATTR_PORT_DESIRED_TYPE
];
672 pr_out_port_handle(tb
);
675 uint16_t port_type
= mnl_attr_get_u16(pt_attr
);
677 pr_out(" type %s", port_type_name(port_type
));
679 uint16_t des_port_type
= mnl_attr_get_u16(dpt_attr
);
681 if (port_type
!= des_port_type
)
682 pr_out("(%s)", port_type_name(des_port_type
));
685 if (tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
687 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]));
688 if (tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
])
690 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
]));
691 if (tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
])
692 pr_out(" split_group %u",
693 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
]));
697 static int cmd_port_show_cb(const struct nlmsghdr
*nlh
, void *data
)
699 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
700 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
702 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
703 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
704 !tb
[DEVLINK_ATTR_PORT_INDEX
])
710 static int cmd_port_show(struct dl
*dl
)
712 struct nlmsghdr
*nlh
;
713 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
716 if (dl_argc(dl
) == 0)
719 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
, flags
);
721 if (dl_argc(dl
) > 0) {
722 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
727 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_port_show_cb
, NULL
);
730 static int cmd_port_set(struct dl
*dl
)
732 struct nlmsghdr
*nlh
;
735 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SET
,
736 NLM_F_REQUEST
| NLM_F_ACK
);
738 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_TYPE
, 0);
742 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
745 static int cmd_port_split(struct dl
*dl
)
747 struct nlmsghdr
*nlh
;
750 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SPLIT
,
751 NLM_F_REQUEST
| NLM_F_ACK
);
753 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_COUNT
, 0);
757 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
760 static int cmd_port_unsplit(struct dl
*dl
)
762 struct nlmsghdr
*nlh
;
765 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_UNSPLIT
,
766 NLM_F_REQUEST
| NLM_F_ACK
);
768 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
772 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
775 static int cmd_port(struct dl
*dl
)
777 if (dl_argv_match(dl
, "help")) {
780 } else if (dl_argv_match(dl
, "show") ||
781 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
783 return cmd_port_show(dl
);
784 } else if (dl_argv_match(dl
, "set")) {
786 return cmd_port_set(dl
);
787 } else if (dl_argv_match(dl
, "split")) {
789 return cmd_port_split(dl
);
790 } else if (dl_argv_match(dl
, "unsplit")) {
792 return cmd_port_unsplit(dl
);
794 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
798 static const char *cmd_name(uint8_t cmd
)
801 case DEVLINK_CMD_UNSPEC
: return "unspec";
802 case DEVLINK_CMD_GET
: return "get";
803 case DEVLINK_CMD_SET
: return "set";
804 case DEVLINK_CMD_NEW
: return "new";
805 case DEVLINK_CMD_DEL
: return "del";
806 case DEVLINK_CMD_PORT_GET
: return "get";
807 case DEVLINK_CMD_PORT_SET
: return "set";
808 case DEVLINK_CMD_PORT_NEW
: return "net";
809 case DEVLINK_CMD_PORT_DEL
: return "del";
810 default: return "<unknown cmd>";
814 static const char *cmd_obj(uint8_t cmd
)
817 case DEVLINK_CMD_UNSPEC
: return "unspec";
818 case DEVLINK_CMD_GET
:
819 case DEVLINK_CMD_SET
:
820 case DEVLINK_CMD_NEW
:
821 case DEVLINK_CMD_DEL
:
823 case DEVLINK_CMD_PORT_GET
:
824 case DEVLINK_CMD_PORT_SET
:
825 case DEVLINK_CMD_PORT_NEW
:
826 case DEVLINK_CMD_PORT_DEL
:
828 default: return "<unknown obj>";
832 static void pr_out_mon_header(uint8_t cmd
)
834 pr_out("[%s,%s] ", cmd_obj(cmd
), cmd_name(cmd
));
837 static bool cmd_filter_check(struct dl
*dl
, uint8_t cmd
)
839 const char *obj
= cmd_obj(cmd
);
840 unsigned int index
= 0;
845 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
846 if (strcmp(cur_obj
, obj
) == 0 || strcmp(cur_obj
, "all") == 0)
852 static int cmd_mon_show_cb(const struct nlmsghdr
*nlh
, void *data
)
854 struct dl
*dl
= data
;
855 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
856 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
857 uint8_t cmd
= genl
->cmd
;
859 if (!cmd_filter_check(dl
, cmd
))
863 case DEVLINK_CMD_GET
: /* fall through */
864 case DEVLINK_CMD_SET
: /* fall through */
865 case DEVLINK_CMD_NEW
: /* fall through */
866 case DEVLINK_CMD_DEL
:
867 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
868 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
870 pr_out_mon_header(genl
->cmd
);
873 case DEVLINK_CMD_PORT_GET
: /* fall through */
874 case DEVLINK_CMD_PORT_SET
: /* fall through */
875 case DEVLINK_CMD_PORT_NEW
: /* fall through */
876 case DEVLINK_CMD_PORT_DEL
:
877 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
878 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
879 !tb
[DEVLINK_ATTR_PORT_INDEX
])
881 pr_out_mon_header(genl
->cmd
);
888 static int cmd_mon_show(struct dl
*dl
)
891 unsigned int index
= 0;
894 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
895 if (strcmp(cur_obj
, "all") != 0 &&
896 strcmp(cur_obj
, "dev") != 0 &&
897 strcmp(cur_obj
, "port") != 0) {
898 pr_err("Unknown object \"%s\"\n", cur_obj
);
902 err
= _mnlg_socket_group_add(dl
->nlg
, DEVLINK_GENL_MCGRP_CONFIG_NAME
);
905 err
= _mnlg_socket_recv_run(dl
->nlg
, cmd_mon_show_cb
, dl
);
911 static void cmd_mon_help(void)
913 pr_out("Usage: devlink monitor [ all | OBJECT-LIST ]\n"
914 "where OBJECT-LIST := { dev | port }\n");
917 static int cmd_mon(struct dl
*dl
)
919 if (dl_argv_match(dl
, "help")) {
922 } else if (dl_no_arg(dl
)) {
924 return cmd_mon_show(dl
);
926 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
930 static void help(void)
932 pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
933 "where OBJECT := { dev | port | monitor }\n"
934 " OPTIONS := { -V[ersion] | -n[no-nice-names] }\n");
937 static int dl_cmd(struct dl
*dl
)
939 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
942 } else if (dl_argv_match(dl
, "dev")) {
945 } else if (dl_argv_match(dl
, "port")) {
948 } else if (dl_argv_match(dl
, "monitor")) {
952 pr_err("Object \"%s\" not found\n", dl_argv(dl
));
956 static int dl_init(struct dl
*dl
, int argc
, char **argv
)
963 dl
->nlg
= mnlg_socket_open(DEVLINK_GENL_NAME
, DEVLINK_GENL_VERSION
);
965 pr_err("Failed to connect to devlink Netlink\n");
969 err
= ifname_map_init(dl
);
971 pr_err("Failed to create index map\n");
972 goto err_ifname_map_create
;
976 err_ifname_map_create
:
977 mnlg_socket_close(dl
->nlg
);
981 static void dl_fini(struct dl
*dl
)
984 mnlg_socket_close(dl
->nlg
);
987 static struct dl
*dl_alloc(void)
991 dl
= calloc(1, sizeof(*dl
));
997 static void dl_free(struct dl
*dl
)
1002 int main(int argc
, char **argv
)
1004 static const struct option long_options
[] = {
1005 { "Version", no_argument
, NULL
, 'V' },
1006 { "no-nice-names", no_argument
, NULL
, 'n' },
1007 { NULL
, 0, NULL
, 0 }
1016 pr_err("Failed to allocate memory for devlink\n");
1017 return EXIT_FAILURE
;
1020 while ((opt
= getopt_long(argc
, argv
, "Vn",
1021 long_options
, NULL
)) >= 0) {
1025 printf("devlink utility, iproute2-ss%s\n", SNAPSHOT
);
1026 return EXIT_SUCCESS
;
1028 dl
->no_nice_names
= true;
1031 pr_err("Unknown option.\n");
1033 return EXIT_FAILURE
;
1040 err
= dl_init(dl
, argc
, argv
);