注,原文來自 https://blog.mygraphql.com/zh/notes/low-tec/network/kernel-net-stack/ 锌钮。如你看到的轉(zhuǎn)載圖片不清诞帐,請回到原文。
目錄
- 目錄
- 《網(wǎng)絡(luò)包的內(nèi)核漂流記》系列介紹
- ISO 網(wǎng)絡(luò)模型
- 網(wǎng)絡(luò)包接收流程概述
- 網(wǎng)絡(luò)包接收步驟
- 結(jié)尾
- 相關(guān)
《網(wǎng)絡(luò)包的內(nèi)核漂流記》系列介紹
大家知道,網(wǎng)絡(luò)數(shù)據(jù)來源于網(wǎng)線轮洋、光纖、無線電波上的比特(bit)抬旺,然后到網(wǎng)卡弊予,到內(nèi)核黔漂,最后到應(yīng)用進程 socket搁胆。事情好像很簡單。但如果是 SRE/DevOps 或是 Performance Engineer 淹辞,需要做細致的監(jiān)控和優(yōu)化時床未,這些顯然是不夠的竭翠。引用本文主要參考作者的原話:
Optimizing and monitoring the network stack is impossible unless you carefully read and understand how it works. You cannot monitor code you don’t understand at a deep level.
除非您仔細閱讀并了解其工作原理,否則無法優(yōu)化和監(jiān)控網(wǎng)絡(luò)堆棧薇搁。 您無法深入監(jiān)控您不理解的代碼斋扰。
—— Joe Damato
《網(wǎng)絡(luò)包的內(nèi)核漂流記》嘗試分析和跟蹤一個網(wǎng)絡(luò)包在內(nèi)核各子系統(tǒng)間的流轉(zhuǎn)和觸發(fā)的協(xié)作。
開始前先做個預告啃洋,《網(wǎng)絡(luò)包的內(nèi)核漂流記》 系統(tǒng)(將)包括:
- Part 1: 圖解網(wǎng)絡(luò)包接收流程
- Part 2: BPF 跟蹤網(wǎng)絡(luò)包的內(nèi)核漂流
- 我將演示如何用 bpftrace 蹤網(wǎng)絡(luò)包的內(nèi)核漂流传货。
為免嚇跑人,還是老套路宏娄,多圖少代碼问裕。不過有的圖有點點復雜。??
本系列主要參考:Monitoring and Tuning the Linux Networking Stack: Receiving Data 孵坚。是的粮宛,這是篇被轉(zhuǎn)載窥淆、參考到泛濫的文章。幾乎你能在網(wǎng)上找到的所有講 Linux 網(wǎng)卡和網(wǎng)絡(luò)棧收發(fā)的文章巍杈,都會參考它忧饭。但有句話是:
一千個人眼中就有一千個 “哈姆雷特”。 —— 無名高人
風格筷畦、樣式词裤、本文的交互閱讀方式 ??
雖然不是寫書,不過還是說明一下吧:
- 我不打算像八股文的 Linux 內(nèi)核文章一樣鳖宾,貼一堆源碼吼砂,讓文章看起來內(nèi)容很豐滿但無趣。我用交互 SVG 圖片的的方法去引用源碼 ?? 攘滩。
- https://blog.mygraphql.com/zh/notes/low-tec/network/kernel-net-stack/ 的原文是 SVG 圖片帅刊。如果你是在其它地方看到本文,請轉(zhuǎn)回原文漂问。
- 正確瀏覽 SVG 圖片的姿勢是瀏覽器中圖片處右鍵赖瞒,選擇 “新 Tab 中打開圖片” 。
- SVG 圖片可以點擊鏈接蚤假,直接跳轉(zhuǎn)到相應(yīng)內(nèi)核源碼網(wǎng)頁栏饮,精確到源碼行。 是的磷仰,你不需要 git clone那大陀源碼 ?? 袍嬉,只需要一個瀏覽器就可以。如果你在電腦前開雙屏灶平,結(jié)合源碼和圖看伺通,相信我,內(nèi)核源碼不是什么天書逢享,你能看懂大部分的罐监。
- 瀏覽內(nèi)核源碼我用 https://elixir.bootlin.com/linux/v5.4/source 。這個是很好的內(nèi)核源碼瀏覽網(wǎng)站瞒爬,內(nèi)置源碼引用跳轉(zhuǎn)和搜索功能弓柱。
ISO 網(wǎng)絡(luò)模型
我并不太學院派,但回顧一下基礎(chǔ)知識還是必須的:
圖:OSI 基本參考模型和 TCP/IP 堆棧之間的邏輯映射侧但,來自這里
下文把第 n 層縮寫為 Ln矢空,如 TRANSPORT 層是第 4 層,縮寫為 L4
禀横。
網(wǎng)絡(luò)包接收流程概述
網(wǎng)絡(luò)包接收步驟
從代碼細節(jié)看屁药,網(wǎng)絡(luò)包接收步驟比較多。下面劃分為 4 步來敘述:
- 初始化與配置
- IRQ 處理
- SoftIRQ 中加載網(wǎng)絡(luò)包到內(nèi)存
- SoftIRQ 中推送網(wǎng)絡(luò)包到上層
初始化與配置
首先說說柏锄,內(nèi)核啟動時者祖,網(wǎng)絡(luò)子系統(tǒng)的初始化流程立莉。
- 創(chuàng)建 ksoftirqd 內(nèi)核線程(每個 CPU 一個)
- ksoftirqd 線程開始在
run_ksoftirqd
函數(shù)中執(zhí)行它們的處理循環(huán)绢彤。 - 接下來七问,為每個 CPU 創(chuàng)建一個專用的
softnet_data
對象。茫舶。這些對象又引用了其它處理網(wǎng)絡(luò)數(shù)據(jù)的重要對象械巡。其中之一是下文會提到poll_list(輪詢列表)
。 程序通過調(diào)用napi_schedule()
函數(shù)或來自設(shè)備驅(qū)動程序的其他 NAPI API 來添加 NAPI 到poll_list
中 饶氏。 - 然后讥耗,
net_dev_init()
通過調(diào)用open_softirq()
向 softirq 系統(tǒng)注冊NET_RX_SOFTIRQ
軟中斷。注冊的處理函數(shù)稱為“net_rx_action()
”疹启。這是softirq內(nèi)核線程將執(zhí)行以處理數(shù)據(jù)包的函數(shù)古程。
不要心急,第 4 步以后的步驟喊崖,將在下文繼續(xù)挣磨。因需要鋪墊一下其它內(nèi)容。
IRQ 處理
下面荤懂,從網(wǎng)卡在網(wǎng)絡(luò)上接收到數(shù)據(jù)開始茁裙,說說前期的包處理過程。
- 網(wǎng)卡從網(wǎng)絡(luò)接收數(shù)據(jù)。
- NIC 使用 DMA 將網(wǎng)絡(luò)數(shù)據(jù)寫入 RAM廊宪。
- NIC 拉起 IRQ 位矾瘾。
- 設(shè)備驅(qū)動之前注冊的IRQ處理程序被執(zhí)行。
- 清除網(wǎng)卡上的 IRQ箭启,以便它可以為新的數(shù)據(jù)包到達生成 IRQ壕翩。
- 通過調(diào)用
napi_schedule()
函數(shù),異步觸發(fā) NAPI softIRQ 輪詢循環(huán)册烈。
有了以上鋪墊知識后戈泼,我們回頭看看上節(jié)的「初始化與配置」中未講解的步驟:
5. 驅(qū)動中對napi_schedule()
的調(diào)用將驅(qū)動的NAPI poll對象添加到當前CPU的poll_list
中。
6. 標記 softirq 拉起位赏僧,以便這個 CPU 上的 ksoftirqd
進程知道有數(shù)據(jù)包要處理大猛。
7. run_ksoftirqd()
函數(shù)被調(diào)用(由ksoftirq
內(nèi)核線程循環(huán)運行)執(zhí)行。
8. __do_softirq()
被調(diào)用檢查softirq 拉起位
淀零,看到一個 softIRQ 拉起挽绩, 并調(diào)用拉起位相關(guān)的softIRQ注冊的處理程序:net_rx_action()
,后續(xù)的網(wǎng)絡(luò)接收數(shù)據(jù)所有重要的工作將在這個函數(shù)中完成驾中。
SoftIRQ 中加載網(wǎng)絡(luò)包到內(nèi)存
這個圖比較簡單唉堪,不多說模聋。
SoftIRQ 中推送網(wǎng)絡(luò)包到上層
在Receive Packet Steering(RPS)
被禁用的情況流程為:
1. netif_receive_skb()
將數(shù)據(jù)傳遞給 __netif_receive_core()
。
6. __netif_receive_core()
將數(shù)據(jù)傳送到 TAP(監(jiān)聽模塊)
(如 PCAP
)唠亚。
7. __netif_receive_core()
將數(shù)據(jù)傳遞給已注冊的協(xié)議層處理程序链方。在大多數(shù)情況下,是 IPv4 協(xié)議棧注冊的 ip_rcv
函數(shù)灶搜。
使用Receive Packet Steering(RPS)
的情況流程祟蚀,這里不說了,我暫時未分析到割卖。
如果你心急前酿,想了解 Receive Packet Steering(RPS)
是什么鬼,那么:
- https://01.org/linuxgraphics/gfx-docs/drm/networking/scaling.html#rps-receive-packet-steering
- https://www.kernel.org/doc/Documentation/networking/scaling.txt
- https://www.alibabacloud.com/blog/597128
結(jié)尾
沒太多好說的鹏溯,好好學習罢维,天天向上。笨人做笨事丙挽,做最好的自己肺孵。
相關(guān)
如果你關(guān)注云原生,也使用到 Calico取试,那么以下這篇兄弟文章你可能喜歡: