内核版本:linux-source-4.19
协议处理函数的注册
无论是系统启动或其他时刻,当一个协议注册时,内核就会调用dev_add_pack
,把一个定义在include/linux.netdevice.h
类型为packet_type的数据结构传进去。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| struct packet_type {
__be16 type; /* This is really htons(ether_type). */
struct net_device *dev; /* NULL is wildcarded here */
int (*func) (struct sk_buff *,
struct net_device *,
struct packet_type *,
struct net_device *);
void (*list_func) (struct list_head *,
struct packet_type *,
struct net_device *);
bool (*id_match)(struct packet_type *ptype,
struct sock *sk);
void *af_packet_priv;
struct list_head list;
};
|
- type: 协议代码
- dev: 设备的指针,置为NULL时,指所有设备
- func: type对应的处理函数
- list_func:
- id_match:
- af_packet_priv:
- list:
为每个协议注册时,内核会对packet_type
结构做初始化,然后调用dev_add_pack
。
当IPv4协议在引导期间初始化时,ip_init函数会被执行。其中一种结果是,IPv4 packet_type
结构中的函数ip_rcv
会注册成此协议的函数处理函数。所有Ethernet帧接收时,若ETH_P_IP
的值为Protocol Above,就会由函数ip_rcv
处理。
ipv4对应的例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| // linux/net/ipv4/af_inet.c
static struct packet_type ip_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_IP),
.func = ip_rcv,
.list_func = ip_list_rcv,
};
static int __init inet_init(void)
{
struct inet_protosw *q;
struct list_head *r;
int rc = -EINVAL;
sock_skb_cb_check_size(sizeof(struct inet_skb_parm));
...
dev_add_pack(&ip_packet_type);
...
}
|