Linux Bridge和Tap關(guān)系詳解
Linux Bridge介紹
Bridge(橋)是Linux上用來(lái)做TCP/IP二層協(xié)議交換的設(shè)備,與現(xiàn)實(shí)世界中的交換機(jī)功能相似。Bridge設(shè)備實(shí)例可以和Linux上其他網(wǎng)絡(luò)設(shè)備實(shí)例連接,既attach一個(gè)從設(shè)備,類(lèi)似于在現(xiàn)實(shí)世界中的交換機(jī)和一個(gè)用戶終端之間連接一根網(wǎng)線。當(dāng)有數(shù)據(jù)到達(dá)時(shí),Bridge會(huì)根據(jù)報(bào)文中的MAC信息進(jìn)行廣播、轉(zhuǎn)發(fā)、丟棄處理。
如圖所示,Bridge的功能主要在內(nèi)核里實(shí)現(xiàn)。當(dāng)一個(gè)從設(shè)備被attach到Bridge上時(shí),相當(dāng)于現(xiàn)實(shí)世界里交換機(jī)的端口被插入了一根連有終端的網(wǎng)線。這時(shí)在內(nèi)核程序里,netdev_rx_handler_register()被調(diào)用,一個(gè)用于接受數(shù)據(jù)的回調(diào)函數(shù)被注冊(cè)。以后每當(dāng)這個(gè)從設(shè)備收到數(shù)據(jù)時(shí)都會(huì)調(diào)用這個(gè)函數(shù)可以把數(shù)據(jù)轉(zhuǎn)發(fā)到Bridge上。當(dāng)Bridge接收到此數(shù)據(jù)時(shí),br_handle_frame()被調(diào)用,進(jìn)行一個(gè)和現(xiàn)實(shí)世界中的交換機(jī)類(lèi)似的處理過(guò)程:判斷包的類(lèi)別(廣播/單點(diǎn)),查找內(nèi)部MAC端口映射表,定位目標(biāo)端口號(hào),將數(shù)據(jù)轉(zhuǎn)發(fā)到目標(biāo)端口或丟棄,自動(dòng)更新內(nèi)部MAC端口映射表以自我學(xué)習(xí)。
Linux內(nèi)核支持網(wǎng)口的橋接(目前只支持以太網(wǎng)接口)。但是與單純的交換機(jī)不同,交換機(jī)只是一個(gè)二層設(shè)備,對(duì)于接收到的報(bào)文,要么轉(zhuǎn)發(fā)、要么丟棄。小型的交換機(jī)里面只需要一塊交換芯片即可,并不需要CPU。而運(yùn)行著Linux內(nèi)核的機(jī)器本身就是一臺(tái)主機(jī),有可能就是網(wǎng)絡(luò)報(bào)文的目的地。其收到的報(bào)文除了轉(zhuǎn) 發(fā)和丟棄,還可能被送到網(wǎng)絡(luò)協(xié)議棧的上層(網(wǎng)絡(luò)層),從而被自己消化。
網(wǎng)橋的功能
概括來(lái)說(shuō),網(wǎng)橋?qū)崿F(xiàn)最重要的兩點(diǎn):
1.MAC學(xué)習(xí):學(xué)習(xí)MAC地址,起初,網(wǎng)橋是沒(méi)有任何地址與端口的對(duì)應(yīng)關(guān)系的,它發(fā)送數(shù)據(jù),還是得想HUB一樣,但是每發(fā)送一個(gè)數(shù)據(jù),它都會(huì)關(guān)心數(shù)據(jù)包的來(lái)源MAC是從自己的哪個(gè)端口來(lái)的,由于學(xué)習(xí),建立地址-端口的對(duì)照表(CAM表)。
2.報(bào)文轉(zhuǎn)發(fā):每發(fā)送一個(gè)數(shù)據(jù)包,網(wǎng)橋都會(huì)提取其目的MAC地址,從自己的地址-端口對(duì)照表(CAM表)中查找由哪個(gè)端口把數(shù)據(jù)包發(fā)送出去。
網(wǎng)橋配置ip
Bridge可以設(shè)置IP地址,當(dāng)一個(gè)bridge0擁有IP后,Linux便可以通過(guò)路由表或者IP表規(guī)則在三層定位bridge0,此時(shí)相當(dāng)于Linux擁有了另外一個(gè)隱藏的虛擬網(wǎng)卡和Bridge的隱藏端口相連。當(dāng)一個(gè)設(shè)備被attach到Bridge上時(shí),那個(gè)設(shè)備的IP會(huì)變的無(wú)效,Linux不再使用那個(gè)IP在三層接受數(shù)據(jù)。
對(duì)于一個(gè)被attach到Bridge上的設(shè)備來(lái)說(shuō),只有它收到數(shù)據(jù)時(shí),此包數(shù)據(jù)才會(huì)被轉(zhuǎn)發(fā)到Bridge上,進(jìn)而完成查表廣播等后續(xù)操作。當(dāng)請(qǐng)求是發(fā)送類(lèi)型時(shí),數(shù)據(jù)是不會(huì)被轉(zhuǎn)發(fā)到Bridge上的,它會(huì)尋找下一個(gè)發(fā)送出口。
網(wǎng)橋處理包原則
網(wǎng)橋需要維護(hù)一個(gè)MAC地址-端口映射表(CAM),端口是指網(wǎng)橋自身提供的端口,而MAC地址是指與端口相連的另一端的MAC地址。
網(wǎng)橋處理包遵循以下幾條原則:
1.在一個(gè)接口上接收的包不會(huì)再在那個(gè)接口上發(fā)送這個(gè)數(shù)據(jù)包;
2.每個(gè)接收到的數(shù)據(jù)包都要學(xué)習(xí)其源地址;
3.如果數(shù)據(jù)包是多播或廣播包,則要在同一個(gè)網(wǎng)段中除了接收端口外的其他所有端口發(fā)送這個(gè)數(shù)據(jù)包,如果上層協(xié)議棧對(duì)多播包感興趣,則需要把數(shù)據(jù)包提交給上層協(xié)議棧;
4.如果數(shù)據(jù)包的目的MAC地址不能再CAM表中找到,則要在同一個(gè)網(wǎng)段中除了接收端口外的其他所有端口發(fā)送這個(gè)數(shù)據(jù)包;
5.如果能夠在CAM表中查詢(xún)到目的MAC地址,則在特定的端口上發(fā)送這個(gè)數(shù)據(jù)包,如果發(fā)送端口和接收端口是同一端口則不發(fā)送。
Tap設(shè)備介紹
TAP設(shè)備是一種讓用戶態(tài)程序向內(nèi)核協(xié)議棧注入數(shù)據(jù)的設(shè)備,工作在二層。做為虛擬網(wǎng)卡驅(qū)動(dòng),Tap驅(qū)動(dòng)程序的數(shù)據(jù)接收和發(fā)送并不直接和真實(shí)網(wǎng)卡打交道,而是通過(guò)用戶態(tài)來(lái)轉(zhuǎn)交。Tap驅(qū)動(dòng)是利用設(shè)備文件實(shí)現(xiàn)用戶態(tài)和核心態(tài)的數(shù)據(jù)交互。
從結(jié)構(gòu)上來(lái)說(shuō),Tap驅(qū)動(dòng)并不單純是實(shí)現(xiàn)網(wǎng)卡驅(qū)動(dòng),同時(shí)它還實(shí)現(xiàn)了字符設(shè)備驅(qū)動(dòng)部分。以字符設(shè)備的方式連接用戶態(tài)和核心態(tài)。下面是示意圖:
Tap驅(qū)動(dòng)程序中包含兩個(gè)部分,一部分是字符設(shè)備驅(qū)動(dòng),還有一部分是網(wǎng)卡驅(qū)動(dòng)部分。利用網(wǎng)卡驅(qū)動(dòng)部分接收來(lái)自TCP/IP協(xié)議棧的網(wǎng)絡(luò)分包并發(fā)送或者反過(guò)來(lái)將接收到的網(wǎng)絡(luò)分包傳給協(xié)議棧處理,而字符驅(qū)動(dòng)部分則將網(wǎng)絡(luò)分包在內(nèi)核與用戶態(tài)之間傳送,模擬物理鏈路的數(shù)據(jù)接收和發(fā)送。Tap驅(qū)動(dòng)很好的實(shí)現(xiàn)了兩種驅(qū)動(dòng)的結(jié)合。
Tap驅(qū)動(dòng)處理流程
如圖所示,當(dāng)一個(gè)TAP設(shè)備被創(chuàng)建時(shí),在Linux設(shè)備文件目錄下將會(huì)生成一個(gè)對(duì)應(yīng)char設(shè)備,用戶程序可以像打開(kāi)普通文件一樣打開(kāi)這個(gè)文件進(jìn)行讀寫(xiě);Linux protocol statck是Linux內(nèi)核的tcp/ip協(xié)議棧。當(dāng)執(zhí)行write()操作時(shí),數(shù)據(jù)進(jìn)入TAP設(shè)備,此時(shí)對(duì)于Linux網(wǎng)絡(luò)層來(lái)說(shuō),相當(dāng)于TAP設(shè)備收到了一包數(shù)據(jù),請(qǐng)求內(nèi)核接受它,如同普通的物理網(wǎng)卡從外界收到一包數(shù)據(jù)一樣,不同的是其實(shí)數(shù)據(jù)來(lái)自Linux上的一個(gè)用戶程序。Linux收到此數(shù)據(jù)后將根據(jù)網(wǎng)絡(luò)配置進(jìn)行后續(xù)處理,從而完成了用戶程序向Linux內(nèi)核網(wǎng)絡(luò)層注入數(shù)據(jù)的功能。當(dāng)用戶程序執(zhí)行read()請(qǐng)求時(shí),相當(dāng)于向內(nèi)核查詢(xún)TAP設(shè)備上是否有需要被發(fā)送出去的數(shù)據(jù),有的話取出到用戶程序里,完成TAP設(shè)備的發(fā)送數(shù)據(jù)功能。針對(duì)TAP設(shè)備的一個(gè)形象的比喻是:使用TAP設(shè)備的應(yīng)用程序相當(dāng)于另外一臺(tái)計(jì)算機(jī),TAP設(shè)備是本機(jī)的一個(gè)網(wǎng)卡,他們之間相互連接。應(yīng)用程序通過(guò)read()/write()操作,和本機(jī)網(wǎng)絡(luò)核心進(jìn)行通訊。
*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。