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
;
119 static int dl_argc(struct dl
*dl
)
124 static char *dl_argv(struct dl
*dl
)
126 if (dl_argc(dl
) == 0)
131 static void dl_arg_inc(struct dl
*dl
)
133 if (dl_argc(dl
) == 0)
139 static char *dl_argv_next(struct dl
*dl
)
143 if (dl_argc(dl
) == 0)
151 static char *dl_argv_index(struct dl
*dl
, unsigned int index
)
153 if (index
>= dl_argc(dl
))
155 return dl
->argv
[index
];
158 static int strcmpx(const char *str1
, const char *str2
)
160 if (strlen(str1
) > strlen(str2
))
162 return strncmp(str1
, str2
, strlen(str1
));
165 static bool dl_argv_match(struct dl
*dl
, const char *pattern
)
167 if (dl_argc(dl
) == 0)
169 return strcmpx(dl_argv(dl
), pattern
) == 0;
172 static bool dl_no_arg(struct dl
*dl
)
174 return dl_argc(dl
) == 0;
177 static int attr_cb(const struct nlattr
*attr
, void *data
)
179 const struct nlattr
**tb
= data
;
182 type
= mnl_attr_get_type(attr
);
184 if (mnl_attr_type_valid(attr
, DEVLINK_ATTR_MAX
) < 0)
187 if (type
== DEVLINK_ATTR_BUS_NAME
&&
188 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
190 if (type
== DEVLINK_ATTR_DEV_NAME
&&
191 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
193 if (type
== DEVLINK_ATTR_PORT_INDEX
&&
194 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
196 if (type
== DEVLINK_ATTR_PORT_TYPE
&&
197 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
199 if (type
== DEVLINK_ATTR_PORT_DESIRED_TYPE
&&
200 mnl_attr_validate(attr
, MNL_TYPE_U16
) < 0)
202 if (type
== DEVLINK_ATTR_PORT_NETDEV_IFINDEX
&&
203 mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0)
205 if (type
== DEVLINK_ATTR_PORT_NETDEV_NAME
&&
206 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
208 if (type
== DEVLINK_ATTR_PORT_IBDEV_NAME
&&
209 mnl_attr_validate(attr
, MNL_TYPE_NUL_STRING
) < 0)
215 static int ifname_map_cb(const struct nlmsghdr
*nlh
, void *data
)
217 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
218 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
219 struct dl
*dl
= data
;
220 struct ifname_map
*ifname_map
;
221 const char *bus_name
;
222 const char *dev_name
;
223 uint32_t port_ifindex
;
224 const char *port_ifname
;
226 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
227 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
228 !tb
[DEVLINK_ATTR_PORT_INDEX
])
231 if (!tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
234 bus_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]);
235 dev_name
= mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]);
236 port_ifindex
= mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]);
237 port_ifname
= mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]);
238 ifname_map
= ifname_map_alloc(bus_name
, dev_name
,
239 port_ifindex
, port_ifname
);
242 list_add(&ifname_map
->list
, &dl
->ifname_map_list
);
247 static void ifname_map_fini(struct dl
*dl
)
249 struct ifname_map
*ifname_map
, *tmp
;
251 list_for_each_entry_safe(ifname_map
, tmp
,
252 &dl
->ifname_map_list
, list
) {
253 list_del(&ifname_map
->list
);
254 ifname_map_free(ifname_map
);
258 static int ifname_map_init(struct dl
*dl
)
260 struct nlmsghdr
*nlh
;
263 INIT_LIST_HEAD(&dl
->ifname_map_list
);
265 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
,
266 NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
);
268 err
= _mnlg_socket_sndrcv(dl
->nlg
, nlh
, ifname_map_cb
, dl
);
276 static int ifname_map_lookup(struct dl
*dl
, const char *ifname
,
277 char **p_bus_name
, char **p_dev_name
,
278 uint32_t *p_port_index
)
280 struct ifname_map
*ifname_map
;
282 list_for_each_entry(ifname_map
, &dl
->ifname_map_list
, list
) {
283 if (strcmp(ifname
, ifname_map
->ifname
) == 0) {
284 *p_bus_name
= ifname_map
->bus_name
;
285 *p_dev_name
= ifname_map
->dev_name
;
286 *p_port_index
= ifname_map
->port_index
;
293 static unsigned int strslashcount(char *str
)
295 unsigned int count
= 0;
298 while ((pos
= strchr(pos
, '/'))) {
305 static int strslashrsplit(char *str
, char **before
, char **after
)
309 slash
= strrchr(str
, '/');
318 static int strtouint32_t(const char *str
, uint32_t *p_val
)
321 unsigned long int val
;
323 val
= strtoul(str
, &endptr
, 10);
324 if (endptr
== str
|| *endptr
!= '\0')
332 static int dl_argv_put_handle(struct nlmsghdr
*nlh
, struct dl
*dl
)
334 char *str
= dl_argv_next(dl
);
335 char *bus_name
= bus_name
;
336 char *dev_name
= dev_name
;
339 pr_err("Devlink identification (\"bus_name/dev_name\") expected\n");
342 if (strslashcount(str
) != 1) {
343 pr_err("Wrong devlink identification string format.\n");
344 pr_err("Expected \"bus_name/dev_name\".\n");
348 strslashrsplit(str
, &bus_name
, &dev_name
);
349 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, bus_name
);
350 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, dev_name
);
354 static int dl_argv_put_handle_port(struct nlmsghdr
*nlh
, struct dl
*dl
)
356 char *str
= dl_argv_next(dl
);
357 unsigned int slash_count
;
358 char *bus_name
= bus_name
;
359 char *dev_name
= dev_name
;
360 uint32_t port_index
= port_index
;
364 pr_err("Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\") expected.\n");
367 slash_count
= strslashcount(str
);
368 if (slash_count
!= 2 && slash_count
!= 0) {
369 pr_err("Wrong port identification string format.\n");
370 pr_err("Expected \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
374 if (slash_count
== 2) {
375 char *handlestr
= handlestr
;
376 char *portstr
= portstr
;
378 err
= strslashrsplit(str
, &handlestr
, &portstr
);
379 err
= strtouint32_t(portstr
, &port_index
);
381 pr_err("Port index \"%s\" is not a number or not within range\n",
385 strslashrsplit(handlestr
, &bus_name
, &dev_name
);
386 } else if (slash_count
== 0) {
387 err
= ifname_map_lookup(dl
, str
, &bus_name
, &dev_name
,
390 pr_err("Netdevice \"%s\" not found\n", str
);
394 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_BUS_NAME
, bus_name
);
395 mnl_attr_put_strz(nlh
, DEVLINK_ATTR_DEV_NAME
, dev_name
);
396 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_INDEX
, port_index
);
400 static int dl_argv_uint32_t(struct dl
*dl
, uint32_t *p_val
)
402 char *str
= dl_argv_next(dl
);
406 pr_err("Unsigned number argument expected\n");
410 err
= strtouint32_t(str
, p_val
);
412 pr_err("\"%s\" is not a number or not within range\n", str
);
418 static int dl_argv_str(struct dl
*dl
, const char **p_str
)
420 const char *str
= dl_argv_next(dl
);
423 pr_err("String parameter expected\n");
430 static int port_type_get(const char *typestr
, enum devlink_port_type
*p_type
)
432 if (strcmp(typestr
, "auto") == 0) {
433 *p_type
= DEVLINK_PORT_TYPE_AUTO
;
434 } else if (strcmp(typestr
, "eth") == 0) {
435 *p_type
= DEVLINK_PORT_TYPE_ETH
;
436 } else if (strcmp(typestr
, "ib") == 0) {
437 *p_type
= DEVLINK_PORT_TYPE_IB
;
439 pr_err("Unknown port type \"%s\"\n", typestr
);
445 #define BIT(nr) (1UL << (nr))
446 #define DL_OPT_HANDLE BIT(0)
447 #define DL_OPT_HANDLEP BIT(1)
448 #define DL_OPT_PORT_TYPE BIT(2)
449 #define DL_OPT_PORT_COUNT BIT(3)
451 static int dl_argv_parse_put(struct nlmsghdr
*nlh
, struct dl
*dl
,
452 uint32_t o_required
, uint32_t o_optional
)
454 uint32_t o_all
= o_required
| o_optional
;
455 uint32_t o_found
= 0;
458 if (o_required
& DL_OPT_HANDLE
) {
459 err
= dl_argv_put_handle(nlh
, dl
);
462 } else if (o_required
& DL_OPT_HANDLEP
) {
463 err
= dl_argv_put_handle_port(nlh
, dl
);
468 while (dl_argc(dl
)) {
469 if (dl_argv_match(dl
, "type") &&
470 (o_all
& DL_OPT_PORT_TYPE
)) {
471 enum devlink_port_type port_type
;
475 err
= dl_argv_str(dl
, &typestr
);
478 err
= port_type_get(typestr
, &port_type
);
481 mnl_attr_put_u16(nlh
, DEVLINK_ATTR_PORT_TYPE
,
483 o_found
|= DL_OPT_PORT_TYPE
;
484 } else if (dl_argv_match(dl
, "count") &&
485 (o_all
& DL_OPT_PORT_COUNT
)) {
489 err
= dl_argv_uint32_t(dl
, &count
);
492 mnl_attr_put_u32(nlh
, DEVLINK_ATTR_PORT_SPLIT_COUNT
,
494 o_found
|= DL_OPT_PORT_COUNT
;
496 pr_err("Unknown option \"%s\"\n", dl_argv(dl
));
501 if ((o_required
& DL_OPT_PORT_TYPE
) && !(o_found
& DL_OPT_PORT_TYPE
)) {
502 pr_err("Port type option expected.\n");
506 if ((o_required
& DL_OPT_PORT_COUNT
) &&
507 !(o_found
& DL_OPT_PORT_COUNT
)) {
508 pr_err("Port split count option expected.\n");
515 static void cmd_dev_help(void)
517 pr_out("Usage: devlink dev show [ DEV ]\n");
520 static void pr_out_handle(struct nlattr
**tb
)
522 pr_out("%s/%s", mnl_attr_get_str(tb
[DEVLINK_ATTR_BUS_NAME
]),
523 mnl_attr_get_str(tb
[DEVLINK_ATTR_DEV_NAME
]));
526 static void pr_out_port_handle(struct nlattr
**tb
)
529 pr_out("/%d", mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]));
532 static void pr_out_dev(struct nlattr
**tb
)
538 static int cmd_dev_show_cb(const struct nlmsghdr
*nlh
, void *data
)
540 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
541 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
543 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
544 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
550 static int cmd_dev_show(struct dl
*dl
)
552 struct nlmsghdr
*nlh
;
553 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
556 if (dl_argc(dl
) == 0)
559 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_GET
, flags
);
561 if (dl_argc(dl
) > 0) {
562 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, 0);
567 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_dev_show_cb
, NULL
);
570 static int cmd_dev(struct dl
*dl
)
572 if (dl_argv_match(dl
, "help")) {
575 } else if (dl_argv_match(dl
, "show") ||
576 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
578 return cmd_dev_show(dl
);
580 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
584 static void cmd_port_help(void)
586 pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n");
587 pr_out(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
588 pr_out(" devlink port split DEV/PORT_INDEX count COUNT\n");
589 pr_out(" devlink port unsplit DEV/PORT_INDEX\n");
592 static const char *port_type_name(uint32_t type
)
595 case DEVLINK_PORT_TYPE_NOTSET
: return "notset";
596 case DEVLINK_PORT_TYPE_AUTO
: return "auto";
597 case DEVLINK_PORT_TYPE_ETH
: return "eth";
598 case DEVLINK_PORT_TYPE_IB
: return "ib";
599 default: return "<unknown type>";
603 static void pr_out_port(struct nlattr
**tb
)
605 struct nlattr
*pt_attr
= tb
[DEVLINK_ATTR_PORT_TYPE
];
606 struct nlattr
*dpt_attr
= tb
[DEVLINK_ATTR_PORT_DESIRED_TYPE
];
608 pr_out_port_handle(tb
);
611 uint16_t port_type
= mnl_attr_get_u16(pt_attr
);
613 pr_out(" type %s", port_type_name(port_type
));
615 uint16_t des_port_type
= mnl_attr_get_u16(dpt_attr
);
617 if (port_type
!= des_port_type
)
618 pr_out("(%s)", port_type_name(des_port_type
));
621 if (tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
623 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]));
624 if (tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
])
626 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
]));
627 if (tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
])
628 pr_out(" split_group %u",
629 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
]));
633 static int cmd_port_show_cb(const struct nlmsghdr
*nlh
, void *data
)
635 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
636 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
638 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
639 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
640 !tb
[DEVLINK_ATTR_PORT_INDEX
])
646 static int cmd_port_show(struct dl
*dl
)
648 struct nlmsghdr
*nlh
;
649 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
652 if (dl_argc(dl
) == 0)
655 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
, flags
);
657 if (dl_argc(dl
) > 0) {
658 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
663 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_port_show_cb
, NULL
);
666 static int cmd_port_set(struct dl
*dl
)
668 struct nlmsghdr
*nlh
;
671 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SET
,
672 NLM_F_REQUEST
| NLM_F_ACK
);
674 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_TYPE
, 0);
678 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
681 static int cmd_port_split(struct dl
*dl
)
683 struct nlmsghdr
*nlh
;
686 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SPLIT
,
687 NLM_F_REQUEST
| NLM_F_ACK
);
689 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_COUNT
, 0);
693 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
696 static int cmd_port_unsplit(struct dl
*dl
)
698 struct nlmsghdr
*nlh
;
701 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_UNSPLIT
,
702 NLM_F_REQUEST
| NLM_F_ACK
);
704 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
708 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
711 static int cmd_port(struct dl
*dl
)
713 if (dl_argv_match(dl
, "help")) {
716 } else if (dl_argv_match(dl
, "show") ||
717 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
719 return cmd_port_show(dl
);
720 } else if (dl_argv_match(dl
, "set")) {
722 return cmd_port_set(dl
);
723 } else if (dl_argv_match(dl
, "split")) {
725 return cmd_port_split(dl
);
726 } else if (dl_argv_match(dl
, "unsplit")) {
728 return cmd_port_unsplit(dl
);
730 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
734 static const char *cmd_name(uint8_t cmd
)
737 case DEVLINK_CMD_UNSPEC
: return "unspec";
738 case DEVLINK_CMD_GET
: return "get";
739 case DEVLINK_CMD_SET
: return "set";
740 case DEVLINK_CMD_NEW
: return "new";
741 case DEVLINK_CMD_DEL
: return "del";
742 case DEVLINK_CMD_PORT_GET
: return "get";
743 case DEVLINK_CMD_PORT_SET
: return "set";
744 case DEVLINK_CMD_PORT_NEW
: return "net";
745 case DEVLINK_CMD_PORT_DEL
: return "del";
746 default: return "<unknown cmd>";
750 static const char *cmd_obj(uint8_t cmd
)
753 case DEVLINK_CMD_UNSPEC
: return "unspec";
754 case DEVLINK_CMD_GET
:
755 case DEVLINK_CMD_SET
:
756 case DEVLINK_CMD_NEW
:
757 case DEVLINK_CMD_DEL
:
759 case DEVLINK_CMD_PORT_GET
:
760 case DEVLINK_CMD_PORT_SET
:
761 case DEVLINK_CMD_PORT_NEW
:
762 case DEVLINK_CMD_PORT_DEL
:
764 default: return "<unknown obj>";
768 static void pr_out_mon_header(uint8_t cmd
)
770 pr_out("[%s,%s] ", cmd_obj(cmd
), cmd_name(cmd
));
773 static bool cmd_filter_check(struct dl
*dl
, uint8_t cmd
)
775 const char *obj
= cmd_obj(cmd
);
776 unsigned int index
= 0;
781 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
782 if (strcmp(cur_obj
, obj
) == 0 || strcmp(cur_obj
, "all") == 0)
788 static int cmd_mon_show_cb(const struct nlmsghdr
*nlh
, void *data
)
790 struct dl
*dl
= data
;
791 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
792 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
793 uint8_t cmd
= genl
->cmd
;
795 if (!cmd_filter_check(dl
, cmd
))
799 case DEVLINK_CMD_GET
: /* fall through */
800 case DEVLINK_CMD_SET
: /* fall through */
801 case DEVLINK_CMD_NEW
: /* fall through */
802 case DEVLINK_CMD_DEL
:
803 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
804 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
806 pr_out_mon_header(genl
->cmd
);
809 case DEVLINK_CMD_PORT_GET
: /* fall through */
810 case DEVLINK_CMD_PORT_SET
: /* fall through */
811 case DEVLINK_CMD_PORT_NEW
: /* fall through */
812 case DEVLINK_CMD_PORT_DEL
:
813 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
814 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
815 !tb
[DEVLINK_ATTR_PORT_INDEX
])
817 pr_out_mon_header(genl
->cmd
);
824 static int cmd_mon_show(struct dl
*dl
)
827 unsigned int index
= 0;
830 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
831 if (strcmp(cur_obj
, "all") != 0 &&
832 strcmp(cur_obj
, "dev") != 0 &&
833 strcmp(cur_obj
, "port") != 0) {
834 pr_err("Unknown object \"%s\"\n", cur_obj
);
838 err
= _mnlg_socket_group_add(dl
->nlg
, DEVLINK_GENL_MCGRP_CONFIG_NAME
);
841 err
= _mnlg_socket_recv_run(dl
->nlg
, cmd_mon_show_cb
, dl
);
847 static void cmd_mon_help(void)
849 pr_out("Usage: devlink monitor [ all | OBJECT-LIST ]\n"
850 "where OBJECT-LIST := { dev | port }\n");
853 static int cmd_mon(struct dl
*dl
)
855 if (dl_argv_match(dl
, "help")) {
858 } else if (dl_no_arg(dl
)) {
860 return cmd_mon_show(dl
);
862 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
866 static void help(void)
868 pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
869 "where OBJECT := { dev | port | monitor }\n"
870 " OPTIONS := { -V[ersion] }\n");
873 static int dl_cmd(struct dl
*dl
)
875 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
878 } else if (dl_argv_match(dl
, "dev")) {
881 } else if (dl_argv_match(dl
, "port")) {
884 } else if (dl_argv_match(dl
, "monitor")) {
888 pr_err("Object \"%s\" not found\n", dl_argv(dl
));
892 static int dl_init(struct dl
*dl
, int argc
, char **argv
)
899 dl
->nlg
= mnlg_socket_open(DEVLINK_GENL_NAME
, DEVLINK_GENL_VERSION
);
901 pr_err("Failed to connect to devlink Netlink\n");
905 err
= ifname_map_init(dl
);
907 pr_err("Failed to create index map\n");
908 goto err_ifname_map_create
;
912 err_ifname_map_create
:
913 mnlg_socket_close(dl
->nlg
);
917 static void dl_fini(struct dl
*dl
)
920 mnlg_socket_close(dl
->nlg
);
923 static struct dl
*dl_alloc(void)
927 dl
= calloc(1, sizeof(*dl
));
933 static void dl_free(struct dl
*dl
)
938 int main(int argc
, char **argv
)
940 static const struct option long_options
[] = {
941 { "Version", no_argument
, NULL
, 'V' },
949 while ((opt
= getopt_long(argc
, argv
, "V",
950 long_options
, NULL
)) >= 0) {
954 printf("devlink utility, iproute2-ss%s\n", SNAPSHOT
);
957 pr_err("Unknown option.\n");
968 pr_err("Failed to allocate memory for devlink\n");
972 err
= dl_init(dl
, argc
, argv
);