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