在netif_receive_skb()函數中,可以看出處理的是像ARP、IP這些鏈路層以上的協議,那麼,鏈路層前序是在哪裡去掉的呢 ?答案是網卡驅動中,在調用netif_receive_skb()前,
skb->protocol = eth_type_trans(skb, bp- >dev);
該函數對處理後skb>data跳過乙太網路前序,由mac_header指示乙太網路前序:
進入 netif_receive_skb()函數
list_for_each_entry_rcu(ptype,&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list)
按照協議類型依次由相應的協議模組進行處理,而所以的協議模組處理都會註冊在ptype_base中,實際是鏈表結構 。
net/core/dev.c
static struct list_head ptype_base __read_mostly; /* Taps */
而相應的 協議模組是通過dev_add_pack()函數加入的:
void dev_add_pack(struct packet_type *pt) { int hash; spin_lock_bh(&ptype_lock); if (pt->type == htons(ETH_P_ALL)) list_add_rcu(&pt->list, &ptype_all); else { hash = ntohs(pt->type) & PTYPE_HASH_MASK; list_add_rcu(&pt->list, &ptype_base[hash]); } spin_unlock_bh(&ptype_lock); }
以ARP處理為例
該模組的定義,它會在arp_init()中註冊進ptype_base鏈表中:
static struct packet_type arp_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_ARP), .func = arp_rcv, };
然後在根據報文的TYPE來在ptype_base中尋找相應協議模組進行處理時,實際調用arp_rcv()進行接收
arp_rcv() --> arp_process()
arp = arp_hdr(skb); …… arp_ptr= (unsigned char *)(arp+1); sha= arp_ptr; arp_ptr += dev->addr_len; memcpy(&sip, arp_ptr, 4); arp_ptr += 4; arp_ptr += dev->addr_len; memcpy(&tip, arp_ptr, 4);
操作後這指標位置: