diff options
Diffstat (limited to 'net/core/rtnl_net_debug.c')
| -rw-r--r-- | net/core/rtnl_net_debug.c | 131 | 
1 files changed, 131 insertions, 0 deletions
diff --git a/net/core/rtnl_net_debug.c b/net/core/rtnl_net_debug.c new file mode 100644 index 000000000000..e90a32242e22 --- /dev/null +++ b/net/core/rtnl_net_debug.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Copyright Amazon.com Inc. or its affiliates. */ + +#include <linux/init.h> +#include <linux/netdevice.h> +#include <linux/notifier.h> +#include <linux/rtnetlink.h> +#include <net/net_namespace.h> +#include <net/netns/generic.h> + +static int rtnl_net_debug_event(struct notifier_block *nb, +				unsigned long event, void *ptr) +{ +	struct net_device *dev = netdev_notifier_info_to_dev(ptr); +	struct net *net = dev_net(dev); +	enum netdev_cmd cmd = event; + +	/* Keep enum and don't add default to trigger -Werror=switch */ +	switch (cmd) { +	case NETDEV_UP: +	case NETDEV_DOWN: +	case NETDEV_REBOOT: +	case NETDEV_CHANGE: +	case NETDEV_REGISTER: +	case NETDEV_UNREGISTER: +	case NETDEV_CHANGEMTU: +	case NETDEV_CHANGEADDR: +	case NETDEV_PRE_CHANGEADDR: +	case NETDEV_GOING_DOWN: +	case NETDEV_CHANGENAME: +	case NETDEV_FEAT_CHANGE: +	case NETDEV_BONDING_FAILOVER: +	case NETDEV_PRE_UP: +	case NETDEV_PRE_TYPE_CHANGE: +	case NETDEV_POST_TYPE_CHANGE: +	case NETDEV_POST_INIT: +	case NETDEV_PRE_UNINIT: +	case NETDEV_RELEASE: +	case NETDEV_NOTIFY_PEERS: +	case NETDEV_JOIN: +	case NETDEV_CHANGEUPPER: +	case NETDEV_RESEND_IGMP: +	case NETDEV_PRECHANGEMTU: +	case NETDEV_CHANGEINFODATA: +	case NETDEV_BONDING_INFO: +	case NETDEV_PRECHANGEUPPER: +	case NETDEV_CHANGELOWERSTATE: +	case NETDEV_UDP_TUNNEL_PUSH_INFO: +	case NETDEV_UDP_TUNNEL_DROP_INFO: +	case NETDEV_CHANGE_TX_QUEUE_LEN: +	case NETDEV_CVLAN_FILTER_PUSH_INFO: +	case NETDEV_CVLAN_FILTER_DROP_INFO: +	case NETDEV_SVLAN_FILTER_PUSH_INFO: +	case NETDEV_SVLAN_FILTER_DROP_INFO: +	case NETDEV_OFFLOAD_XSTATS_ENABLE: +	case NETDEV_OFFLOAD_XSTATS_DISABLE: +	case NETDEV_OFFLOAD_XSTATS_REPORT_USED: +	case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA: +	case NETDEV_XDP_FEAT_CHANGE: +		ASSERT_RTNL(); +		break; + +	/* Once an event fully supports RTNL_NET, move it here +	 * and remove "if (0)" below. +	 * +	 * case NETDEV_XXX: +	 *	ASSERT_RTNL_NET(net); +	 *	break; +	 */ +	} + +	/* Just to avoid unused-variable error for dev and net. */ +	if (0) +		ASSERT_RTNL_NET(net); + +	return NOTIFY_DONE; +} + +static int rtnl_net_debug_net_id; + +static int __net_init rtnl_net_debug_net_init(struct net *net) +{ +	struct notifier_block *nb; + +	nb = net_generic(net, rtnl_net_debug_net_id); +	nb->notifier_call = rtnl_net_debug_event; + +	return register_netdevice_notifier_net(net, nb); +} + +static void __net_exit rtnl_net_debug_net_exit(struct net *net) +{ +	struct notifier_block *nb; + +	nb = net_generic(net, rtnl_net_debug_net_id); +	unregister_netdevice_notifier_net(net, nb); +} + +static struct pernet_operations rtnl_net_debug_net_ops __net_initdata = { +	.init = rtnl_net_debug_net_init, +	.exit = rtnl_net_debug_net_exit, +	.id = &rtnl_net_debug_net_id, +	.size = sizeof(struct notifier_block), +}; + +static struct notifier_block rtnl_net_debug_block = { +	.notifier_call = rtnl_net_debug_event, +}; + +static int __init rtnl_net_debug_init(void) +{ +	int ret; + +	ret = register_pernet_device(&rtnl_net_debug_net_ops); +	if (ret) +		return ret; + +	ret = register_netdevice_notifier(&rtnl_net_debug_block); +	if (ret) +		unregister_pernet_subsys(&rtnl_net_debug_net_ops); + +	return ret; +} + +static void __exit rtnl_net_debug_exit(void) +{ +	unregister_netdevice_notifier(&rtnl_net_debug_block); +	unregister_pernet_device(&rtnl_net_debug_net_ops); +} + +subsys_initcall(rtnl_net_debug_init);  | 
