网络安全 频道

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

// 根据协议类型找是在ptype_all表还是某一HASH链表中

if (pt->type == htons(ETH_P_ALL)) {

netdev_nit--;

head = &ptype_all;

} else

head = &ptype_base[ntohs(pt->type) & 15];

// 直接用地址比对进行查找,而不是类型,因为同一个类型也可能有多个节点

list_for_each_entry(pt1, head, list) {

if (pt == pt1) {

list_del_rcu(&pt->list);

goto out;

}

}

printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt);

out:

spin_unlock_bh(&ptype_lock);

}

/**

* dev_remove_pack - remove packet handler

* @pt: packet type declaration

*

* Remove a protocol handler that was previously added to the kernel

* protocol handlers by dev_add_pack(). The passed &packet_type is removed

* from the kernel lists and can be freed or reused once this function

* returns.

*

* This call sleeps to guarantee that no CPU is looking at the packet

* type after return.

*/

// 只是__dev_remove_pack()的包裹函数

void dev_remove_pack(struct packet_type *pt)

{

__dev_remove_pack(pt);

synchronize_net();

}

4. 实例

4.1 IP

/* net/ipv4/af_inet.c */

static struct packet_type ip_packet_type = {

.type = __constant_htons(ETH_P_IP),

.func = ip_rcv, // IP接收数据的入口点

};

static int __init inet_init(void)

{

......

dev_add_pack(&ip_packet_type);

......

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

4.2 8021q vlan

/* net/8021q/vlan.c */

static struct packet_type vlan_packet_type = {

.type = __constant_htons(ETH_P_8021Q),

.func = vlan_skb_recv, /* VLAN receive method */

};

......

static int __init vlan_proto_init(void)

{

......

dev_add_pack(&vlan_packet_type);

......

static void __exit vlan_cleanup_module(void)

{

......

dev_remove_pack(&vlan_packet_type);

......

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

5. 网络接收

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

/* net/core/dev.c */

int netif_receive_skb(struct sk_buff *skb)

{

......

// 先查处理所有以太类型的链表各节点

0
相关文章