/net/core/dev.c
http://github.com/mirrors/linux · C · 10568 lines · 6899 code · 1665 blank · 2004 comment · 1201 complexity · b85658a488468d1c3f7f658206f1a07c MD5 · raw file
Large files are truncated click here to view the full file
- // SPDX-License-Identifier: GPL-2.0-or-later
- /*
- * NET3 Protocol independent device support routines.
- *
- * Derived from the non IP parts of dev.c 1.0.19
- * Authors: Ross Biro
- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- * Mark Evans, <evansmp@uhura.aston.ac.uk>
- *
- * Additional Authors:
- * Florian la Roche <rzsfl@rz.uni-sb.de>
- * Alan Cox <gw4pts@gw4pts.ampr.org>
- * David Hinds <dahinds@users.sourceforge.net>
- * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
- * Adam Sulmicki <adam@cfar.umd.edu>
- * Pekka Riikonen <priikone@poesidon.pspt.fi>
- *
- * Changes:
- * D.J. Barrow : Fixed bug where dev->refcnt gets set
- * to 2 if register_netdev gets called
- * before net_dev_init & also removed a
- * few lines of code in the process.
- * Alan Cox : device private ioctl copies fields back.
- * Alan Cox : Transmit queue code does relevant
- * stunts to keep the queue safe.
- * Alan Cox : Fixed double lock.
- * Alan Cox : Fixed promisc NULL pointer trap
- * ???????? : Support the full private ioctl range
- * Alan Cox : Moved ioctl permission check into
- * drivers
- * Tim Kordas : SIOCADDMULTI/SIOCDELMULTI
- * Alan Cox : 100 backlog just doesn't cut it when
- * you start doing multicast video 8)
- * Alan Cox : Rewrote net_bh and list manager.
- * Alan Cox : Fix ETH_P_ALL echoback lengths.
- * Alan Cox : Took out transmit every packet pass
- * Saved a few bytes in the ioctl handler
- * Alan Cox : Network driver sets packet type before
- * calling netif_rx. Saves a function
- * call a packet.
- * Alan Cox : Hashed net_bh()
- * Richard Kooijman: Timestamp fixes.
- * Alan Cox : Wrong field in SIOCGIFDSTADDR
- * Alan Cox : Device lock protection.
- * Alan Cox : Fixed nasty side effect of device close
- * changes.
- * Rudi Cilibrasi : Pass the right thing to
- * set_mac_address()
- * Dave Miller : 32bit quantity for the device lock to
- * make it work out on a Sparc.
- * Bjorn Ekwall : Added KERNELD hack.
- * Alan Cox : Cleaned up the backlog initialise.
- * Craig Metz : SIOCGIFCONF fix if space for under
- * 1 device.
- * Thomas Bogendoerfer : Return ENODEV for dev_open, if there
- * is no device open function.
- * Andi Kleen : Fix error reporting for SIOCGIFCONF
- * Michael Chastain : Fix signed/unsigned for SIOCGIFCONF
- * Cyrus Durgin : Cleaned for KMOD
- * Adam Sulmicki : Bug Fix : Network Device Unload
- * A network device unload needs to purge
- * the backlog queue.
- * Paul Rusty Russell : SIOCSIFNAME
- * Pekka Riikonen : Netdev boot-time settings code
- * Andrew Morton : Make unregister_netdevice wait
- * indefinitely on dev->refcnt
- * J Hadi Salim : - Backlog queue sampling
- * - netif_rx() feedback
- */
- #include <linux/uaccess.h>
- #include <linux/bitops.h>
- #include <linux/capability.h>
- #include <linux/cpu.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/hash.h>
- #include <linux/slab.h>
- #include <linux/sched.h>
- #include <linux/sched/mm.h>
- #include <linux/mutex.h>
- #include <linux/string.h>
- #include <linux/mm.h>
- #include <linux/socket.h>
- #include <linux/sockios.h>
- #include <linux/errno.h>
- #include <linux/interrupt.h>
- #include <linux/if_ether.h>
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/ethtool.h>
- #include <linux/skbuff.h>
- #include <linux/bpf.h>
- #include <linux/bpf_trace.h>
- #include <net/net_namespace.h>
- #include <net/sock.h>
- #include <net/busy_poll.h>
- #include <linux/rtnetlink.h>
- #include <linux/stat.h>
- #include <net/dst.h>
- #include <net/dst_metadata.h>
- #include <net/pkt_sched.h>
- #include <net/pkt_cls.h>
- #include <net/checksum.h>
- #include <net/xfrm.h>
- #include <linux/highmem.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/netpoll.h>
- #include <linux/rcupdate.h>
- #include <linux/delay.h>
- #include <net/iw_handler.h>
- #include <asm/current.h>
- #include <linux/audit.h>
- #include <linux/dmaengine.h>
- #include <linux/err.h>
- #include <linux/ctype.h>
- #include <linux/if_arp.h>
- #include <linux/if_vlan.h>
- #include <linux/ip.h>
- #include <net/ip.h>
- #include <net/mpls.h>
- #include <linux/ipv6.h>
- #include <linux/in.h>
- #include <linux/jhash.h>
- #include <linux/random.h>
- #include <trace/events/napi.h>
- #include <trace/events/net.h>
- #include <trace/events/skb.h>
- #include <linux/inetdevice.h>
- #include <linux/cpu_rmap.h>
- #include <linux/static_key.h>
- #include <linux/hashtable.h>
- #include <linux/vmalloc.h>
- #include <linux/if_macvlan.h>
- #include <linux/errqueue.h>
- #include <linux/hrtimer.h>
- #include <linux/netfilter_ingress.h>
- #include <linux/crash_dump.h>
- #include <linux/sctp.h>
- #include <net/udp_tunnel.h>
- #include <linux/net_namespace.h>
- #include <linux/indirect_call_wrapper.h>
- #include <net/devlink.h>
- #include "net-sysfs.h"
- #define MAX_GRO_SKBS 8
- /* This should be increased if a protocol with a bigger head is added. */
- #define GRO_MAX_HEAD (MAX_HEADER + 128)
- static DEFINE_SPINLOCK(ptype_lock);
- static DEFINE_SPINLOCK(offload_lock);
- struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly;
- struct list_head ptype_all __read_mostly; /* Taps */
- static struct list_head offload_base __read_mostly;
- static int netif_rx_internal(struct sk_buff *skb);
- static int call_netdevice_notifiers_info(unsigned long val,
- struct netdev_notifier_info *info);
- static int call_netdevice_notifiers_extack(unsigned long val,
- struct net_device *dev,
- struct netlink_ext_ack *extack);
- static struct napi_struct *napi_by_id(unsigned int napi_id);
- /*
- * The @dev_base_head list is protected by @dev_base_lock and the rtnl
- * semaphore.
- *
- * Pure readers hold dev_base_lock for reading, or rcu_read_lock()
- *
- * Writers must hold the rtnl semaphore while they loop through the
- * dev_base_head list, and hold dev_base_lock for writing when they do the
- * actual updates. This allows pure readers to access the list even
- * while a writer is preparing to update it.
- *
- * To put it another way, dev_base_lock is held for writing only to
- * protect against pure readers; the rtnl semaphore provides the
- * protection against other writers.
- *
- * See, for example usages, register_netdevice() and
- * unregister_netdevice(), which must be called with the rtnl
- * semaphore held.
- */
- DEFINE_RWLOCK(dev_base_lock);
- EXPORT_SYMBOL(dev_base_lock);
- static DEFINE_MUTEX(ifalias_mutex);
- /* protects napi_hash addition/deletion and napi_gen_id */
- static DEFINE_SPINLOCK(napi_hash_lock);
- static unsigned int napi_gen_id = NR_CPUS;
- static DEFINE_READ_MOSTLY_HASHTABLE(napi_hash, 8);
- static seqcount_t devnet_rename_seq;
- static inline void dev_base_seq_inc(struct net *net)
- {
- while (++net->dev_base_seq == 0)
- ;
- }
- static inline struct hlist_head *dev_name_hash(struct net *net, const char *name)
- {
- unsigned int hash = full_name_hash(net, name, strnlen(name, IFNAMSIZ));
- return &net->dev_name_head[hash_32(hash, NETDEV_HASHBITS)];
- }
- static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
- {
- return &net->dev_index_head[ifindex & (NETDEV_HASHENTRIES - 1)];
- }
- static inline void rps_lock(struct softnet_data *sd)
- {
- #ifdef CONFIG_RPS
- spin_lock(&sd->input_pkt_queue.lock);
- #endif
- }
- static inline void rps_unlock(struct softnet_data *sd)
- {
- #ifdef CONFIG_RPS
- spin_unlock(&sd->input_pkt_queue.lock);
- #endif
- }
- static struct netdev_name_node *netdev_name_node_alloc(struct net_device *dev,
- const char *name)
- {
- struct netdev_name_node *name_node;
- name_node = kmalloc(sizeof(*name_node), GFP_KERNEL);
- if (!name_node)
- return NULL;
- INIT_HLIST_NODE(&name_node->hlist);
- name_node->dev = dev;
- name_node->name = name;
- return name_node;
- }
- static struct netdev_name_node *
- netdev_name_node_head_alloc(struct net_device *dev)
- {
- struct netdev_name_node *name_node;
- name_node = netdev_name_node_alloc(dev, dev->name);
- if (!name_node)
- return NULL;
- INIT_LIST_HEAD(&name_node->list);
- return name_node;
- }
- static void netdev_name_node_free(struct netdev_name_node *name_node)
- {
- kfree(name_node);
- }
- static void netdev_name_node_add(struct net *net,
- struct netdev_name_node *name_node)
- {
- hlist_add_head_rcu(&name_node->hlist,
- dev_name_hash(net, name_node->name));
- }
- static void netdev_name_node_del(struct netdev_name_node *name_node)
- {
- hlist_del_rcu(&name_node->hlist);
- }
- static struct netdev_name_node *netdev_name_node_lookup(struct net *net,
- const char *name)
- {
- struct hlist_head *head = dev_name_hash(net, name);
- struct netdev_name_node *name_node;
- hlist_for_each_entry(name_node, head, hlist)
- if (!strcmp(name_node->name, name))
- return name_node;
- return NULL;
- }
- static struct netdev_name_node *netdev_name_node_lookup_rcu(struct net *net,
- const char *name)
- {
- struct hlist_head *head = dev_name_hash(net, name);
- struct netdev_name_node *name_node;
- hlist_for_each_entry_rcu(name_node, head, hlist)
- if (!strcmp(name_node->name, name))
- return name_node;
- return NULL;
- }
- int netdev_name_node_alt_create(struct net_device *dev, const char *name)
- {
- struct netdev_name_node *name_node;
- struct net *net = dev_net(dev);
- name_node = netdev_name_node_lookup(net, name);
- if (name_node)
- return -EEXIST;
- name_node = netdev_name_node_alloc(dev, name);
- if (!name_node)
- return -ENOMEM;
- netdev_name_node_add(net, name_node);
- /* The node that holds dev->name acts as a head of per-device list. */
- list_add_tail(&name_node->list, &dev->name_node->list);
- return 0;
- }
- EXPORT_SYMBOL(netdev_name_node_alt_create);
- static void __netdev_name_node_alt_destroy(struct netdev_name_node *name_node)
- {
- list_del(&name_node->list);
- netdev_name_node_del(name_node);
- kfree(name_node->name);
- netdev_name_node_free(name_node);
- }
- int netdev_name_node_alt_destroy(struct net_device *dev, const char *name)
- {
- struct netdev_name_node *name_node;
- struct net *net = dev_net(dev);
- name_node = netdev_name_node_lookup(net, name);
- if (!name_node)
- return -ENOENT;
- /* lookup might have found our primary name or a name belonging
- * to another device.
- */
- if (name_node == dev->name_node || name_node->dev != dev)
- return -EINVAL;
- __netdev_name_node_alt_destroy(name_node);
- return 0;
- }
- EXPORT_SYMBOL(netdev_name_node_alt_destroy);
- static void netdev_name_node_alt_flush(struct net_device *dev)
- {
- struct netdev_name_node *name_node, *tmp;
- list_for_each_entry_safe(name_node, tmp, &dev->name_node->list, list)
- __netdev_name_node_alt_destroy(name_node);
- }
- /* Device list insertion */
- static void list_netdevice(struct net_device *dev)
- {
- struct net *net = dev_net(dev);
- ASSERT_RTNL();
- write_lock_bh(&dev_base_lock);
- list_add_tail_rcu(&dev->dev_list, &net->dev_base_head);
- netdev_name_node_add(net, dev->name_node);
- hlist_add_head_rcu(&dev->index_hlist,
- dev_index_hash(net, dev->ifindex));
- write_unlock_bh(&dev_base_lock);
- dev_base_seq_inc(net);
- }
- /* Device list removal
- * caller must respect a RCU grace period before freeing/reusing dev
- */
- static void unlist_netdevice(struct net_device *dev)
- {
- ASSERT_RTNL();
- /* Unlink dev from the device chain */
- write_lock_bh(&dev_base_lock);
- list_del_rcu(&dev->dev_list);
- netdev_name_node_del(dev->name_node);
- hlist_del_rcu(&dev->index_hlist);
- write_unlock_bh(&dev_base_lock);
- dev_base_seq_inc(dev_net(dev));
- }
- /*
- * Our notifier list
- */
- static RAW_NOTIFIER_HEAD(netdev_chain);
- /*
- * Device drivers call our routines to queue packets here. We empty the
- * queue in the local softnet handler.
- */
- DEFINE_PER_CPU_ALIGNED(struct softnet_data, softnet_data);
- EXPORT_PER_CPU_SYMBOL(softnet_data);
- /*******************************************************************************
- *
- * Protocol management and registration routines
- *
- *******************************************************************************/
- /*
- * Add a protocol ID to the list. Now that the input handler is
- * smarter we can dispense with all the messy stuff that used to be
- * here.
- *
- * BEWARE!!! Protocol handlers, mangling input packets,
- * MUST BE last in hash buckets and checking protocol handlers
- * MUST start from promiscuous ptype_all chain in net_bh.
- * It is true now, do not change it.
- * Explanation follows: if protocol handler, mangling packet, will
- * be the first on list, it is not able to sense, that packet
- * is cloned and should be copied-on-write, so that it will
- * change it and subsequent readers will get broken packet.
- * --ANK (980803)
- */
- static inline struct list_head *ptype_head(const struct packet_type *pt)
- {
- if (pt->type == htons(ETH_P_ALL))
- return pt->dev ? &pt->dev->ptype_all : &ptype_all;
- else
- return pt->dev ? &pt->dev->ptype_specific :
- &ptype_base[ntohs(pt->type) & PTYPE_HASH_MASK];
- }
- /**
- * dev_add_pack - add packet handler
- * @pt: packet type declaration
- *
- * Add a protocol handler to the networking stack. The passed &packet_type
- * is linked into kernel lists and may not be freed until it has been
- * removed from the kernel lists.
- *
- * This call does not sleep therefore it can not
- * guarantee all CPU's that are in middle of receiving packets
- * will see the new packet type (until the next received packet).
- */
- void dev_add_pack(struct packet_type *pt)
- {
- struct list_head *head = ptype_head(pt);
- spin_lock(&ptype_lock);
- list_add_rcu(&pt->list, head);
- spin_unlock(&ptype_lock);
- }
- EXPORT_SYMBOL(dev_add_pack);
- /**
- * __dev_remove_pack - remove packet handler
- * @pt: packet type declaration
- *
- * Remove a protocol handler that was previously added to the kernel
- * protocol handlers by dev_add_pack(). The passed &packet_type is removed
- * from the kernel lists and can be freed or reused once this function
- * returns.
- *
- * The packet type might still be in use by receivers
- * and must not be freed until after all the CPU's have gone
- * through a quiescent state.
- */
- void __dev_remove_pack(struct packet_type *pt)
- {
- struct list_head *head = ptype_head(pt);
- struct packet_type *pt1;
- spin_lock(&ptype_lock);
- list_for_each_entry(pt1, head, list) {
- if (pt == pt1) {
- list_del_rcu(&pt->list);
- goto out;
- }
- }
- pr_warn("dev_remove_pack: %p not found\n", pt);
- out:
- spin_unlock(&ptype_lock);
- }
- EXPORT_SYMBOL(__dev_remove_pack);
- /**
- * dev_remove_pack - remove packet handler
- * @pt: packet type declaration
- *
- * Remove a protocol handler that was previously added to the kernel
- * protocol handlers by dev_add_pack(). The passed &packet_type is removed
- * from the kernel lists and can be freed or reused once this function
- * returns.
- *
- * This call sleeps to guarantee that no CPU is looking at the packet
- * type after return.
- */
- void dev_remove_pack(struct packet_type *pt)
- {
- __dev_remove_pack(pt);
- synchronize_net();
- }
- EXPORT_SYMBOL(dev_remove_pack);
- /**
- * dev_add_offload - register offload handlers
- * @po: protocol offload declaration
- *
- * Add protocol offload handlers to the networking stack. The passed
- * &proto_offload is linked into kernel lists and may not be freed until
- * it has been removed from the kernel lists.
- *
- * This call does not sleep therefore it can not
- * guarantee all CPU's that are in middle of receiving packets
- * will see the new offload handlers (until the next received packet).
- */
- void dev_add_offload(struct packet_offload *po)
- {
- struct packet_offload *elem;
- spin_lock(&offload_lock);
- list_for_each_entry(elem, &offload_base, list) {
- if (po->priority < elem->priority)
- break;
- }
- list_add_rcu(&po->list, elem->list.prev);
- spin_unlock(&offload_lock);
- }
- EXPORT_SYMBOL(dev_add_offload);
- /**
- * __dev_remove_offload - remove offload handler
- * @po: packet offload declaration
- *
- * Remove a protocol offload handler that was previously added to the
- * kernel offload handlers by dev_add_offload(). The passed &offload_type
- * is removed from the kernel lists and can be freed or reused once this
- * function returns.
- *
- * The packet type might still be in use by receivers
- * and must not be freed until after all the CPU's have gone
- * through a quiescent state.
- */
- static void __dev_remove_offload(struct packet_offload *po)
- {
- struct list_head *head = &offload_base;
- struct packet_offload *po1;
- spin_lock(&offload_lock);
- list_for_each_entry(po1, head, list) {
- if (po == po1) {
- list_del_rcu(&po->list);
- goto out;
- }
- }
- pr_warn("dev_remove_offload: %p not found\n", po);
- out:
- spin_unlock(&offload_lock);
- }
- /**
- * dev_remove_offload - remove packet offload handler
- * @po: packet offload declaration
- *
- * Remove a packet offload handler that was previously added to the kernel
- * offload handlers by dev_add_offload(). The passed &offload_type is
- * removed from the kernel lists and can be freed or reused once this
- * function returns.
- *
- * This call sleeps to guarantee that no CPU is looking at the packet
- * type after return.
- */
- void dev_remove_offload(struct packet_offload *po)
- {
- __dev_remove_offload(po);
- synchronize_net();
- }
- EXPORT_SYMBOL(dev_remove_offload);
- /******************************************************************************
- *
- * Device Boot-time Settings Routines
- *
- ******************************************************************************/
- /* Boot time configuration table */
- static struct netdev_boot_setup dev_boot_setup[NETDEV_BOOT_SETUP_MAX];
- /**
- * netdev_boot_setup_add - add new setup entry
- * @name: name of the device
- * @map: configured settings for the device
- *
- * Adds new setup entry to the dev_boot_setup list. The function
- * returns 0 on error and 1 on success. This is a generic routine to
- * all netdevices.
- */
- static int netdev_boot_setup_add(char *name, struct ifmap *map)
- {
- struct netdev_boot_setup *s;
- int i;
- s = dev_boot_setup;
- for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) {
- if (s[i].name[0] == '\0' || s[i].name[0] == ' ') {
- memset(s[i].name, 0, sizeof(s[i].name));
- strlcpy(s[i].name, name, IFNAMSIZ);
- memcpy(&s[i].map, map, sizeof(s[i].map));
- break;
- }
- }
- return i >= NETDEV_BOOT_SETUP_MAX ? 0 : 1;
- }
- /**
- * netdev_boot_setup_check - check boot time settings
- * @dev: the netdevice
- *
- * Check boot time settings for the device.
- * The found settings are set for the device to be used
- * later in the device probing.
- * Returns 0 if no settings found, 1 if they are.
- */
- int netdev_boot_setup_check(struct net_device *dev)
- {
- struct netdev_boot_setup *s = dev_boot_setup;
- int i;
- for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) {
- if (s[i].name[0] != '\0' && s[i].name[0] != ' ' &&
- !strcmp(dev->name, s[i].name)) {
- dev->irq = s[i].map.irq;
- dev->base_addr = s[i].map.base_addr;
- dev->mem_start = s[i].map.mem_start;
- dev->mem_end = s[i].map.mem_end;
- return 1;
- }
- }
- return 0;
- }
- EXPORT_SYMBOL(netdev_boot_setup_check);
- /**
- * netdev_boot_base - get address from boot time settings
- * @prefix: prefix for network device
- * @unit: id for network device
- *
- * Check boot time settings for the base address of device.
- * The found settings are set for the device to be used
- * later in the device probing.
- * Returns 0 if no settings found.
- */
- unsigned long netdev_boot_base(const char *prefix, int unit)
- {
- const struct netdev_boot_setup *s = dev_boot_setup;
- char name[IFNAMSIZ];
- int i;
- sprintf(name, "%s%d", prefix, unit);
- /*
- * If device already registered then return base of 1
- * to indicate not to probe for this interface
- */
- if (__dev_get_by_name(&init_net, name))
- return 1;
- for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++)
- if (!strcmp(name, s[i].name))
- return s[i].map.base_addr;
- return 0;
- }
- /*
- * Saves at boot time configured settings for any netdevice.
- */
- int __init netdev_boot_setup(char *str)
- {
- int ints[5];
- struct ifmap map;
- str = get_options(str, ARRAY_SIZE(ints), ints);
- if (!str || !*str)
- return 0;
- /* Save settings */
- memset(&map, 0, sizeof(map));
- if (ints[0] > 0)
- map.irq = ints[1];
- if (ints[0] > 1)
- map.base_addr = ints[2];
- if (ints[0] > 2)
- map.mem_start = ints[3];
- if (ints[0] > 3)
- map.mem_end = ints[4];
- /* Add new entry to the list */
- return netdev_boot_setup_add(str, &map);
- }
- __setup("netdev=", netdev_boot_setup);
- /*******************************************************************************
- *
- * Device Interface Subroutines
- *
- *******************************************************************************/
- /**
- * dev_get_iflink - get 'iflink' value of a interface
- * @dev: targeted interface
- *
- * Indicates the ifindex the interface is linked to.
- * Physical interfaces have the same 'ifindex' and 'iflink' values.
- */
- int dev_get_iflink(const struct net_device *dev)
- {
- if (dev->netdev_ops && dev->netdev_ops->ndo_get_iflink)
- return dev->netdev_ops->ndo_get_iflink(dev);
- return dev->ifindex;
- }
- EXPORT_SYMBOL(dev_get_iflink);
- /**
- * dev_fill_metadata_dst - Retrieve tunnel egress information.
- * @dev: targeted interface
- * @skb: The packet.
- *
- * For better visibility of tunnel traffic OVS needs to retrieve
- * egress tunnel information for a packet. Following API allows
- * user to get this info.
- */
- int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
- {
- struct ip_tunnel_info *info;
- if (!dev->netdev_ops || !dev->netdev_ops->ndo_fill_metadata_dst)
- return -EINVAL;
- info = skb_tunnel_info_unclone(skb);
- if (!info)
- return -ENOMEM;
- if (unlikely(!(info->mode & IP_TUNNEL_INFO_TX)))
- return -EINVAL;
- return dev->netdev_ops->ndo_fill_metadata_dst(dev, skb);
- }
- EXPORT_SYMBOL_GPL(dev_fill_metadata_dst);
- /**
- * __dev_get_by_name - find a device by its name
- * @net: the applicable net namespace
- * @name: name to find
- *
- * Find an interface by name. Must be called under RTNL semaphore
- * or @dev_base_lock. If the name is found a pointer to the device
- * is returned. If the name is not found then %NULL is returned. The
- * reference counters are not incremented so the caller must be
- * careful with locks.
- */
- struct net_device *__dev_get_by_name(struct net *net, const char *name)
- {
- struct netdev_name_node *node_name;
- node_name = netdev_name_node_lookup(net, name);
- return node_name ? node_name->dev : NULL;
- }
- EXPORT_SYMBOL(__dev_get_by_name);
- /**
- * dev_get_by_name_rcu - find a device by its name
- * @net: the applicable net namespace
- * @name: name to find
- *
- * Find an interface by name.
- * If the name is found a pointer to the device is returned.
- * If the name is not found then %NULL is returned.
- * The reference counters are not incremented so the caller must be
- * careful with locks. The caller must hold RCU lock.
- */
- struct net_device *dev_get_by_name_rcu(struct net *net, const char *name)
- {
- struct netdev_name_node *node_name;
- node_name = netdev_name_node_lookup_rcu(net, name);
- return node_name ? node_name->dev : NULL;
- }
- EXPORT_SYMBOL(dev_get_by_name_rcu);
- /**
- * dev_get_by_name - find a device by its name
- * @net: the applicable net namespace
- * @name: name to find
- *
- * Find an interface by name. This can be called from any
- * context and does its own locking. The returned handle has
- * the usage count incremented and the caller must use dev_put() to
- * release it when it is no longer needed. %NULL is returned if no
- * matching device is found.
- */
- struct net_device *dev_get_by_name(struct net *net, const char *name)
- {
- struct net_device *dev;
- rcu_read_lock();
- dev = dev_get_by_name_rcu(net, name);
- if (dev)
- dev_hold(dev);
- rcu_read_unlock();
- return dev;
- }
- EXPORT_SYMBOL(dev_get_by_name);
- /**
- * __dev_get_by_index - find a device by its ifindex
- * @net: the applicable net namespace
- * @ifindex: index of device
- *
- * Search for an interface by index. Returns %NULL if the device
- * is not found or a pointer to the device. The device has not
- * had its reference counter increased so the caller must be careful
- * about locking. The caller must hold either the RTNL semaphore
- * or @dev_base_lock.
- */
- struct net_device *__dev_get_by_index(struct net *net, int ifindex)
- {
- struct net_device *dev;
- struct hlist_head *head = dev_index_hash(net, ifindex);
- hlist_for_each_entry(dev, head, index_hlist)
- if (dev->ifindex == ifindex)
- return dev;
- return NULL;
- }
- EXPORT_SYMBOL(__dev_get_by_index);
- /**
- * dev_get_by_index_rcu - find a device by its ifindex
- * @net: the applicable net namespace
- * @ifindex: index of device
- *
- * Search for an interface by index. Returns %NULL if the device
- * is not found or a pointer to the device. The device has not
- * had its reference counter increased so the caller must be careful
- * about locking. The caller must hold RCU lock.
- */
- struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex)
- {
- struct net_device *dev;
- struct hlist_head *head = dev_index_hash(net, ifindex);
- hlist_for_each_entry_rcu(dev, head, index_hlist)
- if (dev->ifindex == ifindex)
- return dev;
- return NULL;
- }
- EXPORT_SYMBOL(dev_get_by_index_rcu);
- /**
- * dev_get_by_index - find a device by its ifindex
- * @net: the applicable net namespace
- * @ifindex: index of device
- *
- * Search for an interface by index. Returns NULL if the device
- * is not found or a pointer to the device. The device returned has
- * had a reference added and the pointer is safe until the user calls
- * dev_put to indicate they have finished with it.
- */
- struct net_device *dev_get_by_index(struct net *net, int ifindex)
- {
- struct net_device *dev;
- rcu_read_lock();
- dev = dev_get_by_index_rcu(net, ifindex);
- if (dev)
- dev_hold(dev);
- rcu_read_unlock();
- return dev;
- }
- EXPORT_SYMBOL(dev_get_by_index);
- /**
- * dev_get_by_napi_id - find a device by napi_id
- * @napi_id: ID of the NAPI struct
- *
- * Search for an interface by NAPI ID. Returns %NULL if the device
- * is not found or a pointer to the device. The device has not had
- * its reference counter increased so the caller must be careful
- * about locking. The caller must hold RCU lock.
- */
- struct net_device *dev_get_by_napi_id(unsigned int napi_id)
- {
- struct napi_struct *napi;
- WARN_ON_ONCE(!rcu_read_lock_held());
- if (napi_id < MIN_NAPI_ID)
- return NULL;
- napi = napi_by_id(napi_id);
- return napi ? napi->dev : NULL;
- }
- EXPORT_SYMBOL(dev_get_by_napi_id);
- /**
- * netdev_get_name - get a netdevice name, knowing its ifindex.
- * @net: network namespace
- * @name: a pointer to the buffer where the name will be stored.
- * @ifindex: the ifindex of the interface to get the name from.
- *
- * The use of raw_seqcount_begin() and cond_resched() before
- * retrying is required as we want to give the writers a chance
- * to complete when CONFIG_PREEMPTION is not set.
- */
- int netdev_get_name(struct net *net, char *name, int ifindex)
- {
- struct net_device *dev;
- unsigned int seq;
- retry:
- seq = raw_seqcount_begin(&devnet_rename_seq);
- rcu_read_lock();
- dev = dev_get_by_index_rcu(net, ifindex);
- if (!dev) {
- rcu_read_unlock();
- return -ENODEV;
- }
- strcpy(name, dev->name);
- rcu_read_unlock();
- if (read_seqcount_retry(&devnet_rename_seq, seq)) {
- cond_resched();
- goto retry;
- }
- return 0;
- }
- /**
- * dev_getbyhwaddr_rcu - find a device by its hardware address
- * @net: the applicable net namespace
- * @type: media type of device
- * @ha: hardware address
- *
- * Search for an interface by MAC address. Returns NULL if the device
- * is not found or a pointer to the device.
- * The caller must hold RCU or RTNL.
- * The returned device has not had its ref count increased
- * and the caller must therefore be careful about locking
- *
- */
- struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type,
- const char *ha)
- {
- struct net_device *dev;
- for_each_netdev_rcu(net, dev)
- if (dev->type == type &&
- !memcmp(dev->dev_addr, ha, dev->addr_len))
- return dev;
- return NULL;
- }
- EXPORT_SYMBOL(dev_getbyhwaddr_rcu);
- struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type)
- {
- struct net_device *dev;
- ASSERT_RTNL();
- for_each_netdev(net, dev)
- if (dev->type == type)
- return dev;
- return NULL;
- }
- EXPORT_SYMBOL(__dev_getfirstbyhwtype);
- struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type)
- {
- struct net_device *dev, *ret = NULL;
- rcu_read_lock();
- for_each_netdev_rcu(net, dev)
- if (dev->type == type) {
- dev_hold(dev);
- ret = dev;
- break;
- }
- rcu_read_unlock();
- return ret;
- }
- EXPORT_SYMBOL(dev_getfirstbyhwtype);
- /**
- * __dev_get_by_flags - find any device with given flags
- * @net: the applicable net namespace
- * @if_flags: IFF_* values
- * @mask: bitmask of bits in if_flags to check
- *
- * Search for any interface with the given flags. Returns NULL if a device
- * is not found or a pointer to the device. Must be called inside
- * rtnl_lock(), and result refcount is unchanged.
- */
- struct net_device *__dev_get_by_flags(struct net *net, unsigned short if_flags,
- unsigned short mask)
- {
- struct net_device *dev, *ret;
- ASSERT_RTNL();
- ret = NULL;
- for_each_netdev(net, dev) {
- if (((dev->flags ^ if_flags) & mask) == 0) {
- ret = dev;
- break;
- }
- }
- return ret;
- }
- EXPORT_SYMBOL(__dev_get_by_flags);
- /**
- * dev_valid_name - check if name is okay for network device
- * @name: name string
- *
- * Network device names need to be valid file names to
- * to allow sysfs to work. We also disallow any kind of
- * whitespace.
- */
- bool dev_valid_name(const char *name)
- {
- if (*name == '\0')
- return false;
- if (strnlen(name, IFNAMSIZ) == IFNAMSIZ)
- return false;
- if (!strcmp(name, ".") || !strcmp(name, ".."))
- return false;
- while (*name) {
- if (*name == '/' || *name == ':' || isspace(*name))
- return false;
- name++;
- }
- return true;
- }
- EXPORT_SYMBOL(dev_valid_name);
- /**
- * __dev_alloc_name - allocate a name for a device
- * @net: network namespace to allocate the device name in
- * @name: name format string
- * @buf: scratch buffer and result name string
- *
- * Passed a format string - eg "lt%d" it will try and find a suitable
- * id. It scans list of devices to build up a free map, then chooses
- * the first empty slot. The caller must hold the dev_base or rtnl lock
- * while allocating the name and adding the device in order to avoid
- * duplicates.
- * Limited to bits_per_byte * page size devices (ie 32K on most platforms).
- * Returns the number of the unit assigned or a negative errno code.
- */
- static int __dev_alloc_name(struct net *net, const char *name, char *buf)
- {
- int i = 0;
- const char *p;
- const int max_netdevices = 8*PAGE_SIZE;
- unsigned long *inuse;
- struct net_device *d;
- if (!dev_valid_name(name))
- return -EINVAL;
- p = strchr(name, '%');
- if (p) {
- /*
- * Verify the string as this thing may have come from
- * the user. There must be either one "%d" and no other "%"
- * characters.
- */
- if (p[1] != 'd' || strchr(p + 2, '%'))
- return -EINVAL;
- /* Use one page as a bit array of possible slots */
- inuse = (unsigned long *) get_zeroed_page(GFP_ATOMIC);
- if (!inuse)
- return -ENOMEM;
- for_each_netdev(net, d) {
- if (!sscanf(d->name, name, &i))
- continue;
- if (i < 0 || i >= max_netdevices)
- continue;
- /* avoid cases where sscanf is not exact inverse of printf */
- snprintf(buf, IFNAMSIZ, name, i);
- if (!strncmp(buf, d->name, IFNAMSIZ))
- set_bit(i, inuse);
- }
- i = find_first_zero_bit(inuse, max_netdevices);
- free_page((unsigned long) inuse);
- }
- snprintf(buf, IFNAMSIZ, name, i);
- if (!__dev_get_by_name(net, buf))
- return i;
- /* It is possible to run out of possible slots
- * when the name is long and there isn't enough space left
- * for the digits, or if all bits are used.
- */
- return -ENFILE;
- }
- static int dev_alloc_name_ns(struct net *net,
- struct net_device *dev,
- const char *name)
- {
- char buf[IFNAMSIZ];
- int ret;
- BUG_ON(!net);
- ret = __dev_alloc_name(net, name, buf);
- if (ret >= 0)
- strlcpy(dev->name, buf, IFNAMSIZ);
- return ret;
- }
- /**
- * dev_alloc_name - allocate a name for a device
- * @dev: device
- * @name: name format string
- *
- * Passed a format string - eg "lt%d" it will try and find a suitable
- * id. It scans list of devices to build up a free map, then chooses
- * the first empty slot. The caller must hold the dev_base or rtnl lock
- * while allocating the name and adding the device in order to avoid
- * duplicates.
- * Limited to bits_per_byte * page size devices (ie 32K on most platforms).
- * Returns the number of the unit assigned or a negative errno code.
- */
- int dev_alloc_name(struct net_device *dev, const char *name)
- {
- return dev_alloc_name_ns(dev_net(dev), dev, name);
- }
- EXPORT_SYMBOL(dev_alloc_name);
- static int dev_get_valid_name(struct net *net, struct net_device *dev,
- const char *name)
- {
- BUG_ON(!net);
- if (!dev_valid_name(name))
- return -EINVAL;
- if (strchr(name, '%'))
- return dev_alloc_name_ns(net, dev, name);
- else if (__dev_get_by_name(net, name))
- return -EEXIST;
- else if (dev->name != name)
- strlcpy(dev->name, name, IFNAMSIZ);
- return 0;
- }
- /**
- * dev_change_name - change name of a device
- * @dev: device
- * @newname: name (or format string) must be at least IFNAMSIZ
- *
- * Change name of a device, can pass format strings "eth%d".
- * for wildcarding.
- */
- int dev_change_name(struct net_device *dev, const char *newname)
- {
- unsigned char old_assign_type;
- char oldname[IFNAMSIZ];
- int err = 0;
- int ret;
- struct net *net;
- ASSERT_RTNL();
- BUG_ON(!dev_net(dev));
- net = dev_net(dev);
- /* Some auto-enslaved devices e.g. failover slaves are
- * special, as userspace might rename the device after
- * the interface had been brought up and running since
- * the point kernel initiated auto-enslavement. Allow
- * live name change even when these slave devices are
- * up and running.
- *
- * Typically, users of these auto-enslaving devices
- * don't actually care about slave name change, as
- * they are supposed to operate on master interface
- * directly.
- */
- if (dev->flags & IFF_UP &&
- likely(!(dev->priv_flags & IFF_LIVE_RENAME_OK)))
- return -EBUSY;
- write_seqcount_begin(&devnet_rename_seq);
- if (strncmp(newname, dev->name, IFNAMSIZ) == 0) {
- write_seqcount_end(&devnet_rename_seq);
- return 0;
- }
- memcpy(oldname, dev->name, IFNAMSIZ);
- err = dev_get_valid_name(net, dev, newname);
- if (err < 0) {
- write_seqcount_end(&devnet_rename_seq);
- return err;
- }
- if (oldname[0] && !strchr(oldname, '%'))
- netdev_info(dev, "renamed from %s\n", oldname);
- old_assign_type = dev->name_assign_type;
- dev->name_assign_type = NET_NAME_RENAMED;
- rollback:
- ret = device_rename(&dev->dev, dev->name);
- if (ret) {
- memcpy(dev->name, oldname, IFNAMSIZ);
- dev->name_assign_type = old_assign_type;
- write_seqcount_end(&devnet_rename_seq);
- return ret;
- }
- write_seqcount_end(&devnet_rename_seq);
- netdev_adjacent_rename_links(dev, oldname);
- write_lock_bh(&dev_base_lock);
- netdev_name_node_del(dev->name_node);
- write_unlock_bh(&dev_base_lock);
- synchronize_rcu();
- write_lock_bh(&dev_base_lock);
- netdev_name_node_add(net, dev->name_node);
- write_unlock_bh(&dev_base_lock);
- ret = call_netdevice_notifiers(NETDEV_CHANGENAME, dev);
- ret = notifier_to_errno(ret);
- if (ret) {
- /* err >= 0 after dev_alloc_name() or stores the first errno */
- if (err >= 0) {
- err = ret;
- write_seqcount_begin(&devnet_rename_seq);
- memcpy(dev->name, oldname, IFNAMSIZ);
- memcpy(oldname, newname, IFNAMSIZ);
- dev->name_assign_type = old_assign_type;
- old_assign_type = NET_NAME_RENAMED;
- goto rollback;
- } else {
- pr_err("%s: name change rollback failed: %d\n",
- dev->name, ret);
- }
- }
- return err;
- }
- /**
- * dev_set_alias - change ifalias of a device
- * @dev: device
- * @alias: name up to IFALIASZ
- * @len: limit of bytes to copy from info
- *
- * Set ifalias for a device,
- */
- int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
- {
- struct dev_ifalias *new_alias = NULL;
- if (len >= IFALIASZ)
- return -EINVAL;
- if (len) {
- new_alias = kmalloc(sizeof(*new_alias) + len + 1, GFP_KERNEL);
- if (!new_alias)
- return -ENOMEM;
- memcpy(new_alias->ifalias, alias, len);
- new_alias->ifalias[len] = 0;
- }
- mutex_lock(&ifalias_mutex);
- new_alias = rcu_replace_pointer(dev->ifalias, new_alias,
- mutex_is_locked(&ifalias_mutex));
- mutex_unlock(&ifalias_mutex);
- if (new_alias)
- kfree_rcu(new_alias, rcuhead);
- return len;
- }
- EXPORT_SYMBOL(dev_set_alias);
- /**
- * dev_get_alias - get ifalias of a device
- * @dev: device
- * @name: buffer to store name of ifalias
- * @len: size of buffer
- *
- * get ifalias for a device. Caller must make sure dev cannot go
- * away, e.g. rcu read lock or own a reference count to device.
- */
- int dev_get_alias(const struct net_device *dev, char *name, size_t len)
- {
- const struct dev_ifalias *alias;
- int ret = 0;
- rcu_read_lock();
- alias = rcu_dereference(dev->ifalias);
- if (alias)
- ret = snprintf(name, len, "%s", alias->ifalias);
- rcu_read_unlock();
- return ret;
- }
- /**
- * netdev_features_change - device changes features
- * @dev: device to cause notification
- *
- * Called to indicate a device has changed features.
- */
- void netdev_features_change(struct net_device *dev)
- {
- call_netdevice_notifiers(NETDEV_FEAT_CHANGE, dev);
- }
- EXPORT_SYMBOL(netdev_features_change);
- /**
- * netdev_state_change - device changes state
- * @dev: device to cause notification
- *
- * Called to indicate a device has changed state. This function calls
- * the notifier chains for netdev_chain and sends a NEWLINK message
- * to the routing socket.
- */
- void netdev_state_change(struct net_device *dev)
- {
- if (dev->flags & IFF_UP) {
- struct netdev_notifier_change_info change_info = {
- .info.dev = dev,
- };
- call_netdevice_notifiers_info(NETDEV_CHANGE,
- &change_info.info);
- rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL);
- }
- }
- EXPORT_SYMBOL(netdev_state_change);
- /**
- * netdev_notify_peers - notify network peers about existence of @dev
- * @dev: network device
- *
- * Generate traffic such that interested network peers are aware of
- * @dev, such as by generating a gratuitous ARP. This may be used when
- * a device wants to inform the rest of the network about some sort of
- * reconfiguration such as a failover event or virtual machine
- * migration.
- */
- void netdev_notify_peers(struct net_device *dev)
- {
- rtnl_lock();
- call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev);
- call_netdevice_notifiers(NETDEV_RESEND_IGMP, dev);
- rtnl_unlock();
- }
- EXPORT_SYMBOL(netdev_notify_peers);
- static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack)
- {
- const struct net_device_ops *ops = dev->netdev_ops;
- int ret;
- ASSERT_RTNL();
- if (!netif_device_present(dev))
- return -ENODEV;
- /* Block netpoll from trying to do any rx path servicing.
- * If we don't do this there is a chance ndo_poll_controller
- * or ndo_poll may be running while we open the device
- */
- netpoll_poll_disable(dev);
- ret = call_netdevice_notifiers_extack(NETDEV_PRE_UP, dev, extack);
- ret = notifier_to_errno(ret);
- if (ret)
- return ret;
- set_bit(__LINK_STATE_START, &dev->state);
- if (ops->ndo_validate_addr)
- ret = ops->ndo_validate_addr(dev);
- if (!ret && ops->ndo_open)
- ret = ops->ndo_open(dev);
- netpoll_poll_enable(dev);
- if (ret)
- clear_bit(__LINK_STATE_START, &dev->state);
- else {
- dev->flags |= IFF_UP;
- dev_set_rx_mode(dev);
- dev_activate(dev);
- add_device_randomness(dev->dev_addr, dev->addr_len);
- }
- return ret;
- }
- /**
- * dev_open - prepare an interface for use.
- * @dev: device to open
- * @extack: netlink extended ack
- *
- * Takes a device from down to up state. The device's private open
- * function is invoked and then the multicast lists are loaded. Finally
- * the device is moved into the up state and a %NETDEV_UP message is
- * sent to the netdev notifier chain.
- *
- * Calling this function on an active interface is a nop. On a failure
- * a negative errno code is returned.
- */
- int dev_open(struct net_device *dev, struct netlink_ext_ack *extack)
- {
- int ret;
- if (dev->flags & IFF_UP)
- return 0;
- ret = __dev_open(dev, extack);
- if (ret < 0)
- return ret;
- rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING, GFP_KERNEL);
- call_netdevice_notifiers(NETDEV_UP, dev);
- return ret;
- }
- EXPORT_SYMBOL(dev_open);
- static void __dev_close_many(struct list_head *head)
- {
- struct net_device *dev;
- ASSERT_RTNL();
- might_sleep();
- list_for_each_entry(dev, head, close_list) {
- /* Temporarily disable netpoll until the interface is down */
- netpoll_poll_disable(dev);
- call_netdevice_notifiers(NETDEV_GOING_DOWN, dev);
- clear_bit(__LINK_STATE_START, &dev->state);
- /* Synchronize to scheduled poll. We cannot touch poll list, it
- * can be even on different cpu. So just clear netif_running().
- *
- * dev->stop() will invoke napi_disable() on all of it's
- * napi_struct instances on this device.
- */
- smp_mb__after_atomic(); /* Commit netif_running(). */
- }
- dev_deactivate_many(head);
- list_for_each_entry(dev, head, close_list) {
- const struct net_device_ops *ops = dev->netdev_ops;
- /*
- * Call the device specific close. This cannot fail.
- * Only if device is UP
- *
- * We allow it to be called even after a DETACH hot-plug
- * event.
- */
- if (ops->ndo_stop)
- ops->ndo_stop(dev);
- dev->flags &= ~IFF_UP;
- netpoll_poll_enable(dev);
- }
- }
- static void __dev_close(struct net_device *dev)
- {
- LIST_HEAD(single);
- list_add(&dev->close_list, &single);
- __dev_close_many(&single);
- list_del(&single);
- }
- void dev_close_many(struct list_head *head, bool unlink)
- {
- struct net_device *dev, *tmp;
- /* Remove the devices that don't need to be closed */
- list_for_each_entry_safe(dev, tmp, head, close_list)
- if (!(dev->flags & IFF_UP))
- list_del_init(&dev->close_list);
- __dev_close_many(head);
- list_for_each_entry_safe(dev, tmp, head, close_list) {
- rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING, GFP_KERNEL);
- call_netdevice_notifiers(NETDEV_DOWN, dev);
- if (unlink)
- list_del_init(&dev->close_list);
- }
- }
- EXPORT_SYMBOL(dev_close_many);
- /**
- * dev_close - shutdown an interface.
- * @dev: device to shutdown
- *
- * This function moves an active device into down state. A
- * %NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device
- * is then deactivated and finally a %NETDEV_DOWN is sent to the notifier
- * chain.
- */
- void dev_close(struct net_device *dev)
- {
- if (dev->flags & IFF_UP) {
- LIST_HEAD(single);
- list_add(&dev->close_list, &single);
- dev_close_many(&single, true);
- list_del(&single);
- }
- }
- EXPORT_SYMBOL(dev_close);
- /**
- * dev_disable_lro - disable Large Receive Offload on a device
- * @dev: device
- *
- * Disable Large Receive Offload (LRO) on a net device. Must be
- * called under RTNL. This is needed if received packets may be
- * forwarded to another interface.
- */
- void dev_disable_lro(struct net_device *dev)
- {
- struct net_device *lower_dev;
- struct list_head *iter;
- dev->wanted_features &= ~NETIF_F_LRO;
- netdev_update_features(dev);
- if (unlikely(dev->features & NETIF_F_LRO))
- netdev_WARN(dev, "failed to disable LRO!\n");
- netdev_for_each_lower_dev(dev, lower_dev, iter)
- dev_disable_lro(lower_dev);
- }
- EXPORT_SYMBOL(dev_disable_lro);
- /**
- * dev_disable_gro_hw - disable HW Generic Receive Offload on a device
- * @dev: device
- *
- * Disable HW Generic Receive Offload (GRO_HW) on a net device. Must be
- * called under RTNL. This is needed if Generic XDP is installed on
- * the device.
- */
- static void dev_disable_gro_hw(struct net_device *dev)
- {
- dev->wanted_features &= ~NETIF_F_GRO_HW;
- netdev_update_features(dev);
- if (unlikely(dev->features & NETIF_F_GRO_HW))
- netdev_WARN(dev, "failed to disable GRO_HW!\n");
- }
- const char *netdev_cmd_to_name(enum netdev_cmd cmd)
- {
- #define N(val) \
- case NETDEV_##val: \
- return "NETDEV_" __stringify(val);
- switch (cmd) {
- N(UP) N(DOWN) N(REBOOT) N(CHANGE) N(REGISTER) N(UNREGISTER)
- N(CHANGEMTU) N(CHANGEADDR) N(GOING_DOWN) N(CHANGENAME) N(FEAT_CHANGE)
- N(BONDING_FAILOVER) N(PRE_UP) N(PRE_TYPE_CHANGE) N(POST_TYPE_CHANGE)
- N(POST_INIT) N(RELEASE) N(NOTIFY_PEERS) N(JOIN) N(CHANGEUPPER)
- N(RESEND_IGMP) N(PRECHANGEMTU) N(CHANGEINFODATA) N(BONDING_INFO)
- N(PRECHANGEUPPER) N(CHANGELOWERSTATE) N(UDP_TUNNEL_PUSH_INFO)
- N(UDP_TUNNEL_DROP_INFO) N(CHANGE_TX_QUEUE_LEN)
- N(CVLAN_FILTER_PUSH_INFO) N(CVLAN_FILTER_DROP_INFO)
- N(SVLAN_FILTER_PUSH_INFO) N(SVLAN_FILTER_DROP_INFO)
- N(PRE_CHANGEADDR)
- }
- #undef N
- return "UNKNOWN_NETDEV_EVENT";
- }
- EXPORT_SYMBOL_GPL(netdev_cmd_to_name);
- static int call_netdevice_notifier(struct notifier_block *nb, unsigned long val,
- struct net_device *dev)
- {
- struct netdev_notifier_info info = {
- .dev = dev,
- };
- return nb->notifier_call(nb, val, &info);
- }
- static int call_netdevice_register_notifiers(struct notifier_block *nb,
- struct net_device *dev)
- {
- int err;
- err = call_netdevice_notifier(nb, NETDEV_REGISTER, dev);
- err = notifier_to_errno(err);
- if (err)
- return err;
- if (!(dev->flags & IFF_UP))
- return 0;
- call_netdevice_notifier(nb, NETDEV_UP, dev);
- return 0;
- }
- static void call_netdevice_unregister_notifiers(struct notifier_block *nb,
- struct net_device *dev)
- {
- if (dev->flags & IFF_UP) {
- call_netdevice_notifier(nb, NETDEV_GOING_DOWN,
- dev);
- call_netdevice_notifier(nb, NETDEV_DOWN, dev);
- }
- call_netdevice_notifier(nb, NETDEV_UNREGISTER, dev);
- }
- static int call_netdevice_register_net_notifiers(struct notifier_block *nb,
- struct net *net)
- {
- struct net_device *dev;
- int err;
- for_each_netdev(net, dev) {
- err = call_netdevice_register_notifiers(nb, dev);
- if (err)
- goto rollback;
- }
- return 0;
- rollback:
- for_each_netdev_continue_reverse(net, dev)
- call_netdevice_unregister_notifiers(nb, dev);
- return err;
- }
- static void call_netdevice_unregister_net_notifiers(struct notifier_block *nb,
- struct net *net)
- {
- struct net_device *dev;
- for_each_netdev(net, dev)
- call_netdevice_unregister_notifiers(nb, dev);
- }
- static int dev_boot_phase = 1;
- /**
- * register_netdevice_notifier - register a network notifier block
- * @nb: notifier
- *
- * Register a notifier to be called when network device events occur.
- * The notifier passed is linked into the kernel structures and must
- * not be reused until it has been unregistered. A negative errno code
- * is returned on a failure.
- *
- * When registered all registration and up events are replayed
- * to the new notifier to allow device to have a race free
- * view of the network device list.
- */
- int register_netdevice_notifier(struct notifier_block *nb)
- {
- struct net *net;
- int err;
- /* Close race with setup_net() and cleanup_net() */
- down_write(&pernet_ops_rwsem);
- rtnl_lock();
- err = raw_notifier_chain_register(&netdev_chain, nb);
- if (err)
- goto unlock;
- if (dev_boot_phase)
- goto unlock;
- for_each_net(net) {
- err = call_netdevice_register_net_notifiers(nb, net);
- if (err)
- goto rollback;
- }
- unlock:
- rtnl_unlock();
- up_write(&pernet_ops_rwsem);
- return err;
- rollback:
- for_each_net_continue_reverse(net)
- call_netdevice_unregister_net_notifiers(nb, net);
- raw_notifier_chain_unregister(&netdev_chain, nb);
- goto unlock;
- }
- EXPORT_SYMBOL(register_netdevice_notifier);
- /**
- * unregister_netdevice_notifier - unregister a network notifier block
- * @nb: notifier
- *
- * Unregister a notifier previously registered by
- * register_netdevice_notifier(). The notifier is unlinked into the
- * kernel structures and may then be reused. A negative errno code
- * is returned on a failure.
- *
- * After unregistering unregister and down device events are synthesized
- * for all devices on the device list to the removed notifier to remove
- * the need for special case cleanup code.
- */
- int unregister_netdevice_notifier(struct notifier_block *nb)
- {
- struct net *net;
- int err;
- /* Close race with setup_net() and cleanup_net() */
- down_write(&pernet_ops_rwsem);
- rtnl_lock();
- err = raw_notifier_chain_unregister(&netdev_chain, nb);
- if (err)
- goto unlock;
- for_each_net(net)
- call_netdevice_unregister_net_notifiers(nb, net);
- unlock:
- rtnl_unlock();
- up_write(&pernet_ops_rwsem);
- return err;
- }
- EXPORT_SYMBOL(unregister_netdevice_notifier);
- static int __register_netdevice_notifier_net(struct net *net,
- struct notifier_block *nb,
- bool ignore_call_fail)
- {
- int err;
- err = raw_notifier_chain_register(&net->netdev_chain, nb);
- if (err)
- return err;
- if (dev_boot_phase)
- return 0;
- err = call_netdevice_register_net_notifiers(nb, net);
- if (err && !ignore_call_fail)
- goto chain_unregister;
- return 0;
- chain_unregister:
- raw_notifier_chain_unregister(&net->netdev_chain, nb);
- return err;
- }
- static int __unregister_netdevice_notifier_net(struct net *net,
- struct notifier_block *nb)
- {
- int err;
- err = raw_notifier_chain_unregister(&net->netdev_chain, nb);
- if (err)
- return err;
- call_netdevice_unregister_net_notifiers(nb, net);
- return 0;
- }
- /**
- * register_netdevice_notifier_net - register a per-netns network notifier block
- * @net: network namespace
- * @nb: notifier
- *
- * Register a notifier to be called when network device events occur.
- * The notifier passed is linked into the kernel structures and must
- * not be reused until it has been unregistered. A negative errno code
- * is returned on a failure.
- *
- * When registered all registration and up events are replayed
- * to the new notifier to allow device to have a race free
- * view of the network device list.
- */
- int register_netdevice_notifier_net(struct net *net, struct notifier_block *nb)
- {
- int err;
- rtnl_lock();
- err = __register_netdevice_notifier_net(net, nb, false);
- rtnl_unlock();
- return err;
- }
- EXPORT_SYMBOL(register_netdevice_notifier_net);
- /**
- * unregister_netdevice_notifier_net - unregister a per-netns
- * network notifier block
- * @net: network namespace
- * @nb: notifier
- *
- * Unregister a notifier previously registered by
- * register_netdevice_notifier(). The notifier is unlinked into the
- * kernel structures and may then be reused. A negative errno code
- * is returned on a failure.
- *
- * After unregistering unregister and down device events are synthesized
- * for all devices on the device list to the removed notifier to remove
- * the need for special case cleanup code.
- */
- int unregister_netdevice_notifier…