storage R&D guy.
全部博文(1000)
分类: LINUX
2014-05-07 08:40:13
原文地址:深入理解Linux网络技术内幕-设备注册和初始化(五) 作者:visualfan
网络设备在系统中注册、注销和关闭、打开等事件都可以通知给相应的内核组件或用户空间应用程序,其中内核组件通过netdev_chain通知链获取消息,而用户空间应用程序则通过注册Netlink RTMGRP_LINK多播群组获取事件消息。
内核组件关联的netdev_chain通知链
前面已经介绍过通知链的使用方法,主要是需要了解网络设备事件消息的内核组件通过register_netdevice_notifier和unregister_netdevice_notifier分别对netdev_chain通知链进行注册和注销。在网络设备相应的事件发生时,会调用这个通知链通知这些内核组件,主要的网络设备事件包括:
#define NETDEV_UP 0x0001 /* 网络设备开启,由dev_open函数产生*/
#define NETDEV_DOWN 0x0002 /*网络设备已经关闭,由dev_close函数产生*/
#define NETDEV_REBOOT 0x0003 /* Tell a protocol stack a network interface
detected a hardware crash and restarted
- we can use this eg to kick tcp sessions
once done */
#define NETDEV_CHANGE 0x0004 /* Notify device state change */
#define NETDEV_REGISTER 0x0005 /*设备已注册,由register_netdevice产生*/
#define NETDEV_UNREGISTER 0x0006 /*设备已注销,由unregister_netdevice产生*/
#define NETDEV_CHANGEMTU 0x0007
#define NETDEV_CHANGEADDR 0x0008
#define NETDEV_GOING_DOWN 0x0009
#define NETDEV_CHANGENAME 0x000A
#define NETDEV_FEAT_CHANGE 0x000B
#define NETDEV_BONDING_FAILOVER 0x000C
#define NETDEV_PRE_UP 0x000D
#define NETDEV_PRE_TYPE_CHANGE 0x000E
#define NETDEV_POST_TYPE_CHANGE 0x000F
#define NETDEV_POST_INIT 0x0010
#define NETDEV_UNREGISTER_BATCH 0x0011
#define NETDEV_BONDING_DESLAVE 0x0012
#define NETDEV_NOTIFY_PEERS 0x0013
用户空间应用程序
当网络设备的状态或配置中有改变时,就会调用rtmsg_ifinfo将事件系统传递给Link多播群组RTNLGRP_LINK,通知的信息包括:
- netdev_chain通知链接收的事件信息;
- 设备状态改变时,如打开关闭的设备,或打开的设备关闭,在netdev_state_change函数中;
- net_device->flags中的标记有改变时,如用户配置命令修改标记,在dev_change_flags函数中;
用户空间的netplugd守护进程(net-utils套件)会监测到这些事件,从而根据用户配置文件进行反应。
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);
}
}
int dev_change_flags(struct net_device *dev, unsigned flags)
{
int ret, changes;
int old_flags = dev->flags;ret = __dev_change_flags(dev, flags);
if (ret < 0)
return ret;changes = old_flags ^ dev->flags;
if (changes)
rtmsg_ifinfo(RTM_NEWLINK, dev, changes);__dev_notify_flags(dev, old_flags);
return ret;
}
EXPORT_SYMBOL(dev_change_flags);