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_dev(struct nlattr
**tb
)
532 static int cmd_dev_show_cb(const struct nlmsghdr
*nlh
, void *data
)
534 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
535 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
537 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
538 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
544 static int cmd_dev_show(struct dl
*dl
)
546 struct nlmsghdr
*nlh
;
547 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
550 if (dl_argc(dl
) == 0)
553 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_GET
, flags
);
555 if (dl_argc(dl
) > 0) {
556 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLE
, 0);
561 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_dev_show_cb
, NULL
);
564 static int cmd_dev(struct dl
*dl
)
566 if (dl_argv_match(dl
, "help")) {
569 } else if (dl_argv_match(dl
, "show") ||
570 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
572 return cmd_dev_show(dl
);
574 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
578 static void cmd_port_help(void)
580 pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n");
581 pr_out(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
582 pr_out(" devlink port split DEV/PORT_INDEX count COUNT\n");
583 pr_out(" devlink port unsplit DEV/PORT_INDEX\n");
586 static const char *port_type_name(uint32_t type
)
589 case DEVLINK_PORT_TYPE_NOTSET
: return "notset";
590 case DEVLINK_PORT_TYPE_AUTO
: return "auto";
591 case DEVLINK_PORT_TYPE_ETH
: return "eth";
592 case DEVLINK_PORT_TYPE_IB
: return "ib";
593 default: return "<unknown type>";
597 static void pr_out_port(struct nlattr
**tb
)
599 struct nlattr
*pt_attr
= tb
[DEVLINK_ATTR_PORT_TYPE
];
600 struct nlattr
*dpt_attr
= tb
[DEVLINK_ATTR_PORT_DESIRED_TYPE
];
603 pr_out("/%d:", mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_INDEX
]));
605 uint16_t port_type
= mnl_attr_get_u16(pt_attr
);
607 pr_out(" type %s", port_type_name(port_type
));
609 uint16_t des_port_type
= mnl_attr_get_u16(dpt_attr
);
611 if (port_type
!= des_port_type
)
612 pr_out("(%s)", port_type_name(des_port_type
));
615 if (tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
])
617 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_NETDEV_NAME
]));
618 if (tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
])
620 mnl_attr_get_str(tb
[DEVLINK_ATTR_PORT_IBDEV_NAME
]));
621 if (tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
])
622 pr_out(" split_group %u",
623 mnl_attr_get_u32(tb
[DEVLINK_ATTR_PORT_SPLIT_GROUP
]));
627 static int cmd_port_show_cb(const struct nlmsghdr
*nlh
, void *data
)
629 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
630 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
632 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
633 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
634 !tb
[DEVLINK_ATTR_PORT_INDEX
])
640 static int cmd_port_show(struct dl
*dl
)
642 struct nlmsghdr
*nlh
;
643 uint16_t flags
= NLM_F_REQUEST
| NLM_F_ACK
;
646 if (dl_argc(dl
) == 0)
649 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_GET
, flags
);
651 if (dl_argc(dl
) > 0) {
652 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
657 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, cmd_port_show_cb
, NULL
);
660 static int cmd_port_set(struct dl
*dl
)
662 struct nlmsghdr
*nlh
;
665 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SET
,
666 NLM_F_REQUEST
| NLM_F_ACK
);
668 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_TYPE
, 0);
672 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
675 static int cmd_port_split(struct dl
*dl
)
677 struct nlmsghdr
*nlh
;
680 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_SPLIT
,
681 NLM_F_REQUEST
| NLM_F_ACK
);
683 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
| DL_OPT_PORT_COUNT
, 0);
687 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
690 static int cmd_port_unsplit(struct dl
*dl
)
692 struct nlmsghdr
*nlh
;
695 nlh
= mnlg_msg_prepare(dl
->nlg
, DEVLINK_CMD_PORT_UNSPLIT
,
696 NLM_F_REQUEST
| NLM_F_ACK
);
698 err
= dl_argv_parse_put(nlh
, dl
, DL_OPT_HANDLEP
, 0);
702 return _mnlg_socket_sndrcv(dl
->nlg
, nlh
, NULL
, NULL
);
705 static int cmd_port(struct dl
*dl
)
707 if (dl_argv_match(dl
, "help")) {
710 } else if (dl_argv_match(dl
, "show") ||
711 dl_argv_match(dl
, "list") || dl_no_arg(dl
)) {
713 return cmd_port_show(dl
);
714 } else if (dl_argv_match(dl
, "set")) {
716 return cmd_port_set(dl
);
717 } else if (dl_argv_match(dl
, "split")) {
719 return cmd_port_split(dl
);
720 } else if (dl_argv_match(dl
, "unsplit")) {
722 return cmd_port_unsplit(dl
);
724 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
728 static const char *cmd_name(uint8_t cmd
)
731 case DEVLINK_CMD_UNSPEC
: return "unspec";
732 case DEVLINK_CMD_GET
: return "get";
733 case DEVLINK_CMD_SET
: return "set";
734 case DEVLINK_CMD_NEW
: return "new";
735 case DEVLINK_CMD_DEL
: return "del";
736 case DEVLINK_CMD_PORT_GET
: return "get";
737 case DEVLINK_CMD_PORT_SET
: return "set";
738 case DEVLINK_CMD_PORT_NEW
: return "net";
739 case DEVLINK_CMD_PORT_DEL
: return "del";
740 default: return "<unknown cmd>";
744 static const char *cmd_obj(uint8_t cmd
)
747 case DEVLINK_CMD_UNSPEC
: return "unspec";
748 case DEVLINK_CMD_GET
:
749 case DEVLINK_CMD_SET
:
750 case DEVLINK_CMD_NEW
:
751 case DEVLINK_CMD_DEL
:
753 case DEVLINK_CMD_PORT_GET
:
754 case DEVLINK_CMD_PORT_SET
:
755 case DEVLINK_CMD_PORT_NEW
:
756 case DEVLINK_CMD_PORT_DEL
:
758 default: return "<unknown obj>";
762 static void pr_out_mon_header(uint8_t cmd
)
764 pr_out("[%s,%s] ", cmd_obj(cmd
), cmd_name(cmd
));
767 static bool cmd_filter_check(struct dl
*dl
, uint8_t cmd
)
769 const char *obj
= cmd_obj(cmd
);
770 unsigned int index
= 0;
775 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
776 if (strcmp(cur_obj
, obj
) == 0 || strcmp(cur_obj
, "all") == 0)
782 static int cmd_mon_show_cb(const struct nlmsghdr
*nlh
, void *data
)
784 struct dl
*dl
= data
;
785 struct nlattr
*tb
[DEVLINK_ATTR_MAX
+ 1] = {};
786 struct genlmsghdr
*genl
= mnl_nlmsg_get_payload(nlh
);
787 uint8_t cmd
= genl
->cmd
;
789 if (!cmd_filter_check(dl
, cmd
))
793 case DEVLINK_CMD_GET
: /* fall through */
794 case DEVLINK_CMD_SET
: /* fall through */
795 case DEVLINK_CMD_NEW
: /* fall through */
796 case DEVLINK_CMD_DEL
:
797 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
798 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
])
800 pr_out_mon_header(genl
->cmd
);
803 case DEVLINK_CMD_PORT_GET
: /* fall through */
804 case DEVLINK_CMD_PORT_SET
: /* fall through */
805 case DEVLINK_CMD_PORT_NEW
: /* fall through */
806 case DEVLINK_CMD_PORT_DEL
:
807 mnl_attr_parse(nlh
, sizeof(*genl
), attr_cb
, tb
);
808 if (!tb
[DEVLINK_ATTR_BUS_NAME
] || !tb
[DEVLINK_ATTR_DEV_NAME
] ||
809 !tb
[DEVLINK_ATTR_PORT_INDEX
])
811 pr_out_mon_header(genl
->cmd
);
818 static int cmd_mon_show(struct dl
*dl
)
821 unsigned int index
= 0;
824 while ((cur_obj
= dl_argv_index(dl
, index
++))) {
825 if (strcmp(cur_obj
, "all") != 0 &&
826 strcmp(cur_obj
, "dev") != 0 &&
827 strcmp(cur_obj
, "port") != 0) {
828 pr_err("Unknown object \"%s\"\n", cur_obj
);
832 err
= _mnlg_socket_group_add(dl
->nlg
, DEVLINK_GENL_MCGRP_CONFIG_NAME
);
835 err
= _mnlg_socket_recv_run(dl
->nlg
, cmd_mon_show_cb
, dl
);
841 static void cmd_mon_help(void)
843 pr_out("Usage: devlink monitor [ all | OBJECT-LIST ]\n"
844 "where OBJECT-LIST := { dev | port }\n");
847 static int cmd_mon(struct dl
*dl
)
849 if (dl_argv_match(dl
, "help")) {
852 } else if (dl_no_arg(dl
)) {
854 return cmd_mon_show(dl
);
856 pr_err("Command \"%s\" not found\n", dl_argv(dl
));
860 static void help(void)
862 pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
863 "where OBJECT := { dev | port | monitor }\n"
864 " OPTIONS := { -V[ersion] }\n");
867 static int dl_cmd(struct dl
*dl
)
869 if (dl_argv_match(dl
, "help") || dl_no_arg(dl
)) {
872 } else if (dl_argv_match(dl
, "dev")) {
875 } else if (dl_argv_match(dl
, "port")) {
878 } else if (dl_argv_match(dl
, "monitor")) {
882 pr_err("Object \"%s\" not found\n", dl_argv(dl
));
886 static int dl_init(struct dl
*dl
, int argc
, char **argv
)
893 dl
->nlg
= mnlg_socket_open(DEVLINK_GENL_NAME
, DEVLINK_GENL_VERSION
);
895 pr_err("Failed to connect to devlink Netlink\n");
899 err
= ifname_map_init(dl
);
901 pr_err("Failed to create index map\n");
902 goto err_ifname_map_create
;
906 err_ifname_map_create
:
907 mnlg_socket_close(dl
->nlg
);
911 static void dl_fini(struct dl
*dl
)
914 mnlg_socket_close(dl
->nlg
);
917 static struct dl
*dl_alloc(void)
921 dl
= calloc(1, sizeof(*dl
));
927 static void dl_free(struct dl
*dl
)
932 int main(int argc
, char **argv
)
934 static const struct option long_options
[] = {
935 { "Version", no_argument
, NULL
, 'V' },
943 while ((opt
= getopt_long(argc
, argv
, "V",
944 long_options
, NULL
)) >= 0) {
948 printf("devlink utility, iproute2-ss%s\n", SNAPSHOT
);
951 pr_err("Unknown option.\n");
962 pr_err("Failed to allocate memory for devlink\n");
966 err
= dl_init(dl
, argc
, argv
);