深入理解Linux网络技术内幕-设备注册和初始化(五


         网络设备在系统中注册、注销和关闭、打开等事件都可以通知给相应的内核组件或用户空间应用程序,其中内核组件通过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,通知的信息包括:

  1. netdev_chain通知链接收的事件信息;
  2. 设备状态改变时,如打开关闭的设备,或打开的设备关闭,在netdev_state_change函数中;
  3. 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);

猜你喜欢

转载自blog.csdn.net/wlf_go/article/details/80284462
今日推荐