📄 dev.c
字号:
* 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 exists only 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 hlist_node *p; hlist_for_each(p, dev_index_hash(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 * @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 address * @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; dev = dev->next) if (dev->type == type && !memcmp(dev->dev_addr, ha, dev->addr_len)) break; return dev;}struct net_device *__dev_getfirstbyhwtype(unsigned short type){ struct net_device *dev; for (dev = dev_base; dev; dev = dev->next) if (dev->type == type) break; return dev;}EXPORT_SYMBOL(__dev_getfirstbyhwtype);struct net_device *dev_getfirstbyhwtype(unsigned short type){ struct net_device *dev; rtnl_lock(); dev = __dev_getfirstbyhwtype(type); if (dev) dev_hold(dev); rtnl_unlock(); return dev;}EXPORT_SYMBOL(dev_getfirstbyhwtype);/** * dev_get_by_flags - find any device with given flags * @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(unsigned short if_flags, unsigned short mask){ struct net_device *dev; read_lock(&dev_base_lock); dev = __dev_get_by_flags(if_flags, mask); if (dev) dev_hold(dev); read_unlock(&dev_base_lock); return dev;}/** * __dev_get_by_flags - find any device with given flags * @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 caller must hold either * the RTNL semaphore or @dev_base_lock. */struct net_device *__dev_get_by_flags(unsigned short if_flags, unsigned short mask){ struct net_device *dev; for (dev = dev_base; dev != NULL; dev = dev->next) { if (((dev->flags ^ if_flags) & mask) == 0) return dev; } return NULL;}/** * 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 */int dev_valid_name(const char *name){ return !(*name == '\0' || !strcmp(name, ".") || !strcmp(name, "..") || strchr(name, '/'));}/** * 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. Not efficient for many devices, not called a lot. The caller * must hold the dev_base or rtnl lock while allocating the name and * adding the device in order to avoid duplicates. Returns the number * of the unit assigned or a negative errno code. */int dev_alloc_name(struct net_device *dev, const char *name){ int i = 0; char buf[IFNAMSIZ]; const char *p; const int max_netdevices = 8*PAGE_SIZE; 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 = (long *) get_zeroed_page(GFP_ATOMIC); if (!inuse) return -ENOMEM; for (d = dev_base; d; d = d->next) { 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, sizeof(buf), 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, sizeof(buf), name, i); if (!__dev_get_by_name(buf)) { strlcpy(dev->name, buf, IFNAMSIZ); 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_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){ int err = 0; ASSERT_RTNL(); if (dev->flags & IFF_UP) return -EBUSY; if (!dev_valid_name(newname)) return -EINVAL; if (strchr(newname, '%')) { err = dev_alloc_name(dev, newname); if (err < 0) return err; strcpy(newname, dev->name); } else if (__dev_get_by_name(newname)) return -EEXIST; else strlcpy(dev->name, newname, IFNAMSIZ); err = class_device_rename(&dev->class_dev, dev->name); if (!err) { hlist_del(&dev->name_hlist); hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); } return err;}/** * 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) { notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); rtmsg_ifinfo(RTM_NEWLINK, dev, 0); }}/** * dev_load - load a network module * @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(const char *name){ struct net_device *dev; read_lock(&dev_base_lock); dev = __dev_get_by_name(name); read_unlock(&dev_base_lock); if (!dev && capable(CAP_SYS_MODULE)) request_module("%s", name);}static int default_rebuild_header(struct sk_buff *skb){ printk(KERN_DEBUG "%s: default_rebuild_header called -- BUG!\n", skb->dev ? skb->dev->name : "NULL!!!"); kfree_skb(skb); return 1;}/** * 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->open) { ret = dev->open(dev); if (ret) clear_bit(__LINK_STATE_START, &dev->state); } /* * If it went open OK then: */ if (!ret) { /* * Set the flags. */ dev->flags |= IFF_UP; /* * Initialize multicasting status */ dev_mc_upload(dev); /* * Wakeup transmit queue engine */ dev_activate(dev); /* * ... and announce new interface. */ notifier_call_chain(&netdev_chain, NETDEV_UP, dev); } return ret;}/** * 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. */int dev_close(struct net_device *dev){ if (!(dev->flags & IFF_UP)) return 0; /* * Tell people we are going down, so that they can * prepare to death, when device is still operating. */ notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev); dev_deactivate(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(), * and wait when poll really will happen. Actually, the best place * for this is inside dev->stop() after device stopped its irq * engine, but this requires more changes in devices. */ smp_mb__after_clear_bit(); /* Commit netif_running(). */ while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) { /* No hurry. */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); } /* * 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 (dev->stop) dev->stop(dev); /* * Device is now down. */ dev->flags &= ~IFF_UP; /* * Tell people we are down */ notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev); return 0;}/* * Device change register/unregister. These are not inline or static * as we export them to the world. *//** * 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_device *dev; int err; rtnl_lock(); err = notifier_chain_register(&netdev_chain, nb); if (!err) { for (dev = dev_base; dev; dev = dev->next) { nb->notifier_call(nb, NETDEV_REGISTER, dev); if (dev->flags & IFF_UP) nb->notifier_call(nb, NETDEV_UP, dev); } } rtnl_unlock(); return err;}/** * 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. */int unregister_netdevice_notifier(struct notifier_block *nb){ return notifier_chain_unregister(&netdev_chain, nb);}/** * call_netdevice_notifiers - call all network notifier blocks * @val: value passed unmodified to notifier function * @v: pointer passed unmodified to notifier function * * Call all network notifier blocks. Parameters and return value * are as for notifier_call_chain(). */int call_netdevice_notifiers(unsigned long val, void *v){ return notifier_call_chain(&netdev_chain, val, v);}/* * Support routine. Sends outgoing frames to any network * taps currently in use.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -