转自:http://blog.csdn.net/viewsky11/article/details/53046787

在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; //网络设备接口的标识符,其状态类型被定义在<linux/if.h>之中;
unsigned int flags; //网络设备接口的标识符,但对用户空间不可见;
unsigned short priv_flags; //接口硬件类型,在<if_arp.h>中定义了每一个接口硬件类型;
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;
}
  • 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
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89

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

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

参数介绍: 
- sizeof_priv:为分配给网络设备私有空间的大小; 
- name :网络设备的名称; 
- setup:对分配的网络设备进行初始化的回调函数; 
- queue_count:分配给网络设备的子队列数;

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);
  • 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
  • 35

2.释放一个网络设备:

void free_netdev(struct net_device *dev);
EXPORT_SYMBOL(free_netdev);
  • 1
  • 2
  • 3

3.注册一个网络设备,只有对一个网络设备进行注册以后,这个网络设备才会在内核中起作用:

 int register_netdev(struct net_device *dev)
EXPORT_SYMBOL(register_netdev);
  • 1
  • 2
  • 3

返回值: 
- 0:表示注册成功; 
- a negative errno code :表示注册失败;

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);
  • 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

3.注销一个网络设备结构体:

void unregister_netdev(struct net_device *dev);
EXPORT_SYMBOL(unregister_netdev);
  • 1
  • 2
  • 3

4.设置一个网络设备的MAC地址:

int dev_set_mac_address(struct net_device *dev,
struct sockaddr *sa);
EXPORT_SYMBOL(dev_set_mac_address);
  • 1
  • 2
  • 3
  • 4

5.设置一个网络设备的最大传输单元:

int dev_set_mtu(struct net_device *dev, int new_mtu);
EXPORT_SYMBOL(dev_set_mtu);
  • 1
  • 2
  • 3

6.改变一个网络设备的flag标识符:

int dev_change_flags(struct net_device *dev, unsigend flags);
EXPORT_SYMBOL(dev_change_flags);
  • 1
  • 2
  • 3

7.获取一个网络设备的flag标识符:

unsigned dev_get_flags(struct net_device *dev);
EXPORT_SYMBOL(dev_get_flags);
  • 1
  • 2
  • 3

8.给网络设备添加一个单播MAC地址,当网络设备在发送单播时使用单播MAC地址

int dev_unicast_add(struct net_device *dev, void *addr);
EXPORT_SYMBOL(dev_unicast_add);
  • 1
  • 2
  • 3

9.删除网络设备中的单播MAC地址:

int dev_unicast_delete(struct net_device *dev, void *addr);
EXPORT_SYMBOL(dev_unicast_delete);
  • 1
  • 2
  • 3

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;
  • 1
  • 2
  • 3
  • 4
  • 5

11.删除网络设备中的一个设备地址:

int dev_addr_del(struct net_device *dev, unsigend char *addr,
unsigned char addr_type);
EXPORT_SYMBOL(dev_addr_del);
  • 1
  • 2
  • 3
  • 4

12.设置网络设备的接口为混杂模式:

 int dev_set_promiscuity(struct net_device *dev, int inc);
EXPORT_SYMBOL(dev_set_promiscuity);
  • 1
  • 2
  • 3

当 inc > 0 将网络设备设置为混杂模式; 
当 inc = 0 将网络设备设置为正常模式; 
当 inc < 0 将去掉网络设备的混杂模式;

13.设置网络设备的接口为allmulticast模式:

 int dev_set_allmulti(struct net_device *dev, int inc);
EXPORT_SYMBOL(dev_set_allmulti);
inc 含义同上;
  • 1
  • 2
  • 3
  • 4

14.在给一个网络设备的设备名称进行赋值时,先要检测这个名字是否有效:

 int dev_valid_name(const char *name);
EXPORT_SYMBOL(dev_valid_name);
  • 1
  • 2
  • 3

返回: 
1 :表示有效; 
0 :表示无效;

15.通过设备的MAC地址以及设备类型来获取网络设备的设备结构体:

  struct net_device *dev_getbyhwaddr(struct net *net,
unsigned short type, char *hwaddr);
EXPORT_SYMBOL(dev_getbyhwaddr);
  • 1
  • 2
  • 3
  • 4

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);
  • 1
  • 2
  • 3

17.通过网络设备的设备名来获取网络设备结构体:

struct net_device *dev_get_by_name(struct net *net, const char *name);
EXPORT_SYMBOL(dev_get_by_name);
  • 1
  • 2
  • 3

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

本文转载自 http://weiguozhihui.blog.51cto.com/3060615/1584894

