参考:Linux设备驱动开发详解(宋宝华)
网络设备完成用户数据包在网络媒介上的发送和接收的设备,它讲上层协议的传递的数据包以媒介访问的方式进行发送,并将接收到的数据传递给上层协议。
一、Linux网络设备结构图
① 网络协议接口层:该层的存在使设备独立于上层协议,即不管上层网络采用什么协议都通过dev_queue_xmit()发送数据,netif_rx()接收数据。
② 网络设备接口层:net_device是描述具体的网络属性和操作的结构体,并且是设备驱动功能层中各函数的容器。
③ 设备驱动功能层:net_device结构体中各函数的具体实现,驱使网络设备硬件完成相应的功能。
④ 网络设备与媒介层:完成数据发送和接收的物理实体,对于Linux来说可以是虚拟的。
二、网络协议接口层
该层的功能是给上层网络协议提供透明的传输。
① 当上层需要发送数据的时候调用dev_queue_xmit()函数
int dev_queue_xmit(struct sk_buff *skb)
② 当上层需要接收数据的时候调用netif_rx()函数
int netif_rx(struct sk_buff *skb)
两个函数的参数都是sk_buff结构体,定义域include/linux/skbuff.h中,该结构体相当于数据传递的中枢。
发送数据的时候,Linux内核的网络处理模块会建立一个sk_buff,然后传递给下层,每层添加不同的协议头文件,最后进行发送。
接收数据的时候,网络设备将数据包向上传递,各层剥去对应的协议头文件,最后交给上层用户。
三、网络设备接口层
该层的主要功能是提供net_device结构体,多种硬件在软件层次上的统一。
net_device在内核中指代一个具体的网络设备,定义于include/linux/netdevice.h中,具体的定义内容如下:
1 struct net_device {
2 char name[IFNAMSIZ];
3 struct hlist_node name_hlist;
4 char *ifalias;
5 /*
6 * I/O specific fields
7 * FIXME: Merge these and struct ifmap into one
8 */
9 unsigned long mem_end;
10 unsigned long mem_start;
11 unsigned long base_addr;
12 int irq;
13
14 atomic_t carrier_changes;
15
16 /*
17 * Some hardware also needs these fields (state,dev_list,
18 * napi_list,unreg_list,close_list) but they are not
19 * part of the usual set specified in Space.c.
20 */
2122 unsigned long state;
23
24 struct list_head dev_list;
25 struct list_head napi_list;
26 struct list_head unreg_list;
27 struct list_head close_list;
......
60 const struct net_device_ops *netdev_ops;
61 const struct ethtool_ops *ethtool_ops;
62 #ifdef CONFIG_NET_SWITCHDEV
63 const struct swdev_ops *swdev_ops;
64 #endif
65
66 const struct header_ops *header_ops;
67
68 unsigned int flags;
......
77 unsigned char if_port;
78 unsigned char dma;
79
80 unsigned int mtu;
81 unsigned short type;
82 unsigned short hard_header_len;
83
84 unsigned short needed_headroom;
85 unsigned short needed_tailroom;
86
87 /* Interface address info. */
88 unsigned char perm_addr[MAX_ADDR_LEN];
89 unsigned char addr_assign_type;
90 unsigned char addr_len;
......
130 /*
131 * Cache lines mostly used on receive path (including
eth_type_trans())
132 */
133 unsigned long last_rx;
134
135 /* Interface address info used in eth_type_trans() */
136 unsigned char *dev_addr;
137
138
139 #ifdef CONFIG_SYSFS140 struct netdev_rx_queue *_rx;
141
142 unsigned int num_rx_queues;
143 unsigned int real_num_rx_queues;
144
145 #endif
......
158 /*
159 * Cache lines mostly used on transmit path
160 */
161 struct netdev_queue *_tx ____cacheline_aligned_in_smp;
162 unsigned int num_tx_queues;
163 unsigned int real_num_tx_queues;
164 struct Qdisc *qdisc;
165 unsigned long tx_queue_len;
166 spinlock_t tx_global_lock;
167 int watchdog_timeo;
......
173 /* These may be needed for future network-power-down code. */
174
175 /*
176 * trans_start here is expensive for high speed devices on SMP,
177 * please use netdev_queue->trans_start instead.
178 */
179 unsigned long trans_start;
......
248 struct phy_device *phydev;
249 struct lock_class_key *qdisc_tx_busylock;
250 };
四、设备驱动功能层
net_device结构体的成员(属性和net_device_ops结构体中的函数指针)需要被设备驱动功能层赋予具体的数值和函数。对于具体的设备xxx,工程师应该编写相应的设备驱动功能层的函数,这些函数形如xxx_open().xxx_stop()、xxx_tx()、xxx_hard_header()、xxx_get_stats(和 xxx_tx_timcout()等。
由于网络数据包的接收可由中断引发,设备驱动功能层中的另一个主体部分将是中断处理函数,它负责读取硬件上接收到的数据包并传送给上层协议,因此可能包含xxxinterrupt()和xxx_rx()函数,前者完成中断类型判断等基本工作,后者则需完成数据包的生成及将其递交给上层等复杂工作。
对于特定的设备,我们还可以定义相关的私有数据和操作,并封装为一个私有信息结构体xxx_private,让其指针赋值给net_device的私有成员。在xxx_private结构体中可包含设备的特殊属性和操作、自旋锁与信号量、定时器以及统计信息等。