Commit 524900a2 authored by David S. Miller's avatar David S. Miller

Merge branch 'netdevsim-add-devlink-health-reporters-support'

Jiri Pirko says:

====================
netdevsim: add devlink health reporters support

This patchset adds support for devlink health reporter interface
testing. First 2 patches are small dependencies of the last 2.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1635520a 9b88fc54
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
#include "bnxt_devlink.h" #include "bnxt_devlink.h"
static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter, static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg) struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack)
{ {
struct bnxt *bp = devlink_health_reporter_priv(reporter); struct bnxt *bp = devlink_health_reporter_priv(reporter);
struct bnxt_fw_health *health = bp->fw_health; struct bnxt_fw_health *health = bp->fw_health;
...@@ -66,7 +67,8 @@ static const struct devlink_health_reporter_ops bnxt_dl_fw_reporter_ops = { ...@@ -66,7 +67,8 @@ static const struct devlink_health_reporter_ops bnxt_dl_fw_reporter_ops = {
}; };
static int bnxt_fw_reset_recover(struct devlink_health_reporter *reporter, static int bnxt_fw_reset_recover(struct devlink_health_reporter *reporter,
void *priv_ctx) void *priv_ctx,
struct netlink_ext_ack *extack)
{ {
struct bnxt *bp = devlink_health_reporter_priv(reporter); struct bnxt *bp = devlink_health_reporter_priv(reporter);
...@@ -84,7 +86,8 @@ struct devlink_health_reporter_ops bnxt_dl_fw_reset_reporter_ops = { ...@@ -84,7 +86,8 @@ struct devlink_health_reporter_ops bnxt_dl_fw_reset_reporter_ops = {
}; };
static int bnxt_fw_fatal_recover(struct devlink_health_reporter *reporter, static int bnxt_fw_fatal_recover(struct devlink_health_reporter *reporter,
void *priv_ctx) void *priv_ctx,
struct netlink_ext_ack *extack)
{ {
struct bnxt *bp = devlink_health_reporter_priv(reporter); struct bnxt *bp = devlink_health_reporter_priv(reporter);
struct bnxt_fw_reporter_ctx *fw_reporter_ctx = priv_ctx; struct bnxt_fw_reporter_ctx *fw_reporter_ctx = priv_ctx;
......
...@@ -222,7 +222,8 @@ static int mlx5e_rx_reporter_recover_from_ctx(struct mlx5e_err_ctx *err_ctx) ...@@ -222,7 +222,8 @@ static int mlx5e_rx_reporter_recover_from_ctx(struct mlx5e_err_ctx *err_ctx)
} }
static int mlx5e_rx_reporter_recover(struct devlink_health_reporter *reporter, static int mlx5e_rx_reporter_recover(struct devlink_health_reporter *reporter,
void *context) void *context,
struct netlink_ext_ack *extack)
{ {
struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
struct mlx5e_err_ctx *err_ctx = context; struct mlx5e_err_ctx *err_ctx = context;
...@@ -301,7 +302,8 @@ static int mlx5e_rx_reporter_build_diagnose_output(struct mlx5e_rq *rq, ...@@ -301,7 +302,8 @@ static int mlx5e_rx_reporter_build_diagnose_output(struct mlx5e_rq *rq,
} }
static int mlx5e_rx_reporter_diagnose(struct devlink_health_reporter *reporter, static int mlx5e_rx_reporter_diagnose(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg) struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack)
{ {
struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
struct mlx5e_params *params = &priv->channels.params; struct mlx5e_params *params = &priv->channels.params;
......
...@@ -135,7 +135,8 @@ static int mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_err_ctx *err_ctx) ...@@ -135,7 +135,8 @@ static int mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_err_ctx *err_ctx)
} }
static int mlx5e_tx_reporter_recover(struct devlink_health_reporter *reporter, static int mlx5e_tx_reporter_recover(struct devlink_health_reporter *reporter,
void *context) void *context,
struct netlink_ext_ack *extack)
{ {
struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
struct mlx5e_err_ctx *err_ctx = context; struct mlx5e_err_ctx *err_ctx = context;
...@@ -205,7 +206,8 @@ mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg, ...@@ -205,7 +206,8 @@ mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg,
} }
static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter, static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg) struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack)
{ {
struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter);
struct mlx5e_txqsq *generic_sq = priv->txq2sq[0]; struct mlx5e_txqsq *generic_sq = priv->txq2sq[0];
......
...@@ -390,7 +390,8 @@ static void print_health_info(struct mlx5_core_dev *dev) ...@@ -390,7 +390,8 @@ static void print_health_info(struct mlx5_core_dev *dev)
static int static int
mlx5_fw_reporter_diagnose(struct devlink_health_reporter *reporter, mlx5_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg) struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack)
{ {
struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter); struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter);
struct mlx5_core_health *health = &dev->priv.health; struct mlx5_core_health *health = &dev->priv.health;
...@@ -491,7 +492,8 @@ mlx5_fw_reporter_heath_buffer_data_put(struct mlx5_core_dev *dev, ...@@ -491,7 +492,8 @@ mlx5_fw_reporter_heath_buffer_data_put(struct mlx5_core_dev *dev,
static int static int
mlx5_fw_reporter_dump(struct devlink_health_reporter *reporter, mlx5_fw_reporter_dump(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg, void *priv_ctx) struct devlink_fmsg *fmsg, void *priv_ctx,
struct netlink_ext_ack *extack)
{ {
struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter); struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter);
int err; int err;
...@@ -545,7 +547,8 @@ static const struct devlink_health_reporter_ops mlx5_fw_reporter_ops = { ...@@ -545,7 +547,8 @@ static const struct devlink_health_reporter_ops mlx5_fw_reporter_ops = {
static int static int
mlx5_fw_fatal_reporter_recover(struct devlink_health_reporter *reporter, mlx5_fw_fatal_reporter_recover(struct devlink_health_reporter *reporter,
void *priv_ctx) void *priv_ctx,
struct netlink_ext_ack *extack)
{ {
struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter); struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter);
...@@ -555,7 +558,8 @@ mlx5_fw_fatal_reporter_recover(struct devlink_health_reporter *reporter, ...@@ -555,7 +558,8 @@ mlx5_fw_fatal_reporter_recover(struct devlink_health_reporter *reporter,
#define MLX5_CR_DUMP_CHUNK_SIZE 256 #define MLX5_CR_DUMP_CHUNK_SIZE 256
static int static int
mlx5_fw_fatal_reporter_dump(struct devlink_health_reporter *reporter, mlx5_fw_fatal_reporter_dump(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg, void *priv_ctx) struct devlink_fmsg *fmsg, void *priv_ctx,
struct netlink_ext_ack *extack)
{ {
struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter); struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter);
u32 crdump_size = dev->priv.health.crdump_size; u32 crdump_size = dev->priv.health.crdump_size;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
obj-$(CONFIG_NETDEVSIM) += netdevsim.o obj-$(CONFIG_NETDEVSIM) += netdevsim.o
netdevsim-objs := \ netdevsim-objs := \
netdev.o dev.o fib.o bus.o netdev.o dev.o fib.o bus.o health.o
ifeq ($(CONFIG_BPF_SYSCALL),y) ifeq ($(CONFIG_BPF_SYSCALL),y)
netdevsim-objs += \ netdevsim-objs += \
......
...@@ -730,12 +730,18 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev, ...@@ -730,12 +730,18 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
if (err) if (err)
goto err_dummy_region_exit; goto err_dummy_region_exit;
err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count); err = nsim_dev_health_init(nsim_dev, devlink);
if (err) if (err)
goto err_traps_exit; goto err_traps_exit;
err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
if (err)
goto err_health_exit;
return 0; return 0;
err_health_exit:
nsim_dev_health_exit(nsim_dev);
err_traps_exit: err_traps_exit:
nsim_dev_traps_exit(devlink); nsim_dev_traps_exit(devlink);
err_dummy_region_exit: err_dummy_region_exit:
...@@ -797,10 +803,14 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) ...@@ -797,10 +803,14 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev)
if (err) if (err)
goto err_traps_exit; goto err_traps_exit;
err = nsim_bpf_dev_init(nsim_dev); err = nsim_dev_health_init(nsim_dev, devlink);
if (err) if (err)
goto err_debugfs_exit; goto err_debugfs_exit;
err = nsim_bpf_dev_init(nsim_dev);
if (err)
goto err_health_exit;
err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count); err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
if (err) if (err)
goto err_bpf_dev_exit; goto err_bpf_dev_exit;
...@@ -810,6 +820,8 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) ...@@ -810,6 +820,8 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev)
err_bpf_dev_exit: err_bpf_dev_exit:
nsim_bpf_dev_exit(nsim_dev); nsim_bpf_dev_exit(nsim_dev);
err_health_exit:
nsim_dev_health_exit(nsim_dev);
err_debugfs_exit: err_debugfs_exit:
nsim_dev_debugfs_exit(nsim_dev); nsim_dev_debugfs_exit(nsim_dev);
err_traps_exit: err_traps_exit:
...@@ -837,6 +849,7 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev) ...@@ -837,6 +849,7 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev)
if (devlink_is_reload_failed(devlink)) if (devlink_is_reload_failed(devlink))
return; return;
nsim_dev_port_del_all(nsim_dev); nsim_dev_port_del_all(nsim_dev);
nsim_dev_health_exit(nsim_dev);
nsim_dev_traps_exit(devlink); nsim_dev_traps_exit(devlink);
nsim_dev_dummy_region_exit(nsim_dev); nsim_dev_dummy_region_exit(nsim_dev);
mutex_destroy(&nsim_dev->port_list_lock); mutex_destroy(&nsim_dev->port_list_lock);
......
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 Mellanox Technologies. All rights reserved */
#include <linux/debugfs.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include "netdevsim.h"
static int
nsim_dev_empty_reporter_dump(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg, void *priv_ctx,
struct netlink_ext_ack *extack)
{
return 0;
}
static int
nsim_dev_empty_reporter_diagnose(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack)
{
return 0;
}
static const
struct devlink_health_reporter_ops nsim_dev_empty_reporter_ops = {
.name = "empty",
.dump = nsim_dev_empty_reporter_dump,
.diagnose = nsim_dev_empty_reporter_diagnose,
};
struct nsim_dev_dummy_reporter_ctx {
char *break_msg;
};
static int
nsim_dev_dummy_reporter_recover(struct devlink_health_reporter *reporter,
void *priv_ctx,
struct netlink_ext_ack *extack)
{
struct nsim_dev_health *health = devlink_health_reporter_priv(reporter);
struct nsim_dev_dummy_reporter_ctx *ctx = priv_ctx;
if (health->fail_recover) {
/* For testing purposes, user set debugfs fail_recover
* value to true. Fail right away.
*/
NL_SET_ERR_MSG_MOD(extack, "User setup the recover to fail for testing purposes");
return -EINVAL;
}
if (ctx) {
kfree(health->recovered_break_msg);
health->recovered_break_msg = kstrdup(ctx->break_msg,
GFP_KERNEL);
if (!health->recovered_break_msg)
return -ENOMEM;
}
return 0;
}
static int nsim_dev_dummy_fmsg_put(struct devlink_fmsg *fmsg, u32 binary_len)
{
char *binary;
int err;
int i;
err = devlink_fmsg_bool_pair_put(fmsg, "test_bool", true);
if (err)
return err;
err = devlink_fmsg_u8_pair_put(fmsg, "test_u8", 1);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "test_u32", 3);
if (err)
return err;
err = devlink_fmsg_u64_pair_put(fmsg, "test_u64", 4);
if (err)
return err;
err = devlink_fmsg_string_pair_put(fmsg, "test_string", "somestring");
if (err)
return err;
err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_binary");
if (err)
return err;
binary = kmalloc(binary_len, GFP_KERNEL);
if (!binary)
return -ENOMEM;
get_random_bytes(binary, binary_len);
err = devlink_fmsg_binary_put(fmsg, binary, binary_len);
kfree(binary);
if (err)
return err;
err = devlink_fmsg_arr_pair_nest_end(fmsg);
if (err)
return err;
err = devlink_fmsg_pair_nest_start(fmsg, "test_nest");
if (err)
return err;
err = devlink_fmsg_obj_nest_start(fmsg);
if (err)
return err;
err = devlink_fmsg_bool_pair_put(fmsg, "nested_test_bool", false);
if (err)
return err;
err = devlink_fmsg_u8_pair_put(fmsg, "nested_test_u8", false);
if (err)
return err;
err = devlink_fmsg_obj_nest_end(fmsg);
if (err)
return err;
err = devlink_fmsg_pair_nest_end(fmsg);
if (err)
return err;
err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_bool_array");
if (err)
return err;
for (i = 0; i < 10; i++) {
err = devlink_fmsg_bool_put(fmsg, true);
if (err)
return err;
}
err = devlink_fmsg_arr_pair_nest_end(fmsg);
if (err)
return err;
err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_u8_array");
if (err)
return err;
for (i = 0; i < 10; i++) {
err = devlink_fmsg_u8_put(fmsg, i);
if (err)
return err;
}
err = devlink_fmsg_arr_pair_nest_end(fmsg);
if (err)
return err;
err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_u32_array");
if (err)
return err;
for (i = 0; i < 10; i++) {
err = devlink_fmsg_u32_put(fmsg, i);
if (err)
return err;
}
err = devlink_fmsg_arr_pair_nest_end(fmsg);
if (err)
return err;
err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_u64_array");
if (err)
return err;
for (i = 0; i < 10; i++) {
err = devlink_fmsg_u64_put(fmsg, i);
if (err)
return err;
}
err = devlink_fmsg_arr_pair_nest_end(fmsg);
if (err)
return err;
err = devlink_fmsg_arr_pair_nest_start(fmsg, "test_array_of_objects");
if (err)
return err;
for (i = 0; i < 10; i++) {
err = devlink_fmsg_obj_nest_start(fmsg);
if (err)
return err;
err = devlink_fmsg_bool_pair_put(fmsg,
"in_array_nested_test_bool",
false);
if (err)
return err;
err = devlink_fmsg_u8_pair_put(fmsg,
"in_array_nested_test_u8",
i);
if (err)
return err;
err = devlink_fmsg_obj_nest_end(fmsg);
if (err)
return err;
}
return devlink_fmsg_arr_pair_nest_end(fmsg);
}
static int
nsim_dev_dummy_reporter_dump(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg, void *priv_ctx,
struct netlink_ext_ack *extack)
{
struct nsim_dev_health *health = devlink_health_reporter_priv(reporter);
struct nsim_dev_dummy_reporter_ctx *ctx = priv_ctx;
int err;
if (ctx) {
err = devlink_fmsg_string_pair_put(fmsg, "break_message",
ctx->break_msg);
if (err)
return err;
}
return nsim_dev_dummy_fmsg_put(fmsg, health->binary_len);
}
static int
nsim_dev_dummy_reporter_diagnose(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack)
{
struct nsim_dev_health *health = devlink_health_reporter_priv(reporter);
int err;
if (health->recovered_break_msg) {
err = devlink_fmsg_string_pair_put(fmsg,
"recovered_break_message",
health->recovered_break_msg);
if (err)
return err;
}
return nsim_dev_dummy_fmsg_put(fmsg, health->binary_len);
}
static const
struct devlink_health_reporter_ops nsim_dev_dummy_reporter_ops = {
.name = "dummy",
.recover = nsim_dev_dummy_reporter_recover,
.dump = nsim_dev_dummy_reporter_dump,
.diagnose = nsim_dev_dummy_reporter_diagnose,
};
static ssize_t nsim_dev_health_break_write(struct file *file,
const char __user *data,
size_t count, loff_t *ppos)
{
struct nsim_dev_health *health = file->private_data;
struct nsim_dev_dummy_reporter_ctx ctx;
char *break_msg;
int err;
break_msg = kmalloc(count + 1, GFP_KERNEL);
if (!break_msg)
return -ENOMEM;
if (copy_from_user(break_msg, data, count)) {
err = -EFAULT;
goto out;
}
break_msg[count] = '\0';
if (break_msg[count - 1] == '\n')
break_msg[count - 1] = '\0';
ctx.break_msg = break_msg;
err = devlink_health_report(health->dummy_reporter, break_msg, &ctx);
if (err)
goto out;
out:
kfree(break_msg);
return err ?: count;
}
static const struct file_operations nsim_dev_health_break_fops = {
.open = simple_open,
.write = nsim_dev_health_break_write,
.llseek = generic_file_llseek,
};
int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink)
{
struct nsim_dev_health *health = &nsim_dev->health;
int err;
health->empty_reporter =
devlink_health_reporter_create(devlink,
&nsim_dev_empty_reporter_ops,
0, false, health);
if (IS_ERR(health->empty_reporter))
return PTR_ERR(health->empty_reporter);
health->dummy_reporter =
devlink_health_reporter_create(devlink,
&nsim_dev_dummy_reporter_ops,
0, false, health);
if (IS_ERR(health->dummy_reporter)) {
err = PTR_ERR(health->dummy_reporter);
goto err_empty_reporter_destroy;
}
health->ddir = debugfs_create_dir("health", nsim_dev->ddir);
if (IS_ERR_OR_NULL(health->ddir)) {
err = PTR_ERR_OR_ZERO(health->ddir) ?: -EINVAL;
goto err_dummy_reporter_destroy;
}
health->recovered_break_msg = NULL;
debugfs_create_file("break_health", 0200, health->ddir, health,
&nsim_dev_health_break_fops);
health->binary_len = 16;
debugfs_create_u32("binary_len", 0600, health->ddir,
&health->binary_len);
health->fail_recover = false;
debugfs_create_bool("fail_recover", 0600, health->ddir,
&health->fail_recover);
return 0;
err_dummy_reporter_destroy:
devlink_health_reporter_destroy(health->dummy_reporter);
err_empty_reporter_destroy:
devlink_health_reporter_destroy(health->empty_reporter);
return err;
}
void nsim_dev_health_exit(struct nsim_dev *nsim_dev)
{
struct nsim_dev_health *health = &nsim_dev->health;
debugfs_remove_recursive(health->ddir);
kfree(health->recovered_break_msg);
devlink_health_reporter_destroy(health->dummy_reporter);
devlink_health_reporter_destroy(health->empty_reporter);
}
...@@ -134,6 +134,18 @@ enum nsim_resource_id { ...@@ -134,6 +134,18 @@ enum nsim_resource_id {
NSIM_RESOURCE_IPV6_FIB_RULES, NSIM_RESOURCE_IPV6_FIB_RULES,
}; };
struct nsim_dev_health {
struct devlink_health_reporter *empty_reporter;
struct devlink_health_reporter *dummy_reporter;
struct dentry *ddir;
char *recovered_break_msg;
u32 binary_len;
bool fail_recover;
};
int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink);
void nsim_dev_health_exit(struct nsim_dev *nsim_dev);
struct nsim_dev_port { struct nsim_dev_port {
struct list_head list; struct list_head list;
struct devlink_port devlink_port; struct devlink_port devlink_port;
...@@ -164,6 +176,7 @@ struct nsim_dev { ...@@ -164,6 +176,7 @@ struct nsim_dev {
bool dont_allow_reload; bool dont_allow_reload;
bool fail_reload; bool fail_reload;
struct devlink_region *dummy_region; struct devlink_region *dummy_region;
struct nsim_dev_health health;
}; };
static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev) static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev)
......
...@@ -507,11 +507,13 @@ enum devlink_health_reporter_state { ...@@ -507,11 +507,13 @@ enum devlink_health_reporter_state {
struct devlink_health_reporter_ops { struct devlink_health_reporter_ops {
char *name; char *name;
int (*recover)(struct devlink_health_reporter *reporter, int (*recover)(struct devlink_health_reporter *reporter,
void *priv_ctx); void *priv_ctx, struct netlink_ext_ack *extack);
int (*dump)(struct devlink_health_reporter *reporter, int (*dump)(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg, void *priv_ctx); struct devlink_fmsg *fmsg, void *priv_ctx,
struct netlink_ext_ack *extack);
int (*diagnose)(struct devlink_health_reporter *reporter, int (*diagnose)(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg); struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack);
}; };
/** /**
......
...@@ -4847,14 +4847,17 @@ EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update); ...@@ -4847,14 +4847,17 @@ EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
static int static int
devlink_health_reporter_recover(struct devlink_health_reporter *reporter, devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
void *priv_ctx) void *priv_ctx, struct netlink_ext_ack *extack)
{ {
int err; int err;
if (reporter->health_state == DEVLINK_HEALTH_REPORTER_STATE_HEALTHY)
return 0;
if (!reporter->ops->recover) if (!reporter->ops->recover)
return -EOPNOTSUPP; return -EOPNOTSUPP;
err = reporter->ops->recover(reporter, priv_ctx); err = reporter->ops->recover(reporter, priv_ctx, extack);
if (err) if (err)
return err; return err;
...@@ -4875,7 +4878,8 @@ devlink_health_dump_clear(struct devlink_health_reporter *reporter) ...@@ -4875,7 +4878,8 @@ devlink_health_dump_clear(struct devlink_health_reporter *reporter)
} }
static int devlink_health_do_dump(struct devlink_health_reporter *reporter, static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
void *priv_ctx) void *priv_ctx,
struct netlink_ext_ack *extack)
{ {
int err; int err;
...@@ -4896,7 +4900,7 @@ static int devlink_health_do_dump(struct devlink_health_reporter *reporter, ...@@ -4896,7 +4900,7 @@ static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
goto dump_err; goto dump_err;
err = reporter->ops->dump(reporter, reporter->dump_fmsg, err = reporter->ops->dump(reporter, reporter->dump_fmsg,
priv_ctx); priv_ctx, extack);
if (err) if (err)
goto dump_err; goto dump_err;
...@@ -4943,11 +4947,12 @@ int devlink_health_report(struct devlink_health_reporter *reporter, ...@@ -4943,11 +4947,12 @@ int devlink_health_report(struct devlink_health_reporter *reporter,
mutex_lock(&reporter->dump_lock); mutex_lock(&reporter->dump_lock);
/* store current dump of current error, for later analysis */ /* store current dump of current error, for later analysis */
devlink_health_do_dump(reporter, priv_ctx); devlink_health_do_dump(reporter, priv_ctx, NULL);
mutex_unlock(&reporter->dump_lock); mutex_unlock(&reporter->dump_lock);
if (reporter->auto_recover) if (reporter->auto_recover)
return devlink_health_reporter_recover(reporter, priv_ctx); return devlink_health_reporter_recover(reporter,
priv_ctx, NULL);
return 0; return 0;
} }
...@@ -5185,7 +5190,7 @@ static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb, ...@@ -5185,7 +5190,7 @@ static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
if (!reporter) if (!reporter)
return -EINVAL; return -EINVAL;
err = devlink_health_reporter_recover(reporter, NULL); err = devlink_health_reporter_recover(reporter, NULL, info->extack);
devlink_health_reporter_put(reporter); devlink_health_reporter_put(reporter);
return err; return err;
...@@ -5218,7 +5223,7 @@ static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb, ...@@ -5218,7 +5223,7 @@ static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
if (err) if (err)
goto out; goto out;
err = reporter->ops->diagnose(reporter, fmsg); err = reporter->ops->diagnose(reporter, fmsg, info->extack);
if (err) if (err)
goto out; goto out;
...@@ -5253,7 +5258,7 @@ devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb, ...@@ -5253,7 +5258,7 @@ devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
} }
mutex_lock(&reporter->dump_lock); mutex_lock(&reporter->dump_lock);
if (!start) { if (!start) {
err = devlink_health_do_dump(reporter, NULL); err = devlink_health_do_dump(reporter, NULL, cb->extack);
if (err) if (err)
goto unlock; goto unlock;
cb->args[1] = reporter->dump_ts; cb->args[1] = reporter->dump_ts;
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
lib_dir=$(dirname $0)/../../../net/forwarding lib_dir=$(dirname $0)/../../../net/forwarding
ALL_TESTS="fw_flash_test params_test regions_test reload_test \ ALL_TESTS="fw_flash_test params_test regions_test reload_test \
netns_reload_test resource_test dev_info_test" netns_reload_test resource_test dev_info_test \
empty_reporter_test dummy_reporter_test"
NUM_NETIFS=0 NUM_NETIFS=0
source $lib_dir/lib.sh source $lib_dir/lib.sh
...@@ -303,6 +304,130 @@ dev_info_test() ...@@ -303,6 +304,130 @@ dev_info_test()
log_test "dev_info test" log_test "dev_info test"
} }
empty_reporter_test()
{
RET=0
devlink health show $DL_HANDLE reporter empty >/dev/null
check_err $? "Failed show empty reporter"
devlink health dump show $DL_HANDLE reporter empty >/dev/null
check_err $? "Failed show dump of empty reporter"
devlink health diagnose $DL_HANDLE reporter empty >/dev/null
check_err $? "Failed diagnose empty reporter"
devlink health recover $DL_HANDLE reporter empty
check_err $? "Failed recover empty reporter"
log_test "empty reporter test"
}
check_reporter_info()
{
local name=$1
local expected_state=$2
local expected_error=$3
local expected_recover=$4
local expected_grace_period=$5
local expected_auto_recover=$6
local show=$(devlink health show $DL_HANDLE reporter $name -j | jq -e -r ".[][][]")
check_err $? "Failed show $name reporter"
local state=$(echo $show | jq -r ".state")
[ "$state" == "$expected_state" ]
check_err $? "Unexpected \"state\" value (got $state, expected $expected_state)"
local error=$(echo $show | jq -r ".error")
[ "$error" == "$expected_error" ]
check_err $? "Unexpected \"error\" value (got $error, expected $expected_error)"
local recover=`echo $show | jq -r ".recover"`
[ "$recover" == "$expected_recover" ]
check_err $? "Unexpected \"recover\" value (got $recover, expected $expected_recover)"
local grace_period=$(echo $show | jq -r ".grace_period")
check_err $? "Failed get $name reporter grace_period"
[ "$grace_period" == "$expected_grace_period" ]
check_err $? "Unexpected \"grace_period\" value (got $grace_period, expected $expected_grace_period)"
local auto_recover=$(echo $show | jq -r ".auto_recover")
[ "$auto_recover" == "$expected_auto_recover" ]
check_err $? "Unexpected \"auto_recover\" value (got $auto_recover, expected $expected_auto_recover)"
}
dummy_reporter_test()
{
RET=0
check_reporter_info dummy healthy 0 0 0 false
local BREAK_MSG="foo bar"
echo "$BREAK_MSG"> $DEBUGFS_DIR/health/break_health
check_err $? "Failed to break dummy reporter"
check_reporter_info dummy error 1 0 0 false
local dump=$(devlink health dump show $DL_HANDLE reporter dummy -j)
check_err $? "Failed show dump of dummy reporter"
local dump_break_msg=$(echo $dump | jq -r ".break_message")
[ "$dump_break_msg" == "$BREAK_MSG" ]
check_err $? "Unexpected dump break message value (got $dump_break_msg, expected $BREAK_MSG)"
devlink health dump clear $DL_HANDLE reporter dummy
check_err $? "Failed clear dump of dummy reporter"
devlink health recover $DL_HANDLE reporter dummy
check_err $? "Failed recover dummy reporter"
check_reporter_info dummy healthy 1 1 0 false
devlink health set $DL_HANDLE reporter dummy auto_recover true
check_err $? "Failed to dummy reporter auto_recover option"
check_reporter_info dummy healthy 1 1 0 true
echo "$BREAK_MSG"> $DEBUGFS_DIR/health/break_health
check_err $? "Failed to break dummy reporter"
check_reporter_info dummy healthy 2 2 0 true
local diagnose=$(devlink health diagnose $DL_HANDLE reporter dummy -j -p)
check_err $? "Failed show diagnose of dummy reporter"
local rcvrd_break_msg=$(echo $diagnose | jq -r ".recovered_break_message")
[ "$rcvrd_break_msg" == "$BREAK_MSG" ]
check_err $? "Unexpected recovered break message value (got $rcvrd_break_msg, expected $BREAK_MSG)"
devlink health set $DL_HANDLE reporter dummy grace_period 10
check_err $? "Failed to dummy reporter grace_period option"
check_reporter_info dummy healthy 2 2 10 true
echo "Y"> $DEBUGFS_DIR/health/fail_recover
check_err $? "Failed set dummy reporter recovery to fail"
echo "$BREAK_MSG"> $DEBUGFS_DIR/health/break_health
check_fail $? "Unexpected success of dummy reporter break"
check_reporter_info dummy error 3 2 10 true
devlink health recover $DL_HANDLE reporter dummy
check_fail $? "Unexpected success of dummy reporter recover"
echo "N"> $DEBUGFS_DIR/health/fail_recover
check_err $? "Failed set dummy reporter recovery to be successful"
devlink health recover $DL_HANDLE reporter dummy
check_err $? "Failed recover dummy reporter"
check_reporter_info dummy healthy 3 3 10 true
log_test "dummy reporter test"
}
setup_prepare() setup_prepare()
{ {
modprobe netdevsim modprobe netdevsim
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment