设为首页 收藏本站
查看: 3004|回复: 0

[经验分享] struct net_device网络设备结构体详解

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-12-1 09:49:47 | 显示全部楼层 |阅读模式
  在linux中使用struct net_device结构体来描述每一个网络设备。同时这个用来刻画网络设备的struct net_device结构体包含的字段非常的多,以至于内核的开发者都觉得在现在的linux内核中,这个struct net_device是一个大的错误。   在本篇文章中,只介绍struct net_device中的一些字段,其他的字段在以后使用的时候再说。
   #define IFNAMSIZ 32

   struct net_device
   {
       //用于存放网络设备的设备名称;

       char name[IFNAMSIZ];

       //网络设备的别名;
       char *ifalias;

       //网络设备的接口索引值,独一无二的网络设备标识符;
       int ifindex;



        //这个字段用于构建网络设备名的哈希散列表,而struct net中的
      //name_hlist就指向每个哈希散列表的链表头;

      struct hlist_node name_hlist;

        //用于构建网络设备的接口索引值哈希散列表,在struct net中的
      //index_hlist用于指向接口索引值哈希散列表的链表头;

      struct hlist_node index_hlist;

      //用于将每一个网络设备加入到一个网络命名空间中的网络设备双链表中
      struct list_head dev_list;

      //网络设备接口的标识符,其状态类型被定义在之中;      unsigned int flags;

      //网络设备接口的标识符,但对用户空间不可见;
      unsigned short  priv_flags;


      //接口硬件类型,在中定义了每一个接口硬件类型;
      unsigned short type;

      //网络设备接口的最大传输单元;
      unsigned mtu;

      //硬件接口头长度;
      unsigned short hard_header_len;


      //网络设备接口的MAC地址;
      unsigned char *dev_addr;

      //网络设备接口的单播模式
      int uc_promisc;

      //网络设备接口的混杂模式;
      unsigned int promiscuity;

      //网络设备接口的全组播模式;
      unsigend int allmulti;

      //secondary unicast mac address

      struct netdev_hw_addr_list uc;

      //list of device hw address;

      struct netdev_hw_addr_list dev_addrs;

      //hw broadcast address;

      unsigned char broadcast[MAX_ADDR_LEN];

      //multicast mac address;

      struct dev_addr_list *mac_list;



        //网络设备接口的数据包接收队列;
      struct netdev_queue rx_queue;

      //网络设备接口的数据包发送队列;
      struct netdev_queue *tx;

      //Number of TX queues allocated at alloc_netdev_mq() time

      unsigned int num_tx_queues;

      //Number of TX queues currently active in device;

      unsigned int real_num_tx_queues;

      //Max frame per queue allowned;

      unsigned long tx_queue_len;

        //网络设备接口的状态;
      unsigned long state;

      //网络设备接口的统计情况;
      struct net_device_state states;

      //用于执行网络设备所在的命名空间;
      struct net *nd_net;     

   }


     下面的这幅图用于展示linux内核如何利用struct net和struct net_device来构成一个网络命名空间:

wKioL1R6tAiTVjEoAAeQ6_Zmnb0143.jpg


  1.分配一个网络设备函数,即分配一个struct net_device结构体:
    alloc_netdev(sizeof_priv, name, setup);

    这个alloc_netdev()函数本质上是一个宏定义:
    #define alloc_netdev(sizeof_priv, name, setup)
     alloc_netdev_mq(sizeof_priv, name, setup, 1)

    struct net_device *alloc_netdev_mq(int sizeof_priv,
        const char *name, void(*setup)(struct net_device*),
        unsigned int queue_count)
     EXPORT_SYMBOL(alloc_netdev_mq);

    参数介绍:
        sizeof_priv:为分配给网络设备私有空间的大小;
        name :网络设备的名称;
        setup:对分配的网络设备进行初始化的回调函数;
        queue_count:分配给网络设备的子队列数;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
struct net_device *alloc_netdev_mq( int sizeof_priv, const char *name,
            void (*setup)( struct net_device *), unsigned int queue_count )
{
       struct net_device *dev ;

       struct netdev_queue *tx ;

       int alloc_size ;

       alloc_size  = sizeof(struct net_device);

       dev = kzalloc(alloc_size, GFP_KERNEL);

       tx = kcalloc(queue_count, sizeof(struct netdev_queue), GFP_KERNEL);

       dev_addr_init(dev);//对struct net_device中的dev_addrs成员进行初始化;

       dev_unicast_init(dev); //对struct net_device中的uc成员进行初始化;

       dev_net_set(dev, &init_net);//对网络设备的命名空间进行初始化,默认为init_net;

       dev->_tx = tx ;//设置网络设备的发送队列;
       dev->num_tx_queues = queue_count ;
       dev->real_num_tx_queues = queue_count ;

       netdev_init_queues(dev);//对struct net_device中的rx_queue成员进行初始化;

       setup(dev); //对struct net_device结构体进行初始化;

       strcpy(dev->name, name);//设置网路设备的设备名称;   

}

