cregit-Linux how code gets into the kernel

Release 4.11 net/core/dev.c

Directory: net/core
/*
 *      NET3    Protocol independent device support routines.
 *
 *              This program is free software; you can redistribute it and/or
 *              modify it under the terms of the GNU General Public License
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 *
 *      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/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/notifier.h>
#include <linux/skbuff.h>
#include <linux/bpf.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/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/pci.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 "net-sysfs.h"

/* Instead of increasing this, you should create a hash table. */

#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 net_device *dev,
					 struct netdev_notifier_info *info);

/*
 * 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);

/* 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) ; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf22100.00%1100.00%
Total22100.00%1100.00%


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)]; }

Contributors

PersonTokensPropCommitsCommitProp
Stephen Hemminger4180.39%240.00%
Eric W. Biedermann713.73%120.00%
Linus Torvalds23.92%120.00%
Eric Dumazet11.96%120.00%
Total51100.00%5100.00%


static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) { return &net->dev_index_head[ifindex & (NETDEV_HASHENTRIES - 1)]; }

Contributors

PersonTokensPropCommitsCommitProp
Stephen Hemminger2475.00%133.33%
Eric W. Biedermann721.88%133.33%
Eric Dumazet13.12%133.33%
Total32100.00%3100.00%


static inline void rps_lock(struct softnet_data *sd) { #ifdef CONFIG_RPS spin_lock(&sd->input_pkt_queue.lock); #endif }

Contributors

PersonTokensPropCommitsCommitProp
Changli Gao2592.59%150.00%
Eric Dumazet27.41%150.00%
Total27100.00%2100.00%


static inline void rps_unlock(struct softnet_data *sd) { #ifdef CONFIG_RPS spin_unlock(&sd->input_pkt_queue.lock); #endif }

Contributors

PersonTokensPropCommitsCommitProp
Changli Gao2592.59%150.00%
Eric Dumazet27.41%150.00%
Total27100.00%2100.00%

/* 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); hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name)); hlist_add_head_rcu(&dev->index_hlist, dev_index_hash(net, dev->ifindex)); write_unlock_bh(&dev_base_lock); dev_base_seq_inc(net); }

Contributors

PersonTokensPropCommitsCommitProp
Eric W. Biedermann7686.36%114.29%
Thomas Graf55.68%114.29%
Eric Dumazet33.41%342.86%
Hideaki Yoshifuji / 吉藤英明33.41%114.29%
Ding Tianhong11.14%114.29%
Total88100.00%7100.00%

/* 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); hlist_del_rcu(&dev->name_hlist); hlist_del_rcu(&dev->index_hlist); write_unlock_bh(&dev_base_lock); dev_base_seq_inc(dev_net(dev)); }

Contributors

PersonTokensPropCommitsCommitProp
Eric W. Biedermann4881.36%120.00%
Thomas Graf813.56%120.00%
Eric Dumazet35.08%360.00%
Total59100.00%5100.00%

/* * 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); #ifdef CONFIG_LOCKDEP /* * register_netdevice() inits txq->_xmit_lock and sets lockdep class * according to dev->type */ static const unsigned short netdev_lock_type[] = { ARPHRD_NETROM, ARPHRD_ETHER, ARPHRD_EETHER, ARPHRD_AX25, ARPHRD_PRONET, ARPHRD_CHAOS, ARPHRD_IEEE802, ARPHRD_ARCNET, ARPHRD_APPLETLK, ARPHRD_DLCI, ARPHRD_ATM, ARPHRD_METRICOM, ARPHRD_IEEE1394, ARPHRD_EUI64, ARPHRD_INFINIBAND, ARPHRD_SLIP, ARPHRD_CSLIP, ARPHRD_SLIP6, ARPHRD_CSLIP6, ARPHRD_RSRVD, ARPHRD_ADAPT, ARPHRD_ROSE, ARPHRD_X25, ARPHRD_HWX25, ARPHRD_PPP, ARPHRD_CISCO, ARPHRD_LAPB, ARPHRD_DDCMP, ARPHRD_RAWHDLC, ARPHRD_TUNNEL, ARPHRD_TUNNEL6, ARPHRD_FRAD, ARPHRD_SKIP, ARPHRD_LOOPBACK, ARPHRD_LOCALTLK, ARPHRD_FDDI, ARPHRD_BIF, ARPHRD_SIT, ARPHRD_IPDDP, ARPHRD_IPGRE, ARPHRD_PIMREG, ARPHRD_HIPPI, ARPHRD_ASH, ARPHRD_ECONET, ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, ARPHRD_FCFABRIC, ARPHRD_IEEE80211, ARPHRD_IEEE80211_PRISM, ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET, ARPHRD_PHONET_PIPE, ARPHRD_IEEE802154, ARPHRD_VOID, ARPHRD_NONE}; static const char *const netdev_lock_name[] = { "_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25", "_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET", "_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM", "_xmit_IEEE1394", "_xmit_EUI64", "_xmit_INFINIBAND", "_xmit_SLIP", "_xmit_CSLIP", "_xmit_SLIP6", "_xmit_CSLIP6", "_xmit_RSRVD", "_xmit_ADAPT", "_xmit_ROSE", "_xmit_X25", "_xmit_HWX25", "_xmit_PPP", "_xmit_CISCO", "_xmit_LAPB", "_xmit_DDCMP", "_xmit_RAWHDLC", "_xmit_TUNNEL", "_xmit_TUNNEL6", "_xmit_FRAD", "_xmit_SKIP", "_xmit_LOOPBACK", "_xmit_LOCALTLK", "_xmit_FDDI", "_xmit_BIF", "_xmit_SIT", "_xmit_IPDDP", "_xmit_IPGRE", "_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET", "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL", "_xmit_FCFABRIC", "_xmit_IEEE80211", "_xmit_IEEE80211_PRISM", "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET", "_xmit_PHONET_PIPE", "_xmit_IEEE802154", "_xmit_VOID", "_xmit_NONE"}; static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)]; static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)];
static inline unsigned short netdev_lock_pos(unsigned short dev_type) { int i; for (i = 0; i < ARRAY_SIZE(netdev_lock_type); i++) if (netdev_lock_type[i] == dev_type) return i; /* the last key is used by default */ return ARRAY_SIZE(netdev_lock_type) - 1; }

