Skip to content

Commit 03fa534

Browse files
q2venPaolo Abeni
authored andcommitted
rtnetlink: Add ASSERT_RTNL_NET() placeholder for netdev notifier.
The global and per-netns netdev notifier depend on RTNL, and its dependency is not so clear due to nested calls. Let's add a placeholder to place ASSERT_RTNL_NET() for each event. Signed-off-by: Kuniyuki Iwashima <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 844e5e7 commit 03fa534

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

net/core/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o
4545
obj-$(CONFIG_OF) += of_net.o
4646
obj-$(CONFIG_NET_TEST) += net_test.o
4747
obj-$(CONFIG_NET_DEVMEM) += devmem.o
48+
obj-$(CONFIG_DEBUG_NET_SMALL_RTNL) += rtnl_net_debug.o

net/core/rtnl_net_debug.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
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);

0 commit comments

Comments
 (0)