X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=devlink%2Fdevlink.c;h=0982faef7d88eef07e1d2ff79035a492d62d7662;hb=fbef655568ee931a82ad463a6f46f01ce3fb27aa;hp=9380792ad423bab3aae8443dda27df9f93c36ee1;hpb=a66af5569337b01a1aa11f929cf50ac04cae359e;p=mirror_iproute2.git diff --git a/devlink/devlink.c b/devlink/devlink.c index 9380792a..0982faef 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -19,18 +19,25 @@ #include #include #include +#include +#include +#include +#include #include #define _LINUX_SYSINFO_H /* avoid collision with musl header */ #include #include +#include #include #include +#include +#include #include -#include "SNAPSHOT.h" +#include "version.h" #include "list.h" #include "mnlg.h" -#include "json_writer.h" +#include "json_print.h" #include "utils.h" #include "namespace.h" @@ -41,6 +48,9 @@ #define ESWITCH_INLINE_MODE_NETWORK "network" #define ESWITCH_INLINE_MODE_TRANSPORT "transport" +#define ESWITCH_ENCAP_MODE_NONE "none" +#define ESWITCH_ENCAP_MODE_BASIC "basic" + #define PARAM_CMODE_RUNTIME_STR "runtime" #define PARAM_CMODE_DRIVERINIT_STR "driverinit" #define PARAM_CMODE_PERMANENT_STR "permanent" @@ -149,6 +159,30 @@ static int _mnlg_socket_recv_run(struct mnlg_socket *nlg, return 0; } +static void dummy_signal_handler(int signum) +{ +} + +static int _mnlg_socket_recv_run_intr(struct mnlg_socket *nlg, + mnl_cb_t data_cb, void *data) +{ + struct sigaction act, oact; + int err; + + act.sa_handler = dummy_signal_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_NODEFER; + + sigaction(SIGINT, &act, &oact); + err = mnlg_socket_recv_run(nlg, data_cb, data); + sigaction(SIGINT, &oact, NULL); + if (err < 0 && errno != EINTR) { + pr_err("devlink answers: %s\n", strerror(errno)); + return -errno; + } + return 0; +} + static int _mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh) { @@ -265,6 +299,7 @@ static void ifname_map_free(struct ifname_map *ifname_map) #define DL_OPT_TRAP_POLICER_ID BIT(34) #define DL_OPT_TRAP_POLICER_RATE BIT(35) #define DL_OPT_TRAP_POLICER_BURST BIT(36) +#define DL_OPT_HEALTH_REPORTER_AUTO_DUMP BIT(37) struct dl_opts { uint64_t present; /* flags of present items */ @@ -283,8 +318,8 @@ struct dl_opts { enum devlink_eswitch_mode eswitch_mode; enum devlink_eswitch_inline_mode eswitch_inline_mode; const char *dpipe_table_name; - bool dpipe_counters_enable; - bool eswitch_encap_mode; + bool dpipe_counters_enabled; + enum devlink_eswitch_encap_mode eswitch_encap_mode; const char *resource_path; uint64_t resource_size; uint32_t resource_id; @@ -301,6 +336,7 @@ struct dl_opts { const char *reporter_name; uint64_t reporter_graceful_period; bool reporter_auto_recover; + bool reporter_auto_dump; const char *trap_name; const char *trap_group_name; enum devlink_trap_action trap_action; @@ -318,7 +354,6 @@ struct dl { char **argv; bool no_nice_names; struct dl_opts opts; - json_writer_t *jw; bool json_output; bool pretty_output; bool verbose; @@ -739,9 +774,11 @@ static int strtobool(const char *str, bool *p_val) { bool val; - if (!strcmp(str, "true") || !strcmp(str, "1")) + if (!strcmp(str, "true") || !strcmp(str, "1") || + !strcmp(str, "enable")) val = true; - else if (!strcmp(str, "false") || !strcmp(str, "0")) + else if (!strcmp(str, "false") || !strcmp(str, "0") || + !strcmp(str, "disable")) val = false; else return -EINVAL; @@ -1076,26 +1113,19 @@ static int eswitch_inline_mode_get(const char *typestr, return 0; } -static int dpipe_counters_enable_get(const char *typestr, - bool *counters_enable) -{ - if (strcmp(typestr, "enable") == 0) { - *counters_enable = 1; - } else if (strcmp(typestr, "disable") == 0) { - *counters_enable = 0; - } else { - pr_err("Unknown counter_state \"%s\"\n", typestr); - return -EINVAL; - } - return 0; -} - -static int eswitch_encap_mode_get(const char *typestr, bool *p_mode) +static int +eswitch_encap_mode_get(const char *typestr, + enum devlink_eswitch_encap_mode *p_encap_mode) { - if (strcmp(typestr, "enable") == 0) { - *p_mode = true; - } else if (strcmp(typestr, "disable") == 0) { - *p_mode = false; + /* The initial implementation incorrectly accepted "enable"/"disable". + * Carry it to maintain backward compatibility. + */ + if (strcmp(typestr, "disable") == 0 || + strcmp(typestr, ESWITCH_ENCAP_MODE_NONE) == 0) { + *p_encap_mode = DEVLINK_ESWITCH_ENCAP_MODE_NONE; + } else if (strcmp(typestr, "enable") == 0 || + strcmp(typestr, ESWITCH_ENCAP_MODE_BASIC) == 0) { + *p_encap_mode = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; } else { pr_err("Unknown eswitch encap mode \"%s\"\n", typestr); return -EINVAL; @@ -1126,6 +1156,8 @@ static int trap_action_get(const char *actionstr, *p_action = DEVLINK_TRAP_ACTION_DROP; } else if (strcmp(actionstr, "trap") == 0) { *p_action = DEVLINK_TRAP_ACTION_TRAP; + } else if (strcmp(actionstr, "mirror") == 0) { + *p_action = DEVLINK_TRAP_ACTION_MIRROR; } else { pr_err("Unknown trap action \"%s\"\n", actionstr); return -EINVAL; @@ -1334,20 +1366,16 @@ static int dl_argv_parse(struct dl *dl, uint64_t o_required, if (err) return err; o_found |= DL_OPT_DPIPE_TABLE_NAME; - } else if (dl_argv_match(dl, "counters") && + } else if ((dl_argv_match(dl, "counters") || + dl_argv_match(dl, "counters_enabled")) && (o_all & DL_OPT_DPIPE_TABLE_COUNTERS)) { - const char *typestr; - dl_arg_inc(dl); - err = dl_argv_str(dl, &typestr); - if (err) - return err; - err = dpipe_counters_enable_get(typestr, - &opts->dpipe_counters_enable); + err = dl_argv_bool(dl, &opts->dpipe_counters_enabled); if (err) return err; o_found |= DL_OPT_DPIPE_TABLE_COUNTERS; - } else if (dl_argv_match(dl, "encap") && + } else if ((dl_argv_match(dl, "encap") || /* Original incorrect implementation */ + dl_argv_match(dl, "encap-mode")) && (o_all & DL_OPT_ESWITCH_ENCAP_MODE)) { const char *typestr; @@ -1457,6 +1485,13 @@ static int dl_argv_parse(struct dl *dl, uint64_t o_required, if (err) return err; o_found |= DL_OPT_HEALTH_REPORTER_AUTO_RECOVER; + } else if (dl_argv_match(dl, "auto_dump") && + (o_all & DL_OPT_HEALTH_REPORTER_AUTO_DUMP)) { + dl_arg_inc(dl); + err = dl_argv_bool(dl, &opts->reporter_auto_dump); + if (err) + return err; + o_found |= DL_OPT_HEALTH_REPORTER_AUTO_DUMP; } else if (dl_argv_match(dl, "trap") && (o_all & DL_OPT_TRAP_NAME)) { dl_arg_inc(dl); @@ -1507,6 +1542,11 @@ static int dl_argv_parse(struct dl *dl, uint64_t o_required, if (err) return err; o_found |= DL_OPT_TRAP_POLICER_ID; + } else if (dl_argv_match(dl, "nopolicer") && + (o_all & DL_OPT_TRAP_POLICER_ID)) { + dl_arg_inc(dl); + opts->trap_policer_id = 0; + o_found |= DL_OPT_TRAP_POLICER_ID; } else if (dl_argv_match(dl, "rate") && (o_all & DL_OPT_TRAP_POLICER_RATE)) { dl_arg_inc(dl); @@ -1593,7 +1633,7 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) opts->dpipe_table_name); if (opts->present & DL_OPT_DPIPE_TABLE_COUNTERS) mnl_attr_put_u8(nlh, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, - opts->dpipe_counters_enable); + opts->dpipe_counters_enabled); if (opts->present & DL_OPT_ESWITCH_ENCAP_MODE) mnl_attr_put_u8(nlh, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, opts->eswitch_encap_mode); @@ -1634,6 +1674,9 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) if (opts->present & DL_OPT_HEALTH_REPORTER_AUTO_RECOVER) mnl_attr_put_u8(nlh, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER, opts->reporter_auto_recover); + if (opts->present & DL_OPT_HEALTH_REPORTER_AUTO_DUMP) + mnl_attr_put_u8(nlh, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP, + opts->reporter_auto_dump); if (opts->present & DL_OPT_TRAP_NAME) mnl_attr_put_strz(nlh, DEVLINK_ATTR_TRAP_NAME, opts->trap_name); @@ -1713,7 +1756,7 @@ static void cmd_dev_help(void) pr_err("Usage: devlink dev show [ DEV ]\n"); pr_err(" devlink dev eswitch set DEV [ mode { legacy | switchdev } ]\n"); pr_err(" [ inline-mode { none | link | network | transport } ]\n"); - pr_err(" [ encap { disable | enable } ]\n"); + pr_err(" [ encap-mode { none | basic } ]\n"); pr_err(" devlink dev eswitch show DEV\n"); pr_err(" devlink dev param set DEV name PARAMETER value VALUE cmode { permanent | driverinit | runtime }\n"); pr_err(" devlink dev param show [DEV name PARAMETER]\n"); @@ -2143,6 +2186,18 @@ static const char *eswitch_inline_mode_name(uint32_t mode) } } +static const char *eswitch_encap_mode_name(uint32_t mode) +{ + switch (mode) { + case DEVLINK_ESWITCH_ENCAP_MODE_NONE: + return ESWITCH_ENCAP_MODE_NONE; + case DEVLINK_ESWITCH_ENCAP_MODE_BASIC: + return ESWITCH_ENCAP_MODE_BASIC; + default: + return ""; + } +} + static void pr_out_eswitch(struct dl *dl, struct nlattr **tb) { __pr_out_handle_start(dl, tb, true, false); @@ -2160,11 +2215,10 @@ static void pr_out_eswitch(struct dl *dl, struct nlattr **tb) tb[DEVLINK_ATTR_ESWITCH_INLINE_MODE]))); } if (tb[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) { - bool encap_mode = !!mnl_attr_get_u8(tb[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]); - check_indent_newline(dl); - print_string(PRINT_ANY, "encap", "encap %s", - encap_mode ? "enable" : "disable"); + print_string(PRINT_ANY, "encap-mode", "encap-mode %s", + eswitch_encap_mode_name(mnl_attr_get_u8( + tb[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]))); } pr_out_handle_end(dl); @@ -2304,6 +2358,11 @@ static const struct param_val_conv param_val_conv[] = { .vstr = "flash", .vuint = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH, }, + { + .name = "fw_load_policy", + .vstr = "disk", + .vuint = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK, + }, { .name = "reset_dev_on_drv_probe", .vstr = "unknown", @@ -2755,18 +2814,13 @@ static int cmd_dev_show(struct dl *dl) return err; } -static void cmd_dev_reload_help(void) -{ - pr_err("Usage: devlink dev reload DEV [ netns { PID | NAME | ID } ]\n"); -} - static int cmd_dev_reload(struct dl *dl) { struct nlmsghdr *nlh; int err; if (dl_argv_match(dl, "help") || dl_no_arg(dl)) { - cmd_dev_reload_help(); + cmd_dev_help(); return 0; } @@ -2888,11 +2942,6 @@ static int cmd_versions_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_OK; } -static void cmd_dev_info_help(void) -{ - pr_err("Usage: devlink dev info [ DEV ]\n"); -} - static int cmd_dev_info(struct dl *dl) { struct nlmsghdr *nlh; @@ -2900,7 +2949,7 @@ static int cmd_dev_info(struct dl *dl) int err; if (dl_argv_match(dl, "help")) { - cmd_dev_info_help(); + cmd_dev_help(); return 0; } @@ -2921,12 +2970,6 @@ static int cmd_dev_info(struct dl *dl) return err; } -static void cmd_dev_flash_help(void) -{ - pr_err("Usage: devlink dev flash DEV file PATH [ component NAME ]\n"); -} - - struct cmd_dev_flash_status_ctx { struct dl *dl; char *last_msg; @@ -3074,7 +3117,7 @@ static int cmd_dev_flash(struct dl *dl) int err; if (dl_argv_match(dl, "help") || dl_no_arg(dl)) { - cmd_dev_flash_help(); + cmd_dev_help(); return 0; } @@ -4243,7 +4286,21 @@ static const char *cmd_obj(uint8_t cmd) static void pr_out_mon_header(uint8_t cmd) { - pr_out("[%s,%s] ", cmd_obj(cmd), cmd_name(cmd)); + if (!is_json_context()) { + pr_out("[%s,%s] ", cmd_obj(cmd), cmd_name(cmd)); + } else { + open_json_object(NULL); + print_string(PRINT_JSON, "command", NULL, cmd_name(cmd)); + open_json_object(cmd_obj(cmd)); + } +} + +static void pr_out_mon_footer(void) +{ + if (is_json_context()) { + close_json_object(); + close_json_object(); + } } static bool cmd_filter_check(struct dl *dl, uint8_t cmd) @@ -4313,6 +4370,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_handle(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_PORT_GET: /* fall through */ case DEVLINK_CMD_PORT_SET: /* fall through */ @@ -4324,6 +4382,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_port(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_PARAM_GET: /* fall through */ case DEVLINK_CMD_PARAM_SET: /* fall through */ @@ -4335,6 +4394,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_param(dl, tb, false); + pr_out_mon_footer(); break; case DEVLINK_CMD_REGION_GET: /* fall through */ case DEVLINK_CMD_REGION_SET: /* fall through */ @@ -4346,6 +4406,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_region(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_FLASH_UPDATE: /* fall through */ case DEVLINK_CMD_FLASH_UPDATE_END: /* fall through */ @@ -4355,6 +4416,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_flash_update(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_HEALTH_REPORTER_RECOVER: mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); @@ -4363,6 +4425,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_health(dl, tb); + pr_out_mon_footer(); break; case DEVLINK_CMD_TRAP_GET: /* fall through */ case DEVLINK_CMD_TRAP_SET: /* fall through */ @@ -4379,6 +4442,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_trap(dl, tb, false); + pr_out_mon_footer(); break; case DEVLINK_CMD_TRAP_GROUP_GET: /* fall through */ case DEVLINK_CMD_TRAP_GROUP_SET: /* fall through */ @@ -4391,6 +4455,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); pr_out_trap_group(dl, tb, false); + pr_out_mon_footer(); break; case DEVLINK_CMD_TRAP_POLICER_GET: /* fall through */ case DEVLINK_CMD_TRAP_POLICER_SET: /* fall through */ @@ -4430,7 +4495,11 @@ static int cmd_mon_show(struct dl *dl) err = _mnlg_socket_group_add(dl->nlg, DEVLINK_GENL_MCGRP_CONFIG_NAME); if (err) return err; - err = _mnlg_socket_recv_run(dl->nlg, cmd_mon_show_cb, dl); + open_json_object(NULL); + open_json_array(PRINT_JSON, "mon"); + err = _mnlg_socket_recv_run_intr(dl->nlg, cmd_mon_show_cb, dl); + close_json_array(PRINT_JSON, NULL); + close_json_object(); if (err) return err; return 0; @@ -4966,15 +5035,19 @@ static int cmd_dpipe_headers_show(struct dl *dl) return err; } -static void cmd_dpipe_header_help(void) +static void cmd_dpipe_help(void) { - pr_err("Usage: devlink dpipe headers show DEV\n"); + pr_err("Usage: devlink dpipe table show DEV [ name TABLE_NAME ]\n"); + pr_err(" devlink dpipe table set DEV name TABLE_NAME\n"); + pr_err(" [ counters_enabled { true | false } ]\n"); + pr_err(" devlink dpipe table dump DEV name TABLE_NAME\n"); + pr_err(" devlink dpipe header show DEV\n"); } static int cmd_dpipe_header(struct dl *dl) { if (dl_argv_match(dl, "help") || dl_no_arg(dl)) { - cmd_dpipe_header_help(); + cmd_dpipe_help(); return 0; } else if (dl_argv_match(dl, "show")) { dl_arg_inc(dl); @@ -5790,16 +5863,10 @@ out: return err; } -static void cmd_dpipe_table_help(void) -{ - pr_err("Usage: devlink dpipe table [ OBJECT-LIST ]\n" - "where OBJECT-LIST := { show | set | dump }\n"); -} - static int cmd_dpipe_table(struct dl *dl) { if (dl_argv_match(dl, "help") || dl_no_arg(dl)) { - cmd_dpipe_table_help(); + cmd_dpipe_help(); return 0; } else if (dl_argv_match(dl, "show")) { dl_arg_inc(dl); @@ -5815,12 +5882,6 @@ static int cmd_dpipe_table(struct dl *dl) return -ENOENT; } -static void cmd_dpipe_help(void) -{ - pr_err("Usage: devlink dpipe [ OBJECT-LIST ]\n" - "where OBJECT-LIST := { header | table }\n"); -} - static int cmd_dpipe(struct dl *dl) { if (dl_argv_match(dl, "help") || dl_no_arg(dl)) { @@ -6429,10 +6490,47 @@ static int cmd_region_read(struct dl *dl) return err; } +static int cmd_region_snapshot_new_cb(const struct nlmsghdr *nlh, void *data) +{ + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; + struct dl *dl = data; + + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || + !tb[DEVLINK_ATTR_REGION_NAME] || + !tb[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) + return MNL_CB_ERROR; + + pr_out_region(dl, tb); + + return MNL_CB_OK; +} + +static int cmd_region_snapshot_new(struct dl *dl) +{ + struct nlmsghdr *nlh; + int err; + + nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_REGION_NEW, + NLM_F_REQUEST | NLM_F_ACK); + + err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION, + DL_OPT_REGION_SNAPSHOT_ID); + if (err) + return err; + + pr_out_section_start(dl, "regions"); + err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_region_snapshot_new_cb, dl); + pr_out_section_end(dl); + return err; +} + static void cmd_region_help(void) { pr_err("Usage: devlink region show [ DEV/REGION ]\n"); pr_err(" devlink region del DEV/REGION snapshot SNAPSHOT_ID\n"); + pr_err(" devlink region new DEV/REGION snapshot SNAPSHOT_ID\n"); pr_err(" devlink region dump DEV/REGION [ snapshot SNAPSHOT_ID ]\n"); pr_err(" devlink region read DEV/REGION [ snapshot SNAPSHOT_ID ] address ADDRESS length LENGTH\n"); } @@ -6456,6 +6554,9 @@ static int cmd_region(struct dl *dl) } else if (dl_argv_match(dl, "read")) { dl_arg_inc(dl); return cmd_region_read(dl); + } else if (dl_argv_match(dl, "new")) { + dl_arg_inc(dl); + return cmd_region_snapshot_new(dl); } pr_err("Command \"%s\" not found\n", dl_argv(dl)); return -ENOENT; @@ -6470,7 +6571,8 @@ static int cmd_health_set_params(struct dl *dl) NLM_F_REQUEST | NLM_F_ACK); err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_HEALTH_REPORTER_NAME, DL_OPT_HEALTH_REPORTER_GRACEFUL_PERIOD | - DL_OPT_HEALTH_REPORTER_AUTO_RECOVER); + DL_OPT_HEALTH_REPORTER_AUTO_RECOVER | + DL_OPT_HEALTH_REPORTER_AUTO_DUMP); if (err) return err; @@ -6884,6 +6986,9 @@ static void pr_out_health(struct dl *dl, struct nlattr **tb_health) if (tb[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]) print_bool(PRINT_ANY, "auto_recover", " auto_recover %s", mnl_attr_get_u8(tb[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])); + if (tb[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]) + print_bool(PRINT_ANY, "auto_dump", " auto_dump %s", + mnl_attr_get_u8(tb[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP])); __pr_out_indent_dec(); pr_out_handle_end(dl); @@ -6937,7 +7042,10 @@ static void cmd_health_help(void) pr_err(" devlink health diagnose DEV reporter REPORTER_NAME\n"); pr_err(" devlink health dump show DEV reporter REPORTER_NAME\n"); pr_err(" devlink health dump clear DEV reporter REPORTER_NAME\n"); - pr_err(" devlink health set DEV reporter REPORTER_NAME { grace_period | auto_recover } { msec | boolean }\n"); + pr_err(" devlink health set DEV reporter REPORTER_NAME\n"); + pr_err(" [ grace_period MSEC ]\n"); + pr_err(" [ auto_recover { true | false } ]\n"); + pr_err(" [ auto_dump { true | false } ]\n"); } static int cmd_health(struct dl *dl) @@ -6979,6 +7087,8 @@ static const char *trap_type_name(uint8_t type) return "drop"; case DEVLINK_TRAP_TYPE_EXCEPTION: return "exception"; + case DEVLINK_TRAP_TYPE_CONTROL: + return "control"; default: return ""; } @@ -6991,6 +7101,8 @@ static const char *trap_action_name(uint8_t action) return "drop"; case DEVLINK_TRAP_ACTION_TRAP: return "trap"; + case DEVLINK_TRAP_ACTION_MIRROR: + return "mirror"; default: return ""; } @@ -7065,9 +7177,10 @@ static int cmd_trap_show_cb(const struct nlmsghdr *nlh, void *data) static void cmd_trap_help(void) { - pr_err("Usage: devlink trap set DEV trap TRAP [ action { trap | drop } ]\n"); + pr_err("Usage: devlink trap set DEV trap TRAP [ action { trap | drop | mirror } ]\n"); pr_err(" devlink trap show [ DEV trap TRAP ]\n"); - pr_err(" devlink trap group set DEV group GROUP [ action { trap | drop } ]\n"); + pr_err(" devlink trap group set DEV group GROUP [ action { trap | drop | mirror } ]\n"); + pr_err(" [ policer POLICER ] [ nopolicer ]\n"); pr_err(" devlink trap group show [ DEV group GROUP ]\n"); pr_err(" devlink trap policer set DEV policer POLICER [ rate RATE ] [ burst BURST ]\n"); pr_err(" devlink trap policer show DEV policer POLICER\n"); @@ -7125,6 +7238,9 @@ static void pr_out_trap_group(struct dl *dl, struct nlattr **tb, bool array) print_string(PRINT_ANY, "name", "name %s", mnl_attr_get_str(tb[DEVLINK_ATTR_TRAP_GROUP_NAME])); print_bool(PRINT_ANY, "generic", " generic %s", !!tb[DEVLINK_ATTR_TRAP_GENERIC]); + if (tb[DEVLINK_ATTR_TRAP_POLICER_ID]) + print_uint(PRINT_ANY, "policer", " policer %u", + mnl_attr_get_u32(tb[DEVLINK_ATTR_TRAP_POLICER_ID])); pr_out_stats(dl, tb[DEVLINK_ATTR_STATS]); pr_out_handle_end(dl); } @@ -7181,7 +7297,7 @@ static int cmd_trap_group_set(struct dl *dl) err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_TRAP_GROUP_NAME, - DL_OPT_TRAP_ACTION); + DL_OPT_TRAP_ACTION | DL_OPT_TRAP_POLICER_ID); if (err) return err; @@ -7490,7 +7606,7 @@ int main(int argc, char **argv) switch (opt) { case 'V': - printf("devlink utility, iproute2-ss%s\n", SNAPSHOT); + printf("devlink utility, iproute2-%s\n", version); ret = EXIT_SUCCESS; goto dl_free; case 'f':