net: add support for netdev notifier error injection
This module allows to insert errors in some of netdevice's notifier events. All network drivers use these notifiers to signal various events and to check if they are allowed, e.g. PRECHANGEMTU and CHANGEMTU afterwards. Until recently I had to run failure tests by injecting a custom module, but now this infrastructure makes it trivial to test these failure paths. Some of the recent bugs I fixed were found using this module. Here's an example: $ cd /sys/kernel/debug/notifier-error-inject/netdev $ echo -22 > actions/NETDEV_CHANGEMTU/error $ ip link set eth0 mtu 1024 RTNETLINK answers: Invalid argument CC: Akinobu Mita <akinobu.mita@gmail.com> CC: "David S. Miller" <davem@davemloft.net> CC: netdev <netdev@vger.kernel.org> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
27a70af3f4
commit
02fff96a79
@@ -1484,6 +1484,29 @@ config OF_RECONFIG_NOTIFIER_ERROR_INJECT
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config NETDEV_NOTIFIER_ERROR_INJECT
|
||||
tristate "Netdev notifier error injection module"
|
||||
depends on NET && NOTIFIER_ERROR_INJECTION
|
||||
help
|
||||
This option provides the ability to inject artificial errors to
|
||||
netdevice notifier chain callbacks. It is controlled through debugfs
|
||||
interface /sys/kernel/debug/notifier-error-inject/netdev
|
||||
|
||||
If the notifier call chain should be failed with some events
|
||||
notified, write the error code to "actions/<notifier event>/error".
|
||||
|
||||
Example: Inject netdevice mtu change error (-22 = -EINVAL)
|
||||
|
||||
# cd /sys/kernel/debug/notifier-error-inject/netdev
|
||||
# echo -22 > actions/NETDEV_CHANGEMTU/error
|
||||
# ip link set eth0 mtu 1024
|
||||
RTNETLINK answers: Invalid argument
|
||||
|
||||
To compile this code as a module, choose M here: the module will
|
||||
be called netdev-notifier-error-inject.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config FAULT_INJECTION
|
||||
bool "Fault-injection framework"
|
||||
depends on DEBUG_KERNEL
|
||||
|
@@ -120,6 +120,7 @@ obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
|
||||
obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o
|
||||
obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o
|
||||
obj-$(CONFIG_PM_NOTIFIER_ERROR_INJECT) += pm-notifier-error-inject.o
|
||||
obj-$(CONFIG_NETDEV_NOTIFIER_ERROR_INJECT) += netdev-notifier-error-inject.o
|
||||
obj-$(CONFIG_MEMORY_NOTIFIER_ERROR_INJECT) += memory-notifier-error-inject.o
|
||||
obj-$(CONFIG_OF_RECONFIG_NOTIFIER_ERROR_INJECT) += \
|
||||
of-reconfig-notifier-error-inject.o
|
||||
|
54
lib/netdev-notifier-error-inject.c
Normal file
54
lib/netdev-notifier-error-inject.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "notifier-error-inject.h"
|
||||
|
||||
static int priority;
|
||||
module_param(priority, int, 0);
|
||||
MODULE_PARM_DESC(priority, "specify netdevice notifier priority");
|
||||
|
||||
static struct notifier_err_inject netdev_notifier_err_inject = {
|
||||
.actions = {
|
||||
{ NOTIFIER_ERR_INJECT_ACTION(NETDEV_REGISTER) },
|
||||
{ NOTIFIER_ERR_INJECT_ACTION(NETDEV_CHANGEMTU) },
|
||||
{ NOTIFIER_ERR_INJECT_ACTION(NETDEV_CHANGENAME) },
|
||||
{ NOTIFIER_ERR_INJECT_ACTION(NETDEV_PRE_UP) },
|
||||
{ NOTIFIER_ERR_INJECT_ACTION(NETDEV_PRE_TYPE_CHANGE) },
|
||||
{ NOTIFIER_ERR_INJECT_ACTION(NETDEV_POST_INIT) },
|
||||
{ NOTIFIER_ERR_INJECT_ACTION(NETDEV_PRECHANGEMTU) },
|
||||
{ NOTIFIER_ERR_INJECT_ACTION(NETDEV_PRECHANGEUPPER) },
|
||||
{}
|
||||
}
|
||||
};
|
||||
|
||||
static struct dentry *dir;
|
||||
|
||||
static int netdev_err_inject_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
dir = notifier_err_inject_init("netdev", notifier_err_inject_dir,
|
||||
&netdev_notifier_err_inject, priority);
|
||||
if (IS_ERR(dir))
|
||||
return PTR_ERR(dir);
|
||||
|
||||
err = register_netdevice_notifier(&netdev_notifier_err_inject.nb);
|
||||
if (err)
|
||||
debugfs_remove_recursive(dir);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void netdev_err_inject_exit(void)
|
||||
{
|
||||
unregister_netdevice_notifier(&netdev_notifier_err_inject.nb);
|
||||
debugfs_remove_recursive(dir);
|
||||
}
|
||||
|
||||
module_init(netdev_err_inject_init);
|
||||
module_exit(netdev_err_inject_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Netdevice notifier error injection module");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Nikolay Aleksandrov <razor@blackwall.org>");
|
Reference in New Issue
Block a user