struct net_device网络设备结构体详解的更多相关文章

  1. NetBios 的结构体详解

    [NetBios 的结构体详解] NetBIOS是早期的局域网传输协议. 1.结构体. 2.命令 NetBIOS命令的使用方式有两种,即等待和非等待(或称为同步与异步)方式. 如果命令码的高阶位是0时 ...

  2. struct socket结构体详解

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://weiguozhihui.blog.51cto.com/3060615/15852 ...

  3. Linux下DIR,dirent,stat等结构体详解

    摘自:http://www.liweifan.com/2012/05/13/linux-system-function-files-operation/ 最近在看Linux下文件操作相关章节,遇到了这 ...

  4. Linux进程描述符task_struct结构体详解--Linux进程的管理与调度(一)【转】

    Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息.它定义在include/linux/sched.h文件中. 谈到task_str ...

  5. Linux下DIR,dirent,stat等结构体详解(转)

    最近在看Linux下文件操作相关章节,遇到了这么几个结构体,被搞的晕乎乎的,今日有空,仔细研究了一下,受益匪浅. 首先说说DIR这一结构体,以下为DIR结构体的定义: struct __dirstre ...

  6. I2C初始化结构体详解

    typedef struct { uint32_t I2C_ClockSpeed; /*设置SCL时钟频,此值不低于40000*/ uint16_t I2C_Mode; /* 指定工作模式,可选I2C ...

  7. CEF CefSettings 结构体 详解

    1. single_process: 设置为ture时,browser和render使用同一个进程.Chromium 不正是支持此运行模式,并且不如默认的多进程稳定. 2. no_sandbox: 沙 ...

  8. struct termios结构体详解

    一.数据成员 termios 函数族提供了一个常规的终端接口,用于控制非同步通信端口. 这个结构包含了至少下列成员:tcflag_t c_iflag;      /* 输入模式 */tcflag_t ...

  9. 【USB】struct usb_device_id 结构体详解

    struct usb_device_id { /* which fields to match against? */ __u16 match_flags; //说明使用哪种匹配方式 /* Used ...

随机推荐

  1. 浅谈js设计模式 — 享元模式

    享元(flyweight)模式是一种用于性能优化的模式,“fly”在这里是苍蝇的意思,意为蝇量级.享元模式的核心是运用共享技术来有效支持大量细粒度的对象. 假设有个内衣工厂,目前的产品有 50种男式内 ...

  2. HTTPS那-攻击实例与防御

    在<HTTPS-SSL证书>我描述了使用SSL证书时一些需要注意的安全问题,在这一篇文章里面我再演示一下针对HTTPS攻击的一些实例,通过这些实例能更安全的使用HTTPS.知己知彼百战不殆 ...

  3. hadoop日志数据分析开发步骤及代码

    日志数据分析:1.背景1.1 hm论坛日志,数据分为两部分组成,原来是一个大文件,是56GB:以后每天生成一个文件,大约是150-200MB之间:1.2 日志格式是apache common日志格式: ...

  4. 025 Spark中的广播变量原理以及测试(共享变量是spark中第二个抽象)

    一:来源 1.说明 为啥要有这个广播变量呢. 一些常亮在Driver中定义,然后Task在Executor上执行. 如果,有多个任务在执行,每个任务需要,就会造成浪费. 二:共享变量的官网 1.官网 ...

  5. 004 作业二(单击弹跳li节点的每个文本节点的值;点击每个 li 节点, 若 li 节点的文本值没有 ^^ 开头, 加上,有,则去除)

    1.需求 点击每个 li 节点, 都弹出其文本值 2.程序 <!DOCTYPE html> <html> <head> <meta charset=" ...

  6. 在windows下使用多版本Python安装相应的虚拟开发环境

    在windows下面使用多版本Python安装相应的虚拟开发环境   在搭建一个项目的时候,希望使用最新版的Python3.7版本,但是Python3.6的版本也要留下,那么问题来了,如何解决这个问题 ...

  7. 004.FTP匿名用户访问

    一 匿名用户配置项 [root@imxhy~]# vi /etc/vsftpd/vsftpd.conf anonymous_enable #允许匿名用户访问 anon_upload_enable #允 ...

  8. 001.SMB简介

    一 简介 samba基于NetBIOS协议开发,能和windows通信,但只能在局域网通信. 二 Samba主要应用 文件共享 打印服务器 Samba登录时身份验证 进行windows主机名解析 三 ...

  9. JSP中的内置标记(JSP动作)和 EL表达式

    一.JSP的内置标记(JSP动作) (一)JSP的内置标记都是以<jsp: 开始标记的 一般会用到<jsp:useBean/>,<jsp:setProperty/>,&l ...

  10. InnoDB的锁机制浅析(五)—死锁场景(Insert死锁)

    可能的死锁场景 文章总共分为五个部分: InnoDB的锁机制浅析(一)-基本概念/兼容矩阵 InnoDB的锁机制浅析(二)-探索InnoDB中的锁(Record锁/Gap锁/Next-key锁/插入意 ...