// SPDX-License-Identifier: GPL-2.0-or-later /* Copyright Amazon.com Inc. or its affiliates. */ #include #include #include #include #include #include static int rtnl_net_debug_event(struct notifier_block *nb, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); enum netdev_cmd cmd = event; /* Keep enum and don't add default to trigger -Werror=switch */ switch (cmd) { case NETDEV_UP: case NETDEV_DOWN: case NETDEV_REBOOT: case NETDEV_CHANGE: case NETDEV_REGISTER: case NETDEV_UNREGISTER: case NETDEV_CHANGEMTU: case NETDEV_CHANGEADDR: case NETDEV_PRE_CHANGEADDR: case NETDEV_GOING_DOWN: case NETDEV_CHANGENAME: case NETDEV_FEAT_CHANGE: case NETDEV_BONDING_FAILOVER: case NETDEV_PRE_UP: case NETDEV_PRE_TYPE_CHANGE: case NETDEV_POST_TYPE_CHANGE: case NETDEV_POST_INIT: case NETDEV_PRE_UNINIT: case NETDEV_RELEASE: case NETDEV_NOTIFY_PEERS: case NETDEV_JOIN: case NETDEV_CHANGEUPPER: case NETDEV_RESEND_IGMP: case NETDEV_PRECHANGEMTU: case NETDEV_CHANGEINFODATA: case NETDEV_BONDING_INFO: case NETDEV_PRECHANGEUPPER: case NETDEV_CHANGELOWERSTATE: case NETDEV_UDP_TUNNEL_PUSH_INFO: case NETDEV_UDP_TUNNEL_DROP_INFO: case NETDEV_CHANGE_TX_QUEUE_LEN: case NETDEV_CVLAN_FILTER_PUSH_INFO: case NETDEV_CVLAN_FILTER_DROP_INFO: case NETDEV_SVLAN_FILTER_PUSH_INFO: case NETDEV_SVLAN_FILTER_DROP_INFO: case NETDEV_OFFLOAD_XSTATS_ENABLE: case NETDEV_OFFLOAD_XSTATS_DISABLE: case NETDEV_OFFLOAD_XSTATS_REPORT_USED: case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA: case NETDEV_XDP_FEAT_CHANGE: ASSERT_RTNL(); break; /* Once an event fully supports RTNL_NET, move it here * and remove "if (0)" below. * * case NETDEV_XXX: * ASSERT_RTNL_NET(net); * break; */ } /* Just to avoid unused-variable error for dev and net. */ if (0) ASSERT_RTNL_NET(net); return NOTIFY_DONE; } static int rtnl_net_debug_net_id; static int __net_init rtnl_net_debug_net_init(struct net *net) { struct notifier_block *nb; nb = net_generic(net, rtnl_net_debug_net_id); nb->notifier_call = rtnl_net_debug_event; return register_netdevice_notifier_net(net, nb); } static void __net_exit rtnl_net_debug_net_exit(struct net *net) { struct notifier_block *nb; nb = net_generic(net, rtnl_net_debug_net_id); unregister_netdevice_notifier_net(net, nb); } static struct pernet_operations rtnl_net_debug_net_ops __net_initdata = { .init = rtnl_net_debug_net_init, .exit = rtnl_net_debug_net_exit, .id = &rtnl_net_debug_net_id, .size = sizeof(struct notifier_block), }; static struct notifier_block rtnl_net_debug_block = { .notifier_call = rtnl_net_debug_event, }; static int __init rtnl_net_debug_init(void) { int ret; ret = register_pernet_device(&rtnl_net_debug_net_ops); if (ret) return ret; ret = register_netdevice_notifier(&rtnl_net_debug_block); if (ret) unregister_pernet_subsys(&rtnl_net_debug_net_ops); return ret; } subsys_initcall(rtnl_net_debug_init);