⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dev.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 	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, <bir7@leland.Stanford.Edu> *				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 <dhinds@allegro.stanford.edu> *		Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> *		Adam Sulmicki <adam@cfar.umd.edu> *              Pekka Riikonen <priikone@poesidon.pspt.fi> * *	Changes: *		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 <asm/uaccess.h>#include <asm/system.h>#include <asm/bitops.h>#include <linux/config.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.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/notifier.h>#include <linux/skbuff.h>#include <linux/brlock.h>#include <net/sock.h>#include <linux/rtnetlink.h>#include <linux/proc_fs.h>#include <linux/stat.h>#include <linux/if_bridge.h>#include <linux/divert.h>#include <net/dst.h>#include <net/pkt_sched.h>#include <net/profile.h>#include <linux/init.h>#include <linux/kmod.h>#include <linux/module.h>#if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)#include <linux/wireless.h>		/* Note : will define WIRELESS_EXT */#endif	/* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */#ifdef CONFIG_PLIPextern int plip_init(void);#endif/* This define, if set, will randomly drop a packet when congestion * is more than moderate.  It helps fairness in the multi-interface * case when one of them is a hog, but it kills performance for the * single interface case so it is off now by default. */#undef RAND_LIE/* Setting this will sample the queue lengths and thus congestion * via a timer instead of as each packet is received. */#undef OFFLINE_SAMPLENET_PROFILE_DEFINE(dev_queue_xmit)NET_PROFILE_DEFINE(softnet_process)const char *if_port_text[] = {  "unknown",  "BNC",  "10baseT",  "AUI",  "100baseT",  "100baseTX",  "100baseFX"};/* *	The list of packet types we will receive (as opposed to discard) *	and the routines to invoke. * *	Why 16. Because with 16 the only overlap we get on a hash of the *	low nibble of the protocol value is RARP/SNAP/X.25.  * *		0800	IP *		0001	802.3 *		0002	AX.25 *		0004	802.2 *		8035	RARP *		0005	SNAP *		0805	X.25 *		0806	ARP *		8137	IPX *		0009	Localtalk *		86DD	IPv6 */static struct packet_type *ptype_base[16];		/* 16 way hashed list */static struct packet_type *ptype_all = NULL;		/* Taps */#ifdef OFFLINE_SAMPLEstatic void sample_queue(unsigned long dummy);static struct timer_list samp_timer = { function: sample_queue };#endif#ifdef CONFIG_HOTPLUGstatic int net_run_sbin_hotplug(struct net_device *dev, char *action);#else#define net_run_sbin_hotplug(dev, action) ({ 0; })#endif/* *	Our notifier list */ static struct notifier_block *netdev_chain=NULL;/* *	Device drivers call our routines to queue packets here. We empty the *	queue in the local softnet handler. */struct softnet_data softnet_data[NR_CPUS] __cacheline_aligned;#ifdef CONFIG_NET_FASTROUTEint netdev_fastroute;int netdev_fastroute_obstacles;#endif/******************************************************************************************		Protocol management and registration routines*******************************************************************************************//* *	For efficiency */int netdev_nit=0;/* *	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 promiscous ptype_all chain in net_bh. *	It is true now, do not change it. *	Explantion 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) *//** *	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. */ void dev_add_pack(struct packet_type *pt){	int hash;	br_write_lock_bh(BR_NETPROTO_LOCK);#ifdef CONFIG_NET_FASTROUTE	/* Hack to detect packet socket */	if (pt->data) {		netdev_fastroute_obstacles++;		dev_clear_fastroute(pt->dev);	}#endif	if (pt->type == htons(ETH_P_ALL)) {		netdev_nit++;		pt->next=ptype_all;		ptype_all=pt;	} else {		hash=ntohs(pt->type)&15;		pt->next = ptype_base[hash];		ptype_base[hash] = pt;	}	br_write_unlock_bh(BR_NETPROTO_LOCK);}/** *	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. */ void dev_remove_pack(struct packet_type *pt){	struct packet_type **pt1;	br_write_lock_bh(BR_NETPROTO_LOCK);	if (pt->type == htons(ETH_P_ALL)) {		netdev_nit--;		pt1=&ptype_all;	} else {		pt1=&ptype_base[ntohs(pt->type)&15];	}	for (; (*pt1) != NULL; pt1 = &((*pt1)->next)) {		if (pt == (*pt1)) {			*pt1 = pt->next;#ifdef CONFIG_NET_FASTROUTE			if (pt->data)				netdev_fastroute_obstacles--;#endif			br_write_unlock_bh(BR_NETPROTO_LOCK);			return;		}	}	br_write_unlock_bh(BR_NETPROTO_LOCK);	printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt);}/******************************************************************************		      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. */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));			strcpy(s[i].name, name);			memcpy(&s[i].map, map, sizeof(s[i].map));			break;		}	}	if (i >= NETDEV_BOOT_SETUP_MAX)		return 0;	return 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;	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] != ' ' &&		    !strncmp(dev->name, s[i].name, strlen(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;}/* * Saves at boot time configured settings for any netdevice. */static 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, -1, 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_by_name	- find a device by its name  *	@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(const char *name){	struct net_device *dev;	for (dev = dev_base; dev != NULL; dev = dev->next) {		if (strcmp(dev->name, name) == 0)			return dev;	}	return NULL;}/** *	dev_get_by_name		- find a device by its name *	@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(const char *name){	struct net_device *dev;	read_lock(&dev_base_lock);	dev = __dev_get_by_name(name);	if (dev)		dev_hold(dev);	read_unlock(&dev_base_lock);	return dev;}/*    Return value is changed to int to prevent illegal usage in future.   It is still legal to use to check for device existance.   User should understand, that the result returned by this function   is meaningless, if it was not issued under rtnl semaphore. *//** *	dev_get	-	test if a device exists *	@name:	name to test for * *	Test if a name exists. Returns true if the name is found. In order *	to be sure the name is not allocated or removed during the test the *	caller must hold the rtnl semaphore. * *	This function primarily exists for back compatibility with older *	drivers.  */ int dev_get(const char *name){	struct net_device *dev;	read_lock(&dev_base_lock);	dev = __dev_get_by_name(name);	read_unlock(&dev_base_lock);	return dev != NULL;}/** *	__dev_get_by_index - find a device by its ifindex *	@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(int ifindex){	struct net_device *dev;	for (dev = dev_base; dev != NULL; dev = dev->next) {		if (dev->ifindex == ifindex)			return dev;	}	return NULL;}/** *	dev_get_by_index - find a device by its ifindex *	@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(int ifindex){	struct net_device *dev;	read_lock(&dev_base_lock);	dev = __dev_get_by_index(ifindex);	if (dev)		dev_hold(dev);	read_unlock(&dev_base_lock);	return dev;}/** *	dev_getbyhwaddr - find a device by its hardware addres *	@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 the *	rtnl semaphore. The returned device has not had its ref count increased *	and the caller must therefore be careful about locking * *	BUGS: *	If the API was consistent this would be __dev_get_by_hwaddr */struct net_device *dev_getbyhwaddr(unsigned short type, char *ha){	struct net_device *dev;	ASSERT_RTNL();	for (dev = dev_base; dev != NULL; dev = dev->next) {		if (dev->type == type &&		    memcmp(dev->dev_addr, ha, dev->addr_len) == 0)			return dev;	}	return NULL;}/** *	dev_alloc_name - allocate a name for a device *	@dev: device 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -