日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Linux网络协议栈(三)——网络设备(1)

發布時間:2025/3/17 102 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux网络协议栈(三)——网络设备(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
網絡設備(network device)是內核對網絡適配器(硬件)的抽象與封裝,并為各個協議實例提供統一的接口,它是硬件與內核的接口,它有兩個特征:
(1)?? ?作為基于硬件的網絡適配器與基于軟件的協議之間的接口;
(2)?? ?內核協議棧異步輸入輸出點。
記住:網絡設備軟件對硬件的抽象
網絡設備與協議和網絡適配器的關系如下:

1、?? ?net_device接口(net_device Interface)
???? 網絡設備是內核中除了字符設備、塊設備之外第三類主要設備,它的主要特征之一就是在設備文件系統/dev/沒有相應的表示,即不存在/dev/eth0等,這就意味著不能通過簡單的讀寫操作來訪問它們。
??? net_device結構保存與網絡設備相關的所有信息。每一個網絡設備都對應一個這樣的結構,包括真實設備(例如以太網卡)和虛擬設備(比如 bonding 或 VLAN)。
所有設備的 net_device 結構都放在一個全局鏈表中,鏈表的頭指針是 dev_base。net_device結構的定義在include/linux/netdevice.h中。與 sk_buff 類似,net_device 結構比較大,而且包含了很多特性相關的參數,這些參數在不同的協議層中使用。出于這個原因,net_device 結構的組織會有一些改變,用于優化協議棧的性能。 網絡設備可以分為不同的類型,比如以太網卡和令牌環網卡。net_device 結構中的某些變量對同一類型的設備來說, 取值是相同的; 而某些變量在同一設備的不同工作模式下,取值必須不同。因此,對幾乎所有類型的設備,linux內核提供了一個通用的函數用于初始化那些在所有模式下取值相同的變量。每一個設備驅動在調用這個函數的同時,還初始化那些在當前模式下取值不同的變量。設備驅動同樣可以覆蓋那些由內核初始化的變量(例如,在優化設備性能時)。
  net_device的定義:
Code
//include/linux/netdevice.h
/*

?*????The?DEVICE?structure.
?*????Actually,?this?whole?structure?is?a?big?mistake.??It?mixes?I/O
?*????data?with?strictly?"high-level"?data,?and?it?has?to?know?about
?*????almost?every?data?structure?used?in?the?INET?module.
?*
?*????FIXME:?cleanup?struct?net_device?such?that?network?protocol?info
?*????moves?out.
?
*/

struct?net_device
{

????
/*
?????*?This?is?the?first?field?of?the?"visible"?part?of?this?structure
?????*?(i.e.?as?seen?by?users?in?the?"Space.c"?file).??It?is?the?name
?????*?the?interface.
?????
*/
????
char????????????name[IFNAMSIZ];//網絡設備名稱

????
/*
?????*????I/O?specific?fields
?????*????FIXME:?Merge?these?and?struct?ifmap?into?one
?????
*/
????unsigned?
long????????mem_end;????/*?shared?mem?end????*/
????unsigned?
long????????mem_start;????/*?shared?mem?start????*/
????unsigned?
long????????base_addr;????/*?device?I/O?address????*/
????unsigned?
int????????irq;????????/*?device?IRQ?number????*/

????
/*
?????*????Some?hardware?also?needs?these?fields,?but?they?are?not
?????*????part?of?the?usual?set?specified?in?Space.c.
?????
*/

????unsigned?
char????????if_port;????/*?Selectable?AUI,?TP,..*/
????unsigned?
char????????dma;????????/*?DMA?channel????????*/

????unsigned?
long????????state;

????
struct?net_device????*next;
????
????
/*?The?device?initialization?function.?Called?only?once.?*/
????
int????????????(*init)(struct?net_device?*dev);

????
/*?-------?Fields?preinitialized?in?Space.c?finish?here?-------?*/

????
struct?net_device????*next_sched;

????
/*?Interface?index.?Unique?device?identifier????*/
????
int????????????ifindex;
????
int????????????iflink;


????
struct?net_device_stats*?(*get_stats)(struct?net_device?*dev);
????
struct?iw_statistics*????(*get_wireless_stats)(struct?net_device?*dev);

????
/*?List?of?functions?to?handle?Wireless?Extensions?(instead?of?ioctl).
?????*?See?<net/iw_handler.h>?for?details.?Jean?II?
*/
????
const?struct?iw_handler_def?*????wireless_handlers;
????
/*?Instance?data?managed?by?the?core?of?Wireless?Extensions.?*/
????
struct?iw_public_data?*????wireless_data;

????
struct?ethtool_ops?*ethtool_ops;

????
/*
?????*?This?marks?the?end?of?the?"visible"?part?of?the?structure.?All
?????*?fields?hereafter?are?internal?to?the?system,?and?may?change?at
?????*?will?(read:?may?be?cleaned?up?at?will).
?????
*/

????
/*?These?may?be?needed?for?future?network-power-down?code.?*/
????unsigned?
long????????trans_start;????/*?Time?(in?jiffies)?of?last?Tx????*/
????unsigned?
long????????last_rx;????/*?Time?of?last?Rx????*/

????unsigned?
short????????flags;????/*?interface?flags?(a?la?BSD)????*/
????unsigned?
short????????gflags;
????????unsigned?
short??????????priv_flags;?/*?Like?'flags'?but?invisible?to?userspace.?*/
????????unsigned?
short??????????unused_alignment_fixer;?/*?Because?we?need?priv_flags,
?????????????????????????????????????????????????????????*?and?we?want?to?be?32-bit?aligned.
?????????????????????????????????????????????????????????
*/

????unsigned????????mtu;????
/*?interface?MTU?value????????*/
????unsigned?
short????????type;????/*?interface?hardware?type????*/
????unsigned?
short????????hard_header_len;????/*?hardware?hdr?length????*/
????
void????????????*priv;????/*?pointer?to?private?data????*/

????
struct?net_device????*master;?/*?Pointer?to?master?device?of?a?group,
??????????????????????*?which?this?device?is?member?of.
??????????????????????
*/

????
/*?Interface?address?info.?*/
????unsigned?
char????????broadcast[MAX_ADDR_LEN];????/*?hw?bcast?add????*/
????unsigned?
char????????dev_addr[MAX_ADDR_LEN];????/*?hw?address????*/
????unsigned?
char????????addr_len;????/*?hardware?address?length????*/
????unsigned?
short??????????dev_id;????????/*?for?shared?network?cards?*/

????
struct?dev_mc_list????*mc_list;????/*?Multicast?mac?addresses????*/
????
int????????????mc_count;????/*?Number?of?installed?mcasts????*/
????
int????????????promiscuity;
????
int????????????allmulti;

????
int????????????watchdog_timeo;
????
struct?timer_list????watchdog_timer;

????
/*?Protocol?specific?pointers?*/
????
????
void?????????????*atalk_ptr;????/*?AppleTalk?link?????*/
????
void????????????*ip_ptr;????/*?IPv4?specific?data????*/??
????
void????????????????????*dn_ptr;????????/*?DECnet?specific?data?*/
????
void????????????????????*ip6_ptr;???????/*?IPv6?specific?data?*/
????
void????????????*ec_ptr;????/*?Econet?specific?data????*/
????
void????????????*ax25_ptr;????/*?AX.25?specific?data?*/

????
struct?list_head????poll_list;????/*?Link?to?poll?list????*/
????
int????????????quota;
????
int????????????weight;

????
struct?Qdisc????????*qdisc;
????
struct?Qdisc????????*qdisc_sleeping;
????
struct?Qdisc????????*qdisc_ingress;
????
struct?list_head????qdisc_list;
????unsigned?
long????????tx_queue_len;????/*?Max?frames?per?queue?allowed?*/

????
/*?ingress?path?synchronizer?*/
????spinlock_t????????ingress_lock;
????
/*?hard_start_xmit?synchronizer?*/
????spinlock_t????????xmit_lock;
????
/*?cpu?id?of?processor?entered?to?hard_start_xmit?or?-1,
???????if?nobody?entered?there.
?????
*/
????
int????????????xmit_lock_owner;
????
/*?device?queue?lock?*/
????spinlock_t????????queue_lock;
????
/*?Number?of?references?to?this?device?*/
????atomic_t????????refcnt;
????
/*?delayed?register/unregister?*/
????
struct?list_head????todo_list;
????
/*?device?name?hash?chain?*/
????
struct?hlist_node????name_hlist;
????
/*?device?index?hash?chain?*/
????
struct?hlist_node????index_hlist;

????
/*?register/unregister?state?machine?*/
????
enum?{?NETREG_UNINITIALIZED=0,
???????????NETREG_REGISTERING,????
/*?called?register_netdevice?*/
???????????NETREG_REGISTERED,????
/*?completed?register?todo?*/
???????????NETREG_UNREGISTERING,????
/*?called?unregister_netdevice?*/
???????????NETREG_UNREGISTERED,????
/*?completed?unregister?todo?*/
???????????NETREG_RELEASED,????????
/*?called?free_netdev?*/
????}?reg_state;

????
/*?Net?device?features?*/
????
int????????????features;
#define?NETIF_F_SG????????1????/*?Scatter/gather?IO.?*/
#define?NETIF_F_IP_CSUM????????2????/*?Can?checksum?only?TCP/UDP?over?IPv4.?*/
#define?NETIF_F_NO_CSUM????????4????/*?Does?not?require?checksum.?F.e.?loopack.?*/
#define?NETIF_F_HW_CSUM????????8????/*?Can?checksum?all?the?packets.?*/
#define?NETIF_F_HIGHDMA????????32????/*?Can?DMA?to?high?memory.?*/
#define?NETIF_F_FRAGLIST????64????/*?Scatter/gather?IO.?*/
#define?NETIF_F_HW_VLAN_TX????128????/*?Transmit?VLAN?hw?acceleration?*/
#define?NETIF_F_HW_VLAN_RX????256????/*?Receive?VLAN?hw?acceleration?*/
#define?NETIF_F_HW_VLAN_FILTER????512????/*?Receive?filtering?on?VLAN?*/
#define?NETIF_F_VLAN_CHALLENGED????1024????/*?Device?cannot?handle?VLAN?packets?*/
#define?NETIF_F_TSO????????2048????/*?Can?offload?TCP/IP?segmentation?*/
#define?NETIF_F_LLTX????????4096????/*?LockLess?TX?*/

????
/*?Called?after?device?is?detached?from?network.?*/
????
void????????????(*uninit)(struct?net_device?*dev);
????
/*?Called?after?last?user?reference?disappears.?*/
????
void????????????(*destructor)(struct?net_device?*dev);

????
/*?Pointers?to?interface?service?routines.????*/
????
int????????????(*open)(struct?net_device?*dev);
????
int????????????(*stop)(struct?net_device?*dev);
????
int????????????(*hard_start_xmit)?(struct?sk_buff?*skb,
????????????????????????????
struct?net_device?*dev);
#define?HAVE_NETDEV_POLL
????
int????????????(*poll)?(struct?net_device?*dev,?int?*quota);
????
int????????????(*hard_header)?(struct?sk_buff?*skb,
????????????????????????
struct?net_device?*dev,
????????????????????????unsigned?
short?type,
????????????????????????
void?*daddr,
????????????????????????
void?*saddr,
????????????????????????unsigned?len);
????
int????????????(*rebuild_header)(struct?sk_buff?*skb);
#define?HAVE_MULTICAST?????????????
????
void????????????(*set_multicast_list)(struct?net_device?*dev);
#define?HAVE_SET_MAC_ADDR???????????
????
int????????????(*set_mac_address)(struct?net_device?*dev,
???????????????????????????
void?*addr);
#define?HAVE_PRIVATE_IOCTL
????
int????????????(*do_ioctl)(struct?net_device?*dev,
????????????????????????
struct?ifreq?*ifr,?int?cmd);
#define?HAVE_SET_CONFIG
????
int????????????(*set_config)(struct?net_device?*dev,
??????????????????????????
struct?ifmap?*map);
#define?HAVE_HEADER_CACHE
????
int????????????(*hard_header_cache)(struct?neighbour?*neigh,
?????????????????????????????
struct?hh_cache?*hh);
????
void????????????(*header_cache_update)(struct?hh_cache?*hh,
???????????????????????????????
struct?net_device?*dev,
???????????????????????????????unsigned?
char?*??haddr);
#define?HAVE_CHANGE_MTU
????
int????????????(*change_mtu)(struct?net_device?*dev,?int?new_mtu);

#define?HAVE_TX_TIMEOUT
????
void????????????(*tx_timeout)?(struct?net_device?*dev);

????
void????????????(*vlan_rx_register)(struct?net_device?*dev,
????????????????????????????
struct?vlan_group?*grp);
????
void????????????(*vlan_rx_add_vid)(struct?net_device?*dev,
???????????????????????????unsigned?
short?vid);
????
void????????????(*vlan_rx_kill_vid)(struct?net_device?*dev,
????????????????????????????unsigned?
short?vid);

????
int????????????(*hard_header_parse)(struct?sk_buff?*skb,
?????????????????????????????unsigned?
char?*haddr);
????
int????????????(*neigh_setup)(struct?net_device?*dev,?struct?neigh_parms?*);
????
int????????????(*accept_fastpath)(struct?net_device?*,?struct?dst_entry*);
#ifdef?CONFIG_NETPOLL
????
int????????????netpoll_rx;
#endif
#ifdef?CONFIG_NET_POLL_CONTROLLER
????
void????????????????????(*poll_controller)(struct?net_device?*dev);
#endif

????
/*?bridge?stuff?*/
????
struct?net_bridge_port????*br_port;

#ifdef?CONFIG_NET_DIVERT
????
/*?this?will?get?initialized?at?each?interface?type?init?routine?*/
????
struct?divert_blk????*divert;
#endif?/*?CONFIG_NET_DIVERT?*/

????
/*?class/net/name?entry?*/
????
struct?class_device????class_dev;
????
/*?how?much?padding?had?been?added?by?alloc_netdev()?*/
????
int?padded;
};
??? net_device結構主要分為以下幾部分:
1.1、?? ?通用字段
name:
網絡適配器的名稱,比如eth0。在注冊網絡設備時可以為設備分配一個名稱,便必須唯一。
next:
所有的網絡設備組成一個由dev_base開頭的鏈表。
int ifindex :
全局唯一的設備ID。在每個設備注冊時,調用dev_new_index 生成。
int iflink:
這個變量主要被(虛擬)隧道設備使用,用于標識隧道的真實設備。
state:
它包含一組被網絡隊列子系統使用的標記。這些標記的值是枚舉類型netdev_state_t中的索引值,這個類型的定義在 include/linux/netdevice.h 中,每個標記都是諸如__LINK_STATE_XOFF 這樣的常量。每一位都可以通過函數 set_bit 和 clear_bit 設置或清除,但通常情況下,都會有一個包裝函數來隱藏標記位的信息。例如,在網絡隊列子系統停止一個設備隊列時,它調用函數 netif_stop_queue,這個函數的定義如下:
? static inline void netif_stop_queue(struct net_device *dev)
{
??????? ...
??????? set_bit(_ _LINK_STATE_XOFF, &dev->state);
}
trans_start:
最后一個幀開始發送的時間(用jiffies度量)。設備驅動在發送之前設置這個變量。這個變量用來檢測網卡是否在給定的時間內把幀發送了出去。 太長的發送時間意味
著有錯誤發生,在這種情況下,設備驅動會重置網卡。
last_rx :
接收到最后一個包的時間(用jiffies度量)。
xmit_lock 和xmit_lock_owner :
xmit_lock 用來序列化對設備驅動函數hard_start_xmit的調用。這意味著,每個cpu每次只能調用設備完成一次發送。xmit_lock_owner 是擁有鎖的 CPU 的 ID。在單cpu 系統上,這個值是 0;在多 cpu 系統中,如果鎖沒有被占用,這個值是-1。內核同樣允許不加鎖的發送,前提條件是設備驅動必須支持這個功能。
struct hlist_node name_hlist
struct hlist_node index_hlist
? 把net_device結構鏈接到兩個哈希表中。
1.2、?? ?硬件相關
unsigned int irq
? 設備中斷號。它可以被多個設備共享。設備驅動調用request_irq來分配這個值,并
調用free_irq來釋放它。
unsigned char if_port
? 接口的端口類型。有些設備可以支持多種接口(最常見的組合是 BNC+RJ45),用戶可以根據需要來選擇使用哪種接口。這個變量用來設置設備的接口類型。如果配置命令沒有指定設備的接口類型,設備驅動就使用缺省的類型。在某些情況下,一個設備驅動可以處理多種接口類型;在這種情況下,設備驅動可以按一定的順序來測試每個接口的類型。下面的代碼片斷展示了一個設備驅動如何根據配置來設置接口的類型:
? switch (dev->if_port) {
??????????????? case??? IF_PORT_10BASE2:
?????????????????????? writeb((readb(addr) & 0xf8) | 1, addr);
??????????????????????? break;
??????????????? case??? IF_PORT_10BASET:
?????????????????????? writeb((readb(addr) & 0xf8), addr);
??????????????????????? break;
??????????????? }
unsigned char dma
? 設備所使用的 DMA 通道。為獲取和釋放一個 DMA 通道,內核在 kernel/dma.c 中定義了兩個函數request_dma和free_dma。為了在獲取dma通道后,啟用或者停止dma通道,內核定義了兩個函數enable_dma和disable_dma。這兩個函數的實現與
體系結構相關,所以在 include/asm-architecture 下有相關的文件(例如include/asm-i386)。這些函數被 ISA 設備使用;PCI 設備不使用這些函數,它們使
用其他函數。并不是所有的設備都可以使用dma,因為有些總線不支持dma。
?unsigned long mem_start
unsigned long mem_end
? 這兩個變量描述設備與內核通信所用到的內存邊界。它們由設備驅動初始化,并且只能被設備驅動訪問;高層協議不需要關心這塊內存。
unsigned long base_addr
? 映射到設備內存空間中I/O 內存起始地址。
1.3、?? ?物理層相關
unsigned mtu
? MTU 的意思是最大傳輸單元,它表示設備可以處理幀的最大長度。不同設備的MTU值:

unsigned short type
??? 設備類型(以太網,幀中繼等)。在include/linux/if_arp.h 中有完整的類型列表。
unsigned short hard_header_len
? 以字節為單位的幀頭部長度。例如,以太網幀的頭是 14 字節。某種設備所支持幀的頭部長度在相應的設備頭文件中定義。對以太網來說,ETH_HLEN 在
<include/linux/if_ether.h>中定義。
unsigned char broadcast[MAX_ADDR_LEN]
? 鏈路層廣播地址。
unsigned char dev_addr[MAX_ADDR_LEN]
unsigned char addr_len
? dev_addr是設備的鏈路層地址,不要把它和IP 地址或者L3 地址混淆了。鏈路層地址的長度是 addr_len,以字節為單位。addr_len 的大小與設備類型有關。以太網地址的長度是8。
int promiscuity
promiscuity計數器來標識設備是否工作在混雜模式。之所以使用計數器而不是一個標志位的原因是:可能有多個用戶程序設置設備工作在混雜模式下。因此,每次進入混雜模式,計數器加一;退出混雜模式,計數器減一。只有計數器為0 時,設備才退出混雜模式。這個變量通常調用函數dev_set_promiscuity 來設置。
struct dev_mc_list *mc_list
? 指向dev_mc_list結構
int mc_count
? 設備多播地址的數量,它同樣表示mc_list所指向鏈表的長度。
int allmulti
? 如果是非零值,那么設備將監聽所有的多播地址。和 promiscuity 一樣,這個變量是一個計數器而不僅僅是一個布爾值。這是因為多個設備(比如VLAN和bonding
設備)可能獨立地要求監聽所有地址。如果這個變量的值從0變為非零,內核會調用函數dev_set_allmulti通知設備監聽所有的多播地址。如果這個值變為0,則停止監聽所有的多播地址。
1.4、?? ?協議相關
void *atalk_ptr
void *ip_ptr
void *dn_ptr
void *ip6_ptr
void *ec_ptr
void *ax25_ptr
這六個變量指向特定協議的數據結構,每個數據結構都包含協議私有的參數。例如,ip_ptr 指向一個 in_device 類型的結構(盡管 ip_ptr 的類型是 void*),它包含 IPv4相關的參數,其中包括設備的 IP 地址列表等。
1.5、?? ?流量管理
Linux 流量控制子系統的功能已經非常強大,并且已經成為 Linux 內核中的一個重要組件。相關的內核選項是 “Device drivers ->Networking support ->Networking options ->QoS and/or fair queueing”。net_device中的相關變量包括:
struct net_device *next_sched
? 被內核軟中斷使用。
struct Qdisc *qdisc
struct Qdisc *qdisc_sleeping
struct Qdisc *qdisc_ingress
struct list_head qdisc_list
? 這些變量管理設備的接收,發送隊列,并且可以被不同的cpu訪問。
spinlock_t queue_lock
spinlock_t ingress_lock
? 流量控制子系統為每個網絡設備定義了一個私有的發送隊列。 queue_lock用于避免并發的訪問(參見第11章)。ingress_lock 用于保護接收隊列。
unsigned long tx_queue_len
? 設備發送隊列的長度。如果內核中包含了流量控制子系統,這個變量可能沒有什么用(只有幾個排隊策略會使用它)。常見設備的 tx_queue_len 值(這個值可以通過sysfs文件系統修改(在/sys/class/net/device_name/目錄下)):

1.6、?? ?設備驅動程序相關
int (*init)(...)
void (*uninit)(...)
void (*destructor)(...)
int (*open)(...)
int (*stop)(...)
用于初始化,清除,銷毀,啟用和停止一個設備。這些函數并不是每個設備都會用到。
int (*hard_start_xmit)(...)
?發送一個幀。
int (*hard_header)(...)
?根據源和目標的第2層地址創建第2層報文頭。
int (*rebuild_header)(...)
?負責在傳送包之前重建第2導報文頭。
int (*set_mac_address)(...)
? 修改設備的 MAC 地址。如果設備不提供這個功能(比如網橋設備),可以把這個指針設置為NULL。
int (*change_mtu)(...)
? 修改設備的MTU,修改mtu 不會對設備驅動有任何影響,它只是讓協議棧軟件可以根據新的mtu 正確地處理分片。 新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!

總結

以上是生活随笔為你收集整理的Linux网络协议栈(三)——网络设备(1)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。