Contributors

PersonTokensPropCommitsCommitProp
Jarek Poplawski52100.00%1100.00%
Total52100.00%1100.00%


static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock, unsigned short dev_type) { int i; i = netdev_lock_pos(dev_type); lockdep_set_class_and_name(lock, &netdev_xmit_lock_key[i], netdev_lock_name[i]); }

Contributors

PersonTokensPropCommitsCommitProp
Jarek Poplawski4097.56%150.00%
David S. Miller12.44%150.00%
Total41100.00%2100.00%


static inline void netdev_set_addr_lockdep_class(struct net_device *dev) { int i; i = netdev_lock_pos(dev->type); lockdep_set_class_and_name(&dev->addr_list_lock, &netdev_addr_lock_key[i], netdev_lock_name[i]); }

Contributors

PersonTokensPropCommitsCommitProp
David S. Miller43100.00%1100.00%
Total43100.00%1100.00%

#else
static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock, unsigned short dev_type) { }

Contributors

PersonTokensPropCommitsCommitProp
Jarek Poplawski1392.86%150.00%
David S. Miller17.14%150.00%
Total14100.00%2100.00%


static inline void netdev_set_addr_lockdep_class(struct net_device *dev) { }

Contributors

PersonTokensPropCommitsCommitProp
David S. Miller11100.00%1100.00%
Total11100.00%1100.00%

#endif /******************************************************************************* * * 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]; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2740.30%555.56%
Salam Noureddine2232.84%111.11%
Eric Dumazet1623.88%111.11%
Pavel Emelyanov11.49%111.11%
Stephen Hemminger11.49%111.11%
Total67100.00%9100.00%

