《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 可編程邏輯 > 其他 > Linux教學(xué)——如何學(xué)習(xí) Linux 內(nèi)核網(wǎng)絡(luò)協(xié)議棧

Linux教學(xué)——如何學(xué)習(xí) Linux 內(nèi)核網(wǎng)絡(luò)協(xié)議棧

2022-10-26
作者:土豆居士
來(lái)源:電子技術(shù)應(yīng)用專欄作家 一口Linux

  協(xié)議棧的細(xì)節(jié)

  下面將介紹一些內(nèi)核網(wǎng)絡(luò)協(xié)議棧中常常涉及到的概念,。

  sk_buff

  內(nèi)核顯然需要一個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)表示報(bào)文,這個(gè)結(jié)構(gòu)就是 sk_buff ( socket buffer 的簡(jiǎn)稱),,它等同于在<TCP/IP詳解 卷2>中描述的 BSD 內(nèi)核中的 mbuf,。

  sk_buff 結(jié)構(gòu)自身并不存儲(chǔ)報(bào)文內(nèi)容,,它通過多個(gè)指針指向真正的報(bào)文內(nèi)存空間:

  微信截圖_20221026155705.png

  sk_buff 是一個(gè)貫穿整個(gè)協(xié)議棧層次的結(jié)構(gòu),,在各層間傳遞時(shí),,內(nèi)核只需要調(diào)整 sk_buff 中的指針位置就行,。

  net_device

  內(nèi)核使用 net_device 表示網(wǎng)卡,。網(wǎng)卡可以分為物理網(wǎng)卡和虛擬網(wǎng)卡,。物理網(wǎng)卡是指真正能把報(bào)文發(fā)出本機(jī)的網(wǎng)卡,包括真實(shí)物理機(jī)的網(wǎng)卡以及VM虛擬機(jī)的網(wǎng)卡,,而像 tun/tap,,vxlan、veth pair 這樣的則屬于虛擬網(wǎng)卡的范疇,。

  如下圖所示,,每個(gè)網(wǎng)卡都有兩端,一端是協(xié)議棧(IP,、TCP,、UDP),另一端則有所區(qū)別,,對(duì)物理網(wǎng)卡來(lái)說,,這一端是網(wǎng)卡生產(chǎn)廠商提供的設(shè)備驅(qū)動(dòng)程序,而對(duì)虛擬網(wǎng)卡來(lái)說差別就大了,,正是由于虛擬網(wǎng)卡的存在,,內(nèi)核才能支持各種隧道封裝、容器通信等功能,。

  微信截圖_20221026155928.png

  socket & sock

  用戶空間通過 socket(),、bind(),、listen()、accept() 等庫(kù)函數(shù)進(jìn)行網(wǎng)絡(luò)編程,。而這里提到的 socket 和 sock 是內(nèi)核中的兩個(gè)數(shù)據(jù)結(jié)構(gòu),,其中 socket 向上面向用戶,而 sock 向下面向協(xié)議棧,。

  如下圖所示,,這兩個(gè)結(jié)構(gòu)實(shí)際上是一一對(duì)應(yīng)的。

  微信截圖_20221026155951.png

  注意到,,這兩個(gè)結(jié)構(gòu)上都有一個(gè)叫 ops 的指針, 但它們的類型不同,。socket 的 ops 是一個(gè)指向 struct proto_ops 的指針,sock 的 ops 是一個(gè)指向 struct proto 的指針, 它們?cè)诮Y(jié)構(gòu)被創(chuàng)建時(shí)確定,。

  回憶網(wǎng)絡(luò)編程中 socket() 函數(shù)的原型:

