1b912d599SStanislav Fomichev // SPDX-License-Identifier: GPL-2.0-or-later
2b912d599SStanislav Fomichev /* Copyright Amazon.com Inc. or its affiliates. */
3b912d599SStanislav Fomichev
4b912d599SStanislav Fomichev #include <linux/init.h>
5b912d599SStanislav Fomichev #include <linux/netdevice.h>
6b912d599SStanislav Fomichev #include <linux/notifier.h>
7b912d599SStanislav Fomichev #include <linux/rtnetlink.h>
8b912d599SStanislav Fomichev #include <net/net_namespace.h>
91901066aSStanislav Fomichev #include <net/netdev_lock.h>
10b912d599SStanislav Fomichev #include <net/netns/generic.h>
11b912d599SStanislav Fomichev
netdev_debug_event(struct notifier_block * nb,unsigned long event,void * ptr)121901066aSStanislav Fomichev int netdev_debug_event(struct notifier_block *nb, unsigned long event,
131901066aSStanislav Fomichev void *ptr)
14b912d599SStanislav Fomichev {
15b912d599SStanislav Fomichev struct net_device *dev = netdev_notifier_info_to_dev(ptr);
16b912d599SStanislav Fomichev struct net *net = dev_net(dev);
17b912d599SStanislav Fomichev enum netdev_cmd cmd = event;
18b912d599SStanislav Fomichev
19b912d599SStanislav Fomichev /* Keep enum and don't add default to trigger -Werror=switch */
20b912d599SStanislav Fomichev switch (cmd) {
211901066aSStanislav Fomichev case NETDEV_REGISTER:
22b912d599SStanislav Fomichev case NETDEV_UP:
23*04efcee6SStanislav Fomichev case NETDEV_CHANGE:
241901066aSStanislav Fomichev netdev_ops_assert_locked(dev);
251901066aSStanislav Fomichev fallthrough;
26b912d599SStanislav Fomichev case NETDEV_DOWN:
27b912d599SStanislav Fomichev case NETDEV_REBOOT:
28b912d599SStanislav Fomichev case NETDEV_UNREGISTER:
29b912d599SStanislav Fomichev case NETDEV_CHANGEMTU:
30b912d599SStanislav Fomichev case NETDEV_CHANGEADDR:
31b912d599SStanislav Fomichev case NETDEV_PRE_CHANGEADDR:
32b912d599SStanislav Fomichev case NETDEV_GOING_DOWN:
33b912d599SStanislav Fomichev case NETDEV_FEAT_CHANGE:
34b912d599SStanislav Fomichev case NETDEV_BONDING_FAILOVER:
35b912d599SStanislav Fomichev case NETDEV_PRE_UP:
36b912d599SStanislav Fomichev case NETDEV_PRE_TYPE_CHANGE:
37b912d599SStanislav Fomichev case NETDEV_POST_TYPE_CHANGE:
38b912d599SStanislav Fomichev case NETDEV_POST_INIT:
39b912d599SStanislav Fomichev case NETDEV_PRE_UNINIT:
40b912d599SStanislav Fomichev case NETDEV_RELEASE:
41b912d599SStanislav Fomichev case NETDEV_NOTIFY_PEERS:
42b912d599SStanislav Fomichev case NETDEV_JOIN:
43b912d599SStanislav Fomichev case NETDEV_CHANGEUPPER:
44b912d599SStanislav Fomichev case NETDEV_RESEND_IGMP:
45b912d599SStanislav Fomichev case NETDEV_PRECHANGEMTU:
46b912d599SStanislav Fomichev case NETDEV_CHANGEINFODATA:
47b912d599SStanislav Fomichev case NETDEV_BONDING_INFO:
48b912d599SStanislav Fomichev case NETDEV_PRECHANGEUPPER:
49b912d599SStanislav Fomichev case NETDEV_CHANGELOWERSTATE:
50b912d599SStanislav Fomichev case NETDEV_UDP_TUNNEL_PUSH_INFO:
51b912d599SStanislav Fomichev case NETDEV_UDP_TUNNEL_DROP_INFO:
52b912d599SStanislav Fomichev case NETDEV_CHANGE_TX_QUEUE_LEN:
53b912d599SStanislav Fomichev case NETDEV_CVLAN_FILTER_PUSH_INFO:
54b912d599SStanislav Fomichev case NETDEV_CVLAN_FILTER_DROP_INFO:
55b912d599SStanislav Fomichev case NETDEV_SVLAN_FILTER_PUSH_INFO:
56b912d599SStanislav Fomichev case NETDEV_SVLAN_FILTER_DROP_INFO:
57b912d599SStanislav Fomichev case NETDEV_OFFLOAD_XSTATS_ENABLE:
58b912d599SStanislav Fomichev case NETDEV_OFFLOAD_XSTATS_DISABLE:
59b912d599SStanislav Fomichev case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
60b912d599SStanislav Fomichev case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
61b912d599SStanislav Fomichev case NETDEV_XDP_FEAT_CHANGE:
62b912d599SStanislav Fomichev ASSERT_RTNL();
63b912d599SStanislav Fomichev break;
64b912d599SStanislav Fomichev
65b912d599SStanislav Fomichev case NETDEV_CHANGENAME:
66b912d599SStanislav Fomichev ASSERT_RTNL_NET(net);
67b912d599SStanislav Fomichev break;
68b912d599SStanislav Fomichev }
69b912d599SStanislav Fomichev
70b912d599SStanislav Fomichev return NOTIFY_DONE;
71b912d599SStanislav Fomichev }
721901066aSStanislav Fomichev EXPORT_SYMBOL_NS_GPL(netdev_debug_event, "NETDEV_INTERNAL");
73b912d599SStanislav Fomichev
74b912d599SStanislav Fomichev static int rtnl_net_debug_net_id;
75b912d599SStanislav Fomichev
rtnl_net_debug_net_init(struct net * net)76b912d599SStanislav Fomichev static int __net_init rtnl_net_debug_net_init(struct net *net)
77b912d599SStanislav Fomichev {
78b912d599SStanislav Fomichev struct notifier_block *nb;
79b912d599SStanislav Fomichev
80b912d599SStanislav Fomichev nb = net_generic(net, rtnl_net_debug_net_id);
811901066aSStanislav Fomichev nb->notifier_call = netdev_debug_event;
82b912d599SStanislav Fomichev
83b912d599SStanislav Fomichev return register_netdevice_notifier_net(net, nb);
84b912d599SStanislav Fomichev }
85b912d599SStanislav Fomichev
rtnl_net_debug_net_exit(struct net * net)86b912d599SStanislav Fomichev static void __net_exit rtnl_net_debug_net_exit(struct net *net)
87b912d599SStanislav Fomichev {
88b912d599SStanislav Fomichev struct notifier_block *nb;
89b912d599SStanislav Fomichev
90b912d599SStanislav Fomichev nb = net_generic(net, rtnl_net_debug_net_id);
91b912d599SStanislav Fomichev unregister_netdevice_notifier_net(net, nb);
92b912d599SStanislav Fomichev }
93b912d599SStanislav Fomichev
94b912d599SStanislav Fomichev static struct pernet_operations rtnl_net_debug_net_ops __net_initdata = {
95b912d599SStanislav Fomichev .init = rtnl_net_debug_net_init,
96b912d599SStanislav Fomichev .exit = rtnl_net_debug_net_exit,
97b912d599SStanislav Fomichev .id = &rtnl_net_debug_net_id,
98b912d599SStanislav Fomichev .size = sizeof(struct notifier_block),
99b912d599SStanislav Fomichev };
100b912d599SStanislav Fomichev
101b912d599SStanislav Fomichev static struct notifier_block rtnl_net_debug_block = {
1021901066aSStanislav Fomichev .notifier_call = netdev_debug_event,
103b912d599SStanislav Fomichev };
104b912d599SStanislav Fomichev
rtnl_net_debug_init(void)105b912d599SStanislav Fomichev static int __init rtnl_net_debug_init(void)
106b912d599SStanislav Fomichev {
107b912d599SStanislav Fomichev int ret;
108b912d599SStanislav Fomichev
109b912d599SStanislav Fomichev ret = register_pernet_subsys(&rtnl_net_debug_net_ops);
110b912d599SStanislav Fomichev if (ret)
111b912d599SStanislav Fomichev return ret;
112b912d599SStanislav Fomichev
113b912d599SStanislav Fomichev ret = register_netdevice_notifier(&rtnl_net_debug_block);
114b912d599SStanislav Fomichev if (ret)
115b912d599SStanislav Fomichev unregister_pernet_subsys(&rtnl_net_debug_net_ops);
116b912d599SStanislav Fomichev
117b912d599SStanislav Fomichev return ret;
118b912d599SStanislav Fomichev }
119b912d599SStanislav Fomichev
120b912d599SStanislav Fomichev subsys_initcall(rtnl_net_debug_init);
121