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