xref: /linux/net/core/rtnl_net_debug.c (revision 13d68a16430312fc21990f48326366eb73891202)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright Amazon.com Inc. or its affiliates. */
3 
4 #include <linux/init.h>
5 #include <linux/netdevice.h>
6 #include <linux/notifier.h>
7 #include <linux/rtnetlink.h>
8 #include <net/net_namespace.h>
9 #include <net/netns/generic.h>
10 
11 static int rtnl_net_debug_event(struct notifier_block *nb,
12 				unsigned long event, void *ptr)
13 {
14 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
15 	struct net *net = dev_net(dev);
16 	enum netdev_cmd cmd = event;
17 
18 	/* Keep enum and don't add default to trigger -Werror=switch */
19 	switch (cmd) {
20 	case NETDEV_UP:
21 	case NETDEV_DOWN:
22 	case NETDEV_REBOOT:
23 	case NETDEV_CHANGE:
24 	case NETDEV_REGISTER:
25 	case NETDEV_UNREGISTER:
26 	case NETDEV_CHANGEMTU:
27 	case NETDEV_CHANGEADDR:
28 	case NETDEV_PRE_CHANGEADDR:
29 	case NETDEV_GOING_DOWN:
30 	case NETDEV_CHANGENAME:
31 	case NETDEV_FEAT_CHANGE:
32 	case NETDEV_BONDING_FAILOVER:
33 	case NETDEV_PRE_UP:
34 	case NETDEV_PRE_TYPE_CHANGE:
35 	case NETDEV_POST_TYPE_CHANGE:
36 	case NETDEV_POST_INIT:
37 	case NETDEV_PRE_UNINIT:
38 	case NETDEV_RELEASE:
39 	case NETDEV_NOTIFY_PEERS:
40 	case NETDEV_JOIN:
41 	case NETDEV_CHANGEUPPER:
42 	case NETDEV_RESEND_IGMP:
43 	case NETDEV_PRECHANGEMTU:
44 	case NETDEV_CHANGEINFODATA:
45 	case NETDEV_BONDING_INFO:
46 	case NETDEV_PRECHANGEUPPER:
47 	case NETDEV_CHANGELOWERSTATE:
48 	case NETDEV_UDP_TUNNEL_PUSH_INFO:
49 	case NETDEV_UDP_TUNNEL_DROP_INFO:
50 	case NETDEV_CHANGE_TX_QUEUE_LEN:
51 	case NETDEV_CVLAN_FILTER_PUSH_INFO:
52 	case NETDEV_CVLAN_FILTER_DROP_INFO:
53 	case NETDEV_SVLAN_FILTER_PUSH_INFO:
54 	case NETDEV_SVLAN_FILTER_DROP_INFO:
55 	case NETDEV_OFFLOAD_XSTATS_ENABLE:
56 	case NETDEV_OFFLOAD_XSTATS_DISABLE:
57 	case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
58 	case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
59 	case NETDEV_XDP_FEAT_CHANGE:
60 		ASSERT_RTNL();
61 		break;
62 
63 	/* Once an event fully supports RTNL_NET, move it here
64 	 * and remove "if (0)" below.
65 	 *
66 	 * case NETDEV_XXX:
67 	 *	ASSERT_RTNL_NET(net);
68 	 *	break;
69 	 */
70 	}
71 
72 	/* Just to avoid unused-variable error for dev and net. */
73 	if (0)
74 		ASSERT_RTNL_NET(net);
75 
76 	return NOTIFY_DONE;
77 }
78 
79 static int rtnl_net_debug_net_id;
80 
81 static int __net_init rtnl_net_debug_net_init(struct net *net)
82 {
83 	struct notifier_block *nb;
84 
85 	nb = net_generic(net, rtnl_net_debug_net_id);
86 	nb->notifier_call = rtnl_net_debug_event;
87 
88 	return register_netdevice_notifier_net(net, nb);
89 }
90 
91 static void __net_exit rtnl_net_debug_net_exit(struct net *net)
92 {
93 	struct notifier_block *nb;
94 
95 	nb = net_generic(net, rtnl_net_debug_net_id);
96 	unregister_netdevice_notifier_net(net, nb);
97 }
98 
99 static struct pernet_operations rtnl_net_debug_net_ops __net_initdata = {
100 	.init = rtnl_net_debug_net_init,
101 	.exit = rtnl_net_debug_net_exit,
102 	.id = &rtnl_net_debug_net_id,
103 	.size = sizeof(struct notifier_block),
104 };
105 
106 static struct notifier_block rtnl_net_debug_block = {
107 	.notifier_call = rtnl_net_debug_event,
108 };
109 
110 static int __init rtnl_net_debug_init(void)
111 {
112 	int ret;
113 
114 	ret = register_pernet_device(&rtnl_net_debug_net_ops);
115 	if (ret)
116 		return ret;
117 
118 	ret = register_netdevice_notifier(&rtnl_net_debug_block);
119 	if (ret)
120 		unregister_pernet_subsys(&rtnl_net_debug_net_ops);
121 
122 	return ret;
123 }
124 
125 static void __exit rtnl_net_debug_exit(void)
126 {
127 	unregister_netdevice_notifier(&rtnl_net_debug_block);
128 	unregister_pernet_device(&rtnl_net_debug_net_ops);
129 }
130 
131 subsys_initcall(rtnl_net_debug_init);
132