/** * 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); }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet2661.90%120.00%
Linus Torvalds (pre-git)819.05%360.00%
Stephen Hemminger819.05%120.00%
Total42100.00%5100.00%

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); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3141.33%660.00%
Stephen Hemminger3040.00%110.00%
Eric Dumazet79.33%110.00%
Arnaldo Carvalho de Melo56.67%110.00%
Joe Perches22.67%110.00%
Total75100.00%10100.00%

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(); }

Contributors

PersonTokensPropCommitsCommitProp
Stephen Hemminger1477.78%133.33%
Arnaldo Carvalho de Melo316.67%133.33%
Linus Torvalds (pre-git)15.56%133.33%
Total18100.00%3100.00%

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); }

Contributors

PersonTokensPropCommitsCommitProp
Vlad Yasevich3454.84%150.00%
David S. Miller2845.16%150.00%
Total62100.00%2100.00%

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); }

Contributors

PersonTokensPropCommitsCommitProp
Vlad Yasevich7195.95%133.33%
Eric Dumazet22.70%133.33%
Stephen Hemminger11.35%133.33%
Total74100.00%3100.00%

/** * 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(); }

Contributors

PersonTokensPropCommitsCommitProp
Vlad Yasevich18100.00%1100.00%
Total18100.00%1100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)13294.96%125.00%
Arnaldo Carvalho de Melo32.16%125.00%
Wang Chen32.16%125.00%
Adrian Bunk10.72%125.00%
Total139100.00%4100.00%

/** * 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; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)13397.79%250.00%
Arnaldo Carvalho de Melo21.47%125.00%
Wang Chen10.74%125.00%
Total136100.00%4100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Stephen Hemminger9496.91%266.67%
Eric W. Biedermann33.09%133.33%
Total97100.00%3100.00%

/* * 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); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)14199.30%150.00%
Linus Torvalds10.70%150.00%
Total142100.00%2100.00%

__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; }

Contributors

PersonTokensPropCommitsCommitProp
Nicolas Dichtel38100.00%2100.00%
Total38100.00%2100.00%

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); }

Contributors

PersonTokensPropCommitsCommitProp
Pravin B Shelar84100.00%1100.00%
Total84100.00%1100.00%

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 net_device *dev; struct hlist_head *head = dev_name_hash(net, name); hlist_for_each_entry(dev, head, name_hlist) if (!strncmp(dev->name, name, IFNAMSIZ)) return dev; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2946.77%758.33%
Eric Dumazet1625.81%18.33%
Stephen Hemminger812.90%18.33%
Eric W. Biedermann58.06%18.33%
Linus Torvalds34.84%18.33%
Arnaldo Carvalho de Melo11.61%18.33%
Total62100.00%12100.00%

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 net_device *dev; struct hlist_head *head = dev_name_hash(net, name); hlist_for_each_entry_rcu(dev, head, name_hlist) if (!strncmp(dev->name, name, IFNAMSIZ)) return dev; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet62100.00%1100.00%
Total62100.00%1100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3775.51%360.00%
Eric W. Biedermann714.29%120.00%
Eric Dumazet510.20%120.00%
Total49100.00%5100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2546.30%240.00%
Eric Dumazet1629.63%120.00%
Stephen Hemminger814.81%120.00%
Eric W. Biedermann59.26%120.00%
Total54100.00%5100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Eric Dumazet54100.00%1100.00%
Total54100.00%1100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3574.47%360.00%
Eric W. Biedermann714.89%120.00%
Eric Dumazet510.64%120.00%
Total47100.00%5100.00%

EXPORT_SYMBOL(dev_get_by_index); /** * 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_PREEMPT 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; }

Contributors

PersonTokensPropCommitsCommitProp
Nicolas Schichan95100.00%1100.00%
Total95100.00%1100.00%

/** * 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; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4371.67%337.50%
Pavel Emelyanov610.00%112.50%
Eric W. Biedermann610.00%112.50%
Eric Dumazet35.00%112.50%
Denis V. Lunev11.67%112.50%
Arnaldo Carvalho de Melo11.67%112.50%
Total60100.00%8100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Arnaldo Carvalho de Melo2250.00%120.00%
Eric W. Biedermann715.91%120.00%
Pavel Emelyanov715.91%120.00%
Patrick McHardy613.64%120.00%
Christoph Hellwig24.55%120.00%
Total44100.00%5100.00%

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; }

Contributors

PersonTokensPropCommitsCommitProp
Patrick McHardy2236.07%125.00%
Eric Dumazet2236.07%125.00%
Arnaldo Carvalho de Melo1118.03%125.00%
Eric W. Biedermann69.84%125.00%
Total61100.00%4100.00%

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;