歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> Linux系統內核接收以太幀的處理程序

Linux系統內核接收以太幀的處理程序

日期:2017/2/27 9:45:26   编辑:更多Linux
·Linux系統中如何實現遠程控制·Linux系統的硬件驅動程序編寫原理·Linux系統中如何正確安裝攝像頭驅動·超好用 Linux系統的8個經典技巧·Linux系統調用跟我學(3)――僵屍進程·Linux系統規劃硬盤分區·Linux系統中集群技術及其配置實例·Linux系統調用跟我學(2)――進程管理·靈活運用 詳細了解Linux系統中的關機命令·看上去很美!新款Linux系統JDS2003再戰江

1. 前言

以太頭中除了6字節目的MAC地址、6字節源MAC地址外,還有兩字節的以太幀類型值,如IPv4為0x0800,ARP為0x0806等,網卡驅動收到以太幀後通過接口函數netif_receive_skb()(netif_rx實際最後也是調用netif_receive_skb)交到上層,而這個接口函數就完成對以太幀類型的區分,交到不同的協議處理程序。如果想自己編寫某一以太類型幀的處理程序,需要自己添加相應的代碼。以下為Linux內核2.6代碼。

2. 數據結構

每種協議都要定義一個packet_type結構,引導進入相關的協議數據處理函數,所有節點組成一個鏈表(HASH鏈表)。

/* include/linux/netdevice.h */ 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 *af_packet_priv; struct list_head list; };

參數說明:

type:以太幀類型,16位。

dev:所附著的網卡設備,如果為NULL則匹配全部網卡。

func:協議入口接收處理函數。

af_packet_priv:協議私有數據。

list:鏈表扣。

一般各協議的packet_type結構都是靜態存在,初始化時只提供type和func兩個參數就可以了,每個協議在初始化時都要將此結構加入到系統類型鏈表中。

3. 處理函數

3.1 添加節點

/* net/core/dev.c */ /** * dev_add_pack - add packet handler * @pt: packet type declaration * * Add a protocol handler to the networking stack. The passed &packet_type * is linked into kernel lists and may not be freed until it has been * removed from the kernel lists. * * This call does not sleep therefore it can not * guarantee all CPU's that are in middle of receiving packets * will see the new packet type (until the next received packet). */ void dev_add_pack(struct packet_type *pt) { int hash; spin_lock_bh(&ptype_lock); // 如果類型是全部以太類型,則節點鏈接到ptype_all鏈 if (pt->type == htons(ETH_P_ALL)) { netdev_nit++; list_add_rcu(&pt->list, &ptype_all); } else { // 根據協議類型取個HASH,共15個HASH鏈表 hash = ntohs(pt->type) & 15; // 將節點鏈接到HASH鏈表中,list_add_rcu是加了smp_wmb()保護的list_add鏈表操作 list_add_rcu(&pt->list, &ptype_base[hash]); } spin_unlock_bh(&ptype_lock); }

更多內容請看內核技術 系統管理專題,或




Copyright © Linux教程網 All Rights Reserved