EXPORT_SYMBOL(alloc_netdev_mq);




   2.释放一个网络设备:
    void free_netdev(struct net_device *dev);
    EXPORT_SYMBOL(free_netdev);

  3.注册一个网络设备,只有对一个网络设备进行注册以后,这个网络设备才会在内核中起作用:
    int register_netdev(struct net_device *dev)
    EXPORT_SYMBOL(register_netdev);
    返回值:
           0:表示注册成功;
           a negative errno code :表示注册失败;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int register_netdev(struct net_device *dev)
{
    struct hlist_head *head;
    struct hlist_node *p;
    int ret;
    struct net *net = dev_net(dev); // 获取网络设备所在的命名空间;
    rtnl_lock();//获取rtnl信号量;

    if(!dev_valid_name(dev->name)) //判断网络设备的设备名是否有效;
    {}  

    dev->ifindex = dev_new_index(net); //从网络设备所在的命名空间中找到一个全局唯一的网络
                                       //接口索引值;
    dev->iflink = dev->ifindex ;

    //用于判断网络命名空间中是否有相同名字的网络设备存在;
    head = dev_name_hash(net, dev->name);
    hlist_for_each(p,head)
    {
       struct net_device *d = hlist_entry(p, struct net_device, name_hlist);
       if(!strncmp(d->name, dev->name, 32))
          {
             ret = -EEXIST ;
          }
    }

    set_bit(__LINK_STATE_PRESENT, &dev->state);//设置网络设备的状态;
    list_netdevice(dev); //将网络设备叫入到相应的命名空间之中;
}
EXPORT_SYMBOL(register_netdev);




   3.注销一个网络设备结构体:
    void unregister_netdev(struct net_device *dev);
    EXPORT_SYMBOL(unregister_netdev);

   4.设置一个网络设备的MAC地址:
    int dev_set_mac_address(struct net_device *dev,

                        struct sockaddr *sa);
    EXPORT_SYMBOL(dev_set_mac_address);

   5.设置一个网络设备的最大传输单元:
    int dev_set_mtu(struct net_device *dev, int new_mtu);
    EXPORT_SYMBOL(dev_set_mtu);

   6.改变一个网络设备的flag标识符:
    int dev_change_flags(struct net_device *dev, unsigend flags);
    EXPORT_SYMBOL(dev_change_flags);

   7.获取一个网络设备的flag标识符:
    unsigned dev_get_flags(struct net_device *dev);
    EXPORT_SYMBOL(dev_get_flags);

   8.给网络设备添加一个单播MAC地址,当网络设备在发送单播时使用单播MAC地址
    int dev_unicast_add(struct net_device *dev, void *addr);
    EXPORT_SYMBOL(dev_unicast_add);

   9.删除网络设备中的单播MAC地址:
    int dev_unicast_delete(struct net_device *dev, void *addr);
    EXPORT_SYMBOL(dev_unicast_delete);


   10.给网络设备添加一个设备地址:
    int dev_addr_add(struct net_device *dev, unsigned char *addr,
                      unsigned char addr_type)
    EXPORT_SYMBOL(dev_addr_add);
    addr_type : address type;


    11.删除网络设备中的一个设备地址:
    int dev_addr_del(struct net_device *dev, unsigend char *addr,
                      unsigned char addr_type);
    EXPORT_SYMBOL(dev_addr_del);

   12.设置网络设备的接口为混杂模式:
     int dev_set_promiscuity(struct net_device *dev, int inc);
     EXPORT_SYMBOL(dev_set_promiscuity);
     当 inc > 0 将网络设备设置为混杂模式;
     当 inc = 0 将网络设备设置为正常模式;
     当 inc < 0 将去掉网络设备的混杂模式;

   13.设置网络设备的接口为allmulticast模式:
     int dev_set_allmulti(struct net_device *dev, int inc);
     EXPORT_SYMBOL(dev_set_allmulti);
     inc 含义同上;

   14.在给一个网络设备的设备名称进行赋值时,先要检测这个名字是否有效:
     int dev_valid_name(const char *name);
     EXPORT_SYMBOL(dev_valid_name);
     返回: 1 :表示有效;
            0 :表示无效;

   15.通过设备的MAC地址以及设备类型来获取网络设备的设备结构体:
     struct net_device *dev_getbyhwaddr(struct net *net,
                  unsigned short type, char *hwaddr);
     EXPORT_SYMBOL(dev_getbyhwaddr);
     net : 网络命名空间;
     type: media type of device;
     hwaddr:hardware address;
     通过memcmp(dev->dev_addr, hwaddr, dev->addr_len)来实现;


   16.通过网络设备的接口索引值来获取网络设备结构体:
     struct net_device *dev_get_by_index(struct net *net, int ifindex);
     EXPORT_SYMBOL(dev_get_by_index);

   17.通过网络设备的设备名来获取网络设备结构体:
      struct net_device *dev_get_by_name(struct net *net, const char *name);
      EXPORT_SYMBOL(dev_get_by_name);

   以上所介绍的所有函数位于/net/core/dev.c之中;

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-34235-1-1.html 上篇帖子: Ext4文件系统的特性 下篇帖子: RHEL6.4双网卡绑定配置诀窍 结构体 网络
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表