diff --git a/devlink/devlink.c b/devlink/devlink.c index f16fc801..27cb4431 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -682,6 +682,15 @@ static const enum mnl_attr_data_type devlink_policy[DEVLINK_ATTR_MAX + 1] = { [DEVLINK_ATTR_TRAP_METADATA] = MNL_TYPE_NESTED, [DEVLINK_ATTR_TRAP_GROUP_NAME] = MNL_TYPE_STRING, [DEVLINK_ATTR_RELOAD_FAILED] = MNL_TYPE_U8, + [DEVLINK_ATTR_DEV_STATS] = MNL_TYPE_NESTED, + [DEVLINK_ATTR_RELOAD_STATS] = MNL_TYPE_NESTED, + [DEVLINK_ATTR_RELOAD_STATS_ENTRY] = MNL_TYPE_NESTED, + [DEVLINK_ATTR_RELOAD_ACTION] = MNL_TYPE_U8, + [DEVLINK_ATTR_RELOAD_STATS_LIMIT] = MNL_TYPE_U8, + [DEVLINK_ATTR_RELOAD_STATS_VALUE] = MNL_TYPE_U32, + [DEVLINK_ATTR_REMOTE_RELOAD_STATS] = MNL_TYPE_NESTED, + [DEVLINK_ATTR_RELOAD_ACTION_INFO] = MNL_TYPE_NESTED, + [DEVLINK_ATTR_RELOAD_ACTION_STATS] = MNL_TYPE_NESTED, [DEVLINK_ATTR_TRAP_POLICER_ID] = MNL_TYPE_U32, [DEVLINK_ATTR_TRAP_POLICER_RATE] = MNL_TYPE_U64, [DEVLINK_ATTR_TRAP_POLICER_BURST] = MNL_TYPE_U64, @@ -2371,6 +2380,18 @@ static const char *reload_action_name(uint8_t reload_action) } } +static const char *reload_limit_name(uint8_t reload_limit) +{ + switch (reload_limit) { + case DEVLINK_RELOAD_LIMIT_UNSPEC: + return "unspecified"; + case DEVLINK_RELOAD_LIMIT_NO_RESET: + return "no_reset"; + default: + return ""; + } +} + static const char *eswitch_mode_name(uint32_t mode) { switch (mode) { @@ -2976,17 +2997,101 @@ static int cmd_dev_param(struct dl *dl) return -ENOENT; } -static void pr_out_dev(struct dl *dl, struct nlattr **tb) +static void pr_out_action_stats(struct dl *dl, struct nlattr *action_stats) { + struct nlattr *tb_stats_entry[DEVLINK_ATTR_MAX + 1] = {}; + struct nlattr *nla_reload_stats_entry, *nla_limit, *nla_value; + enum devlink_reload_limit limit; + uint32_t value; + int err; + + mnl_attr_for_each_nested(nla_reload_stats_entry, action_stats) { + err = mnl_attr_parse_nested(nla_reload_stats_entry, attr_cb, + tb_stats_entry); + if (err != MNL_CB_OK) + return; + + nla_limit = tb_stats_entry[DEVLINK_ATTR_RELOAD_STATS_LIMIT]; + nla_value = tb_stats_entry[DEVLINK_ATTR_RELOAD_STATS_VALUE]; + if (!nla_limit || !nla_value) + return; + + check_indent_newline(dl); + limit = mnl_attr_get_u8(nla_limit); + value = mnl_attr_get_u32(nla_value); + print_uint_name_value(reload_limit_name(limit), value); + } +} + +static void pr_out_reload_stats(struct dl *dl, struct nlattr *reload_stats) +{ + struct nlattr *nla_action_info, *nla_action, *nla_action_stats; + struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; + enum devlink_reload_action action; + int err; + + mnl_attr_for_each_nested(nla_action_info, reload_stats) { + err = mnl_attr_parse_nested(nla_action_info, attr_cb, tb); + if (err != MNL_CB_OK) + return; + nla_action = tb[DEVLINK_ATTR_RELOAD_ACTION]; + nla_action_stats = tb[DEVLINK_ATTR_RELOAD_ACTION_STATS]; + if (!nla_action || !nla_action_stats) + return; + + action = mnl_attr_get_u8(nla_action); + pr_out_object_start(dl, reload_action_name(action)); + pr_out_action_stats(dl, nla_action_stats); + pr_out_object_end(dl); + } +} + +static void pr_out_reload_data(struct dl *dl, struct nlattr **tb) +{ + struct nlattr *nla_reload_stats, *nla_remote_reload_stats; + struct nlattr *tb_stats[DEVLINK_ATTR_MAX + 1] = {}; uint8_t reload_failed = 0; + int err; if (tb[DEVLINK_ATTR_RELOAD_FAILED]) reload_failed = mnl_attr_get_u8(tb[DEVLINK_ATTR_RELOAD_FAILED]); if (reload_failed) { - __pr_out_handle_start(dl, tb, true, false); check_indent_newline(dl); print_bool(PRINT_ANY, "reload_failed", "reload_failed %s", true); + } + if (!tb[DEVLINK_ATTR_DEV_STATS] || !dl->stats) + return; + err = mnl_attr_parse_nested(tb[DEVLINK_ATTR_DEV_STATS], attr_cb, + tb_stats); + if (err != MNL_CB_OK) + return; + + pr_out_object_start(dl, "stats"); + + nla_reload_stats = tb_stats[DEVLINK_ATTR_RELOAD_STATS]; + if (nla_reload_stats) { + pr_out_object_start(dl, "reload"); + pr_out_reload_stats(dl, nla_reload_stats); + pr_out_object_end(dl); + } + nla_remote_reload_stats = tb_stats[DEVLINK_ATTR_REMOTE_RELOAD_STATS]; + if (nla_remote_reload_stats) { + pr_out_object_start(dl, "remote_reload"); + pr_out_reload_stats(dl, nla_remote_reload_stats); + pr_out_object_end(dl); + } + + pr_out_object_end(dl); +} + + +static void pr_out_dev(struct dl *dl, struct nlattr **tb) +{ + if ((tb[DEVLINK_ATTR_RELOAD_FAILED] && mnl_attr_get_u8(tb[DEVLINK_ATTR_RELOAD_FAILED])) || + (tb[DEVLINK_ATTR_DEV_STATS] && dl->stats)) { + __pr_out_handle_start(dl, tb, true, false); + pr_out_reload_data(dl, tb); pr_out_handle_end(dl); } else { pr_out_handle(dl, tb); @@ -4849,6 +4954,7 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME]) return MNL_CB_ERROR; pr_out_mon_header(genl->cmd); + dl->stats = true; pr_out_dev(dl, tb); pr_out_mon_footer(); break;