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

📄 dev.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 */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_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 hlist_node *p;	hlist_for_each(p, dev_name_hash(net, name)) {		struct net_device *dev			= hlist_entry(p, struct net_device, name_hlist);		if (!strncmp(dev->name, name, IFNAMSIZ))			return dev;	}	return NULL;}/** *	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;	read_lock(&dev_base_lock);	dev = __dev_get_by_name(net, name);	if (dev)		dev_hold(dev);	read_unlock(&dev_base_lock);	return dev;}/** *	__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 hlist_node *p;	hlist_for_each(p, dev_index_hash(net, ifindex)) {		struct net_device *dev			= hlist_entry(p, struct net_device, index_hlist);		if (dev->ifindex == ifindex)			return dev;	}	return NULL;}/** *	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;	read_lock(&dev_base_lock);	dev = __dev_get_by_index(net, ifindex);	if (dev)		dev_hold(dev);	read_unlock(&dev_base_lock);	return dev;}/** *	dev_getbyhwaddr - 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 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(struct net *net, unsigned short type, char *ha){	struct net_device *dev;	ASSERT_RTNL();	for_each_netdev(&init_net, dev)		if (dev->type == type &&		    !memcmp(dev->dev_addr, ha, dev->addr_len))			return dev;	return NULL;}EXPORT_SYMBOL(dev_getbyhwaddr);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;	rtnl_lock();	dev = __dev_getfirstbyhwtype(net, type);	if (dev)		dev_hold(dev);	rtnl_unlock();	return dev;}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. 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_flags(struct net *net, unsigned short if_flags, unsigned short mask){	struct net_device *dev, *ret;	ret = NULL;	read_lock(&dev_base_lock);	for_each_netdev(net, dev) {		if (((dev->flags ^ if_flags) & mask) == 0) {			dev_hold(dev);			ret = dev;			break;		}	}	read_unlock(&dev_base_lock);	return ret;}/** *	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. */int dev_valid_name(const char *name){	if (*name == '\0')		return 0;	if (strlen(name) >= IFNAMSIZ)		return 0;	if (!strcmp(name, ".") || !strcmp(name, ".."))		return 0;	while (*name) {		if (*name == '/' || isspace(*name))			return 0;		name++;	}	return 1;}/** *	__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;	p = strnchr(name, IFNAMSIZ-1, '%');	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;}/** *	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){	char buf[IFNAMSIZ];	struct net *net;	int ret;	BUG_ON(!dev->nd_net);	net = dev->nd_net;	ret = __dev_alloc_name(net, name, buf);	if (ret >= 0)		strlcpy(dev->name, buf, IFNAMSIZ);	return ret;}/** *	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, char *newname){	char oldname[IFNAMSIZ];	int err = 0;	int ret;	struct net *net;	ASSERT_RTNL();	BUG_ON(!dev->nd_net);	net = dev->nd_net;	if (dev->flags & IFF_UP)		return -EBUSY;	if (!dev_valid_name(newname))		return -EINVAL;	if (strncmp(newname, dev->name, IFNAMSIZ) == 0)		return 0;	memcpy(oldname, dev->name, IFNAMSIZ);	if (strchr(newname, '%')) {		err = dev_alloc_name(dev, newname);		if (err < 0)			return err;		strcpy(newname, dev->name);	}	else if (__dev_get_by_name(net, newname))		return -EEXIST;	else		strlcpy(dev->name, newname, IFNAMSIZ);rollback:	device_rename(&dev->dev, dev->name);	write_lock_bh(&dev_base_lock);	hlist_del(&dev->name_hlist);	hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name));	write_unlock_bh(&dev_base_lock);	ret = call_netdevice_notifiers(NETDEV_CHANGENAME, dev);	ret = notifier_to_errno(ret);	if (ret) {		if (err) {			printk(KERN_ERR			       "%s: name change rollback failed: %d.\n",			       dev->name, ret);		} else {			err = ret;			memcpy(dev->name, oldname, IFNAMSIZ);			goto rollback;		}	}	return err;}/** *	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) {		call_netdevice_notifiers(NETDEV_CHANGE, dev);		rtmsg_ifinfo(RTM_NEWLINK, dev, 0);	}}/** *	dev_load 	- load a network module *	@net: the applicable net namespace *	@name: name of interface * *	If a network interface is not present and the process has suitable *	privileges this function loads the module. If module loading is not *	available in this kernel then it becomes a nop. */void dev_load(struct net *net, const char *name){	struct net_device *dev;	read_lock(&dev_base_lock);	dev = __dev_get_by_name(net, name);	read_unlock(&dev_base_lock);	if (!dev && capable(CAP_SYS_MODULE))		request_module("%s", name);}/** *	dev_open	- prepare an interface for use. *	@dev:	device to open * *	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){	int ret = 0;	/*	 *	Is it already up?	 */	if (dev->flags & IFF_UP)		return 0;	/*	 *	Is it even present?	 */	if (!netif_device_present(dev))		return -ENODEV;	/*	 *	Call device private open method	 */	set_bit(__LINK_STATE_START, &dev->state);	if (dev->validate_addr)		ret = dev->validate_addr(dev);	if (!ret && dev->open)		ret = dev->open(dev);	/*	 *	If it went open OK then:	 */	if (ret)		clear_bit(__LINK_STATE_START, &dev->state);	else {		/*		 *	Set the flags.		 */		dev->flags |= IFF_UP;		/*		 *	Initialize multicasting status		 */		dev_set_rx_mode(dev);		/*		 *	Wakeup transmit queue engine		 */		dev_activate(dev);		/*		 *	... and announce new interface.		 */		call_netdevice_notifiers(NETDEV_UP, dev);	}

⌨️ 快捷键说明

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