linux 虚拟机大量udp请求失败_理解 Linux 网络栈:Linux 网络协议栈简单总结分析...
1. Linux 網(wǎng)絡路徑
1.1 發(fā)送端
1.1.1 應用層
(1) Socket
應用層的各種網(wǎng)絡應用程序基本上都是通過 Linux Socket 編程接口來和內(nèi)核空間的網(wǎng)絡協(xié)議棧通信的。Linux Socket 是從 BSD Socket 發(fā)展而來的,它是 Linux 操作系統(tǒng)的重要組成部分之一,它是網(wǎng)絡應用程序的基礎。從層次上來說,它位于應用層,是操作系統(tǒng)為應用程序員提供的 API,通過它,應用程序可以訪問傳輸層協(xié)議。
- socket 位于傳輸層協(xié)議之上,屏蔽了不同網(wǎng)絡協(xié)議之間的差異
- socket 是網(wǎng)絡編程的入口,它提供了大量的系統(tǒng)調(diào)用,構(gòu)成了網(wǎng)絡程序的主體
- 在Linux系統(tǒng)中,socket 屬于文件系統(tǒng)的一部分,網(wǎng)絡通信可以被看作是對文件的讀取,使得我們對網(wǎng)絡的控制和對文件的控制一樣方便。
UDP socket 處理過程
Linuxc/c++服務器開發(fā)高階視頻學習資料+主頁qun獲取
TCP Socket 處理過程
(2) 應用層處理流程
1.1.2 傳輸層
傳輸層的最終目的是向它的用戶提供高效的、可靠的和成本有效的數(shù)據(jù)傳輸服務,主要功能包括
(1)構(gòu)造 TCP segment
(2)計算 checksum
(3)發(fā)送回復(ACK)包
(4)滑動窗口(sliding windown)等保證可靠性的操作
TCP 協(xié)議棧的大致處理過程如下圖所示:
TCP 棧簡要過程:
UDP 棧簡要過程:
1.1.3 IP 網(wǎng)絡層 - 添加header 和 checksum,路由處理,IP fragmentation
網(wǎng)絡層的任務就是選擇合適的網(wǎng)間路由和交換結(jié)點, 確保數(shù)據(jù)及時傳送。網(wǎng)絡層將數(shù)據(jù)鏈路層提供的幀組成數(shù)據(jù)包,包中封裝有網(wǎng)絡層包頭,其中含有邏輯地址信息- -源站點和目的站點地址的網(wǎng)絡地址。其主要任務包括
(1)路由處理,即選擇下一跳
(2)添加 IP header
(3)計算 IP header checksum,用于檢測 IP 報文頭部在傳播過程中是否出錯
(4)可能的話,進行 IP 分片
(5)處理完畢,獲取下一跳的 MAC 地址,設置鏈路層報文頭,然后轉(zhuǎn)入鏈路層處理。
IP 頭:
IP 棧基本處理過程如下圖所示:
1.1.4 數(shù)據(jù)鏈路層
功能上,在物理層提供比特流服務的基礎上,建立相鄰結(jié)點之間的數(shù)據(jù)鏈路,通過差錯控制提供數(shù)據(jù)幀(Frame)在信道上無差錯的傳輸,并進行各電路上的動作系列。數(shù)據(jù)鏈路層在不可靠的物理介質(zhì)上提供可靠的傳輸。該層的作用包括:物理地址尋址、數(shù)據(jù)的成幀、流量控制、數(shù)據(jù)的檢錯、重發(fā)等。在這一層,數(shù)據(jù)的單位稱為幀(frame)。數(shù)據(jù)鏈路層協(xié)議的代表包括:SDLC、HDLC、PPP、STP、幀中繼等。
實現(xiàn)上,Linux 提供了一個 Network device 的抽象層,其實現(xiàn)在 linux/net/core/dev.c。具體的物理網(wǎng)絡設備在設備驅(qū)動中(driver.c)需要實現(xiàn)其中的虛函數(shù)。Network Device 抽象層調(diào)用具體網(wǎng)絡設備的函數(shù)。
1.1.5 物理層 - 物理層封裝和發(fā)送
1.1.6 簡單總結(jié)
1.2 接收端
1.2.1 物理層和數(shù)據(jù)鏈路層
簡要過程:
1.2.2 網(wǎng)絡層
1.2.3 傳輸層 (TCP/UDP)
1.2.4 接收端 - 應用層
1.2.5 報文接收過程簡單總結(jié)
2. Linux sk_buff struct 數(shù)據(jù)結(jié)構(gòu)和隊列(Queue)
2.1 sk_buff
(本章節(jié)摘選自 http://amsekharkernel.blogspot.com/2014/08/what-is-skb-in-linux-kernel-what-are.html)
2.1.1 sk_buff 是什么
當網(wǎng)絡包被內(nèi)核處理時,底層協(xié)議的數(shù)據(jù)被傳送更高層,當數(shù)據(jù)傳送時過程反過來。由不同協(xié)議產(chǎn)生的數(shù)據(jù)(包括頭和負載)不斷往下層傳遞直到它們最終被發(fā)送。因為這些操作的速度對于網(wǎng)絡層的表現(xiàn)至關重要,內(nèi)核使用一個特定的結(jié)構(gòu)叫 sk_buff, 其定義文件在 skbuffer.h。Socket buffer被用來在網(wǎng)絡實現(xiàn)層交換數(shù)據(jù)而不用拷貝來或去數(shù)據(jù)包 –這顯著獲得速度收益。
- sk_buff 是 Linux 網(wǎng)絡的一個核心數(shù)據(jù)結(jié)構(gòu),其定義文件在 skbuffer.h。
- socket kernel buffer (skb) 是 Linux 內(nèi)核網(wǎng)絡棧(L2 到 L4)處理網(wǎng)絡包(packets)所使用的 buffer,它的類型是 sk_buffer。簡單來說,一個 skb 表示 Linux 網(wǎng)絡棧中的一個 packet;TCP 分段和 IP 分組生產(chǎn)的多個 skb 被一個 skb list 形式來保存。
- struct sock 有三個 skb 隊列(sk_buffer queue),分別是 rx , tx 和 err。
它的主要結(jié)構(gòu)成員:
struct sk_buff {/* These two members must be first. */ # packet 可以存在于 list 或者 queue 中,這兩個成員用于鏈表處理struct sk_buff *next;struct sk_buff *prev;struct sk_buff_head *list; #該 packet 所在的 list...struct sock *sk; #跟該 skb 相關聯(lián)的 socketstruct timeval stamp; # packet 發(fā)送或者接收的時間,主要用于 packet sniffersstruct net_device *dev; #這三個成員跟蹤該 packet 相關的 devices,比如接收它的設備等struct net_device *input_dev;struct net_device *real_dev;union { #指向各協(xié)議層 header 結(jié)構(gòu)struct tcphdr *th;struct udphdr *uh;struct icmphdr *icmph;struct igmphdr *igmph;struct iphdr *ipiph;struct ipv6hdr *ipv6h;unsigned char *raw;} h;union {struct iphdr *iph;struct ipv6hdr *ipv6h;struct arphdr *arph;unsigned char *raw;} nh;union {unsigned char *raw;} mac;struct dst_entry *dst; #指向該 packet 的路由目的結(jié)構(gòu),告訴我們它會被如何路由到目的地char cb[40]; # SKB control block,用于各協(xié)議層保存私有信息,比如 TCP 的順序號和幀的重發(fā)狀態(tài)unsigned int len, #packet 的長度data_len,mac_len, # MAC header 長度csum; # packet 的 checksum,用于計算保存在 protocol header 中的校驗和。發(fā)送時,當 checksum offloading 時,不設置;接收時,可以由device計算unsigned char local_df, #用于 IPV4 在已經(jīng)做了分片的情況下的再分片,比如 IPSEC 情況下。cloned:1, #在 skb 被 cloned 時設置,此時,skb 各成員是自己的,但是數(shù)據(jù)是shared的nohdr:1, #用于支持 TSOpkt_type, #packet 類型ip_summed; # 網(wǎng)卡能支持的校驗和計算的類型,NONE 表示不支持,HW 表示支持,__u32 priority; #用于 QoSunsigned short protocol, # 接收 packet 的協(xié)議security;2.1.2 skb 的主要操作
(1)分配 skb = alloc_skb(len, GFP_KERNEL)
(2)添加 payload (skb_put(skb, user_data_len))
(3)使用 skb->push 添加 protocol header,或者 skb->pull 刪除 header
2.2 Linux 網(wǎng)絡棧使用的驅(qū)動隊列 (driver queue)
2.2.1 隊列
在 IP 棧和 NIC 驅(qū)動之間,存在一個 driver queue (驅(qū)動隊列)。典型地,它被實現(xiàn)為 FIFO ring buffer,簡單地可以認為它是固定大小的。這個隊列不包含 packet data,相反,它只是保存 socket kernel buffer (skb)的指針,而 skb 的使用如上節(jié)所述是貫穿內(nèi)核網(wǎng)絡棧處理過程的始終的。
該隊列的輸入時 IP 棧處理完畢的 packets。這些packets 要么是本機的應用產(chǎn)生的,要么是進入本機又要被路由出去的。被 IP 棧加入隊列的 packets 會被網(wǎng)絡設備驅(qū)動(hardware driver)取出并且通過一個數(shù)據(jù)通道(data bus)發(fā)到 NIC 硬件設備并傳輸出去。
在不使用 TSO/GSO 的情況下,IP 棧發(fā)到該隊列的 packets 的長度必須小于 MTU。
2.2.2 skb 大小 - 默認最大大小為 NIC MTU
絕大多數(shù)的網(wǎng)卡都有一個固定的最大傳輸單元(maximum transmission unit, MTU)屬性,它是該網(wǎng)絡設備能夠傳輸?shù)淖畲髱?#xff08;frame)的大小。對以太網(wǎng)來說,默認值為 1500 bytes,但是有些以太網(wǎng)絡可以支持巨幀(jumbo frame),最大能到 9000 bytes。在 IP 網(wǎng)絡棧內(nèi),MTU 表示能發(fā)給 NIC 的最大 packet 的大小。比如,如果一個應用向一個 TCP socket 寫入了 2000 bytes 數(shù)據(jù),那么 IP 棧需要創(chuàng)建兩個 IP packets 來保持每個 packet 的大小等于或者小于 1500 bytes。可見,對于大數(shù)據(jù)傳輸,相對較小的 MTU 會導致產(chǎn)生大量的小網(wǎng)絡包(small packets)并被傳入 driver queue。這成為 IP 分片 (IP fragmentation)。
下圖表示 payload 為 1500 bytes 的 IP 包,在 MTU 為 1000 和 600 時候的分片情況:
備注:
以上資料是從網(wǎng)絡上獲取的各種資料整理而來
這一塊本身就比較復雜,而且不同的 linux 內(nèi)核的版本之間也有差異,文中的內(nèi)容還需要進一步加工,錯誤在所難免。
原文:理解 Linux 網(wǎng)絡棧(1):Linux 網(wǎng)絡協(xié)議棧簡單總結(jié)
總結(jié)
以上是生活随笔為你收集整理的linux 虚拟机大量udp请求失败_理解 Linux 网络栈:Linux 网络协议栈简单总结分析...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: eas 在linux下安装_Linux下
- 下一篇: linux 消息对lie_Linux进程