微信截圖_20221026160045.png

  實(shí)際上, socket->ops 和 sock->ops 由前兩個(gè)參數(shù) socket_family 和 socket_type 共同確定,。

  如果 socket_family 是最常用的 PF_INET 協(xié)議簇, 則 socket->ops 和 sock->ops 的取值就記錄在 INET 協(xié)議開關(guān)表中:

 微信截圖_20221026160135.png

  L3->L4

  我們知道網(wǎng)絡(luò)協(xié)議棧是分層的,但實(shí)際上,,具體到實(shí)現(xiàn),,內(nèi)核協(xié)議棧的分層只是邏輯上的,,本質(zhì)還是函數(shù)調(diào)用,。發(fā)送流程(上層調(diào)用下層)通常是直接調(diào)用(因?yàn)闆]有不確定性,比如TCP知道下面一定IP),,但接收過程不一樣了,,比如報(bào)文在 IP 層時(shí),它上面可能是 TCP,,也可能是 UDP,,或者是 ICMP 等等,所以接收過程使用的是注冊(cè)-回調(diào)機(jī)制,。

  還是以 INET 協(xié)議簇為例,,注冊(cè)接口是:

  微信截圖_20221026160156.png

  在內(nèi)核網(wǎng)絡(luò)子系統(tǒng)初始化時(shí),L4 層協(xié)議(如下面的 TCP 和 UDP)會(huì)被注冊(cè):

 微信截圖_20221026160213.png

  而在IP層,,查詢過路由后,,如果該報(bào)文是需要上送本機(jī)的,則會(huì)根據(jù)報(bào)文的 L4 協(xié)議,,送給不同的 L4 處理:

 微信截圖_20221026160253.png

  L2->L3

  L2->L3 如出一轍,。只不過注冊(cè)接口變成了:

  微信截圖_20221026160310.png

  誰(shuí)會(huì)注冊(cè)呢?顯然至少 IP 會(huì):

微信截圖_20221026160329.png

  而在報(bào)文接收過程中,,設(shè)備驅(qū)動(dòng)程序會(huì)將報(bào)文的 L3 類型設(shè)置到 skb->protocol,,然后在內(nèi)核 netif_receive_skb 收包時(shí),會(huì)根據(jù)這個(gè) protocol 調(diào)用不同的回調(diào)函數(shù):

 微信截圖_20221026160346.png

  Netfilter

  Netfilter 是報(bào)文在內(nèi)核協(xié)議棧必然會(huì)通過的路徑,,我們從下面這張圖就可以看到,,Netfilter 在內(nèi)核的 5 個(gè)地方設(shè)置了 HOOK 點(diǎn),,用戶可以通過配置 iptables 規(guī)則,在 HOOK 點(diǎn)對(duì)報(bào)文進(jìn)行過濾,、修改等操作,。

  微信截圖_20221026160406.png

  在內(nèi)核代碼中,我們時(shí)??梢?NF_HOOK 這樣的調(diào)用,。我的建議是,如果你暫時(shí)不考慮 Netfilter,,那么就直接跳過, 跟蹤 okfn 就行,。

  微信截圖_20221026160428.png

  dst_entry

  內(nèi)核需要確定收到的報(bào)文是應(yīng)該本地上送(local deliver)還是轉(zhuǎn)發(fā)(forward),對(duì)本機(jī)發(fā)送(local out)的報(bào)文需要確定是從哪個(gè)網(wǎng)卡發(fā)送出去,這都是內(nèi)核通過查詢 fib (forward information base, 轉(zhuǎn)發(fā)信息表) 確定,。fib 可以理解為一個(gè)數(shù)據(jù)庫(kù),,數(shù)據(jù)來(lái)源是用戶配置或者內(nèi)核自動(dòng)生成的路由。

  fib 查詢的輸入是報(bào)文 sk_buff,,輸出是 dst_entry. dst_entry 會(huì)被設(shè)置到 skb 上:

 微信截圖_20221026160448.png

  而 dst_entry 中最重要的是一個(gè) input 指針和 output 指針:

  微信截圖_20221026160506.png

微信截圖_20221026160524.png



 更多信息可以來(lái)這里獲取==>>電子技術(shù)應(yīng)用-AET<<

微信圖片_20210517164139.jpg

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn),。轉(zhuǎn)載的所有的文章,、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有,。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無(wú)法一一聯(lián)系確認(rèn)版權(quán)者,。如涉及作品內(nèi)容、版權(quán)和其它問題,,請(qǐng)及時(shí)通過電子郵件或電話通知我們,,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失,。聯(lián)系電話:010-82306118,;郵箱:[email protected]