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> 9*1901066aSStanislav Fomichev #include <net/netdev_lock.h> 10b912d599SStanislav Fomichev #include <net/netns/generic.h> 11b912d599SStanislav Fomichev 12*1901066aSStanislav Fomichev int netdev_debug_event(struct notifier_block *nb, unsigned long event, 13*1901066aSStanislav 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) { 21*1901066aSStanislav Fomichev case NETDEV_REGISTER: 22b912d599SStanislav Fomichev case NETDEV_UP: 23*1901066aSStanislav Fomichev netdev_ops_assert_locked(dev); 24*1901066aSStanislav Fomichev fallthrough; 25b912d599SStanislav Fomichev case NETDEV_DOWN: 26b912d599SStanislav Fomichev case NETDEV_REBOOT: 27b912d599SStanislav Fomichev case NETDEV_CHANGE: 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 } 72*1901066aSStanislav Fomichev EXPORT_SYMBOL_NS_GPL(netdev_debug_event, "NETDEV_INTERNAL"); 73b912d599SStanislav Fomichev 74b912d599SStanislav Fomichev static int rtnl_net_debug_net_id; 75b912d599SStanislav Fomichev 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); 81*1901066aSStanislav Fomichev nb->notifier_call = netdev_debug_event; 82b912d599SStanislav Fomichev 83b912d599SStanislav Fomichev return register_netdevice_notifier_net(net, nb); 84b912d599SStanislav Fomichev } 85b912d599SStanislav Fomichev 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 = { 102*1901066aSStanislav Fomichev .notifier_call = netdev_debug_event, 103b912d599SStanislav Fomichev }; 104b912d599SStanislav Fomichev 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