Linux系统内核接收以太帧的处理程序

1. 前言

以太头中除了6字节目的MAC地址、6字节源MAC地址外,还有两字节的以太帧类型值,如IPv4为0x0800,ARP为0x0806等,网卡驱动收到以太帧后通过接口函数netif_receive_skb()(netif_rx实际最后也是调用netif_receive_skb)交到上层,而这个接口函数就完成对以太帧类型的区分,交到不同的协议处理程序。如果想自己编写某一以太类型帧的处理程序,需要自己添加相应的代码。以下为Linux内核2.6代码。

2. 数据结构

每种协议都要定义一个packet_type结构,引导进入相关的协议数据处理函数,所有节点组成一个链表(HASH链表)。


参数说明:

type:以太帧类型,16位。

dev:所附着的网卡设备,如果为NULL则匹配全部网卡。

func:协议入口接收处理函数。

af_packet_priv:协议私有数据。

list:链表扣。

一般各协议的packet_type结构都是静态存在,初始化时只提供type和func两个参数就可以了,每个协议在初始化时都要将此结构加入到系统类型链表中。

3. 处理函数

3.1 添加节点

3.2 删除节点


4. 实例

4.1 IP

由于IP协议部分不能作为内核模块,所以是没有卸载函数的,没必要调用dev_remove_pack()函数。

 

4.2 8021q vlan


由于VLAN可为模块方式存在,所以在模块清除函数中要调用dev_remove_pack()。

5. 网络接收

网卡驱动收到数据包构造出skb后,通过接口函数netif_receive_skb()传递到上层进行协议处理分配。

6. 结论

通过链表挂接方式,Linux内核可以很容易的添加各种协议的接收处理函数。

数据流程:

网卡驱动--->netif_rx()--->netif_receive_skb()->deliver_skb()->packet_type.func

分享到