网络帧在进入网络层时,需要区分不同的网络协议进行处理,这就需要涉及协议处理函数。
首先我们从驱动接收到一个数据帧,分析数据帧在协议栈中自下而上的传输流程。
设备驱动程序在接收到一个数据帧时,会将其保存在一个sk_buff缓冲区数据结构,并对其进行初始化。
struct sk_buff {
......
	__be16          protocol:16;  
......
} 在这个缓冲区结构体中,有一个protocol字段,用于标识网络层的协议。protocol的定义在include/linux/if_ether.h中,如下所示:
#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ #define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ #define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ /*ETH_P_ALL不是真正的协议,而是作为通配符,主要用于sniff嗅探器等*/ #define ETH_P_802_2 0x0004 /* 802.2 frames */ #define ETH_P_SNAP 0x0005 /* Internal only */ #define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */ #define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/ #define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */ ......
struct packet_type {
    __be16  type;   /* This is really htons(ether_type). */ //二层协议类型,ETH_P_IP、ETH_P_ARP等等
    struct net_device   *dev;   /* NULL is wildcarded here       */
    //钩子函数了,如 ip_rcv()、arp_rcv()等等
    int         (*func) (struct sk_buff *,
                     struct net_device *,
                     struct packet_type *,
                     struct net_device *);
    struct sk_buff      *(*gso_segment)(struct sk_buff *skb,
                        int features);
    int         (*gso_send_check)(struct sk_buff *skb);
    struct sk_buff      **(*gro_receive)(struct sk_buff **head,
                           struct sk_buff *skb);
    int         (*gro_complete)(struct sk_buff *skb);
    void            *af_packet_priv;
    struct list_head    list;
};
 其中成员func即为各个协议的钩子函数(协议处理函数).//注册协议:把packet_type结构挂在与type对应的list_head上面                                                                               
void dev_add_pack(struct packet_type *pt)
{
    int hash;                 
    spin_lock_bh(&ptype_lock);
    if (pt->type == htons(ETH_P_ALL))  //type为ETH_P_ALL时,挂在ptype_all上面
        list_add_rcu(&pt->list, &ptype_all);
    else {  //否则,挂在ptype_base[type&15]上面
        hash = ntohs(pt->type) & PTYPE_HASH_MASK;
        list_add_rcu(&pt->list, &ptype_base[hash]);
    }  
    spin_unlock_bh(&ptype_lock);   
}
EXPORT_SYMBOL(dev_add_pack);  
static struct packet_type ip_packet_type __read_mostly = {
    .type = cpu_to_be16(ETH_P_IP),
    .func = ip_rcv,   //ipv4 的协议处理函数 ,在netif_receive_skb会使用  
    .gso_send_check = inet_gso_send_check,
    .gso_segment = inet_gso_segment,
    .gro_receive = inet_gro_receive,
    .gro_complete = inet_gro_complete,
};     
static int __init inet_init(void)
{
	......
    dev_add_pack(&ip_packet_type);
	......                                                                                                                        
}
原文地址:http://blog.csdn.net/windeal3203/article/details/44831133