Linux 网络协议栈开发—— 二层桥实现原理
網(wǎng)橋原理:
網(wǎng)橋工作在鏈路層,所以它是二層的東西,對(duì)于以太網(wǎng)來(lái)說(shuō)網(wǎng)橋和二層網(wǎng)絡(luò)設(shè)備交換機(jī)的工作方式幾乎是一樣的,每個(gè)交換機(jī)包含一系列以太網(wǎng)接口,交換機(jī)通過(guò)其內(nèi)部的硬件交換芯片實(shí)現(xiàn)對(duì)這些以太網(wǎng)接口出入報(bào)文的二層接收轉(zhuǎn)發(fā)及過(guò)濾等二層qos功能,網(wǎng)橋在功能上和交換機(jī)幾乎是一樣的,只不過(guò)它是由軟件實(shí)現(xiàn)這些功能。
下圖是交換機(jī)和網(wǎng)橋的內(nèi)部實(shí)現(xiàn)原理簡(jiǎn)圖:
二層交換機(jī)內(nèi)部實(shí)現(xiàn)簡(jiǎn)圖
網(wǎng)橋內(nèi)部實(shí)現(xiàn)簡(jiǎn)圖
如上圖,可以把網(wǎng)橋本身看做一個(gè)二層交換機(jī),該交換機(jī)下面有eth0、usb1、vlan2、wlan3共4個(gè)接口,每個(gè)網(wǎng)橋下可以有很多個(gè)接口,不考慮STP生成樹(shù)協(xié)議的話,可以認(rèn)為網(wǎng)橋下接口是由用戶配置的,普遍用brctl應(yīng)用程序工具生成網(wǎng)橋,并在每個(gè)網(wǎng)橋下增加和刪除接口,brctl使用舉例如下:
初始情況下,沒(méi)有網(wǎng)橋,由命令“brctl addbr br0”創(chuàng)建一個(gè)網(wǎng)橋br0,然后可以觀察到創(chuàng)建了網(wǎng)橋br0,此時(shí)它底下還沒(méi)有接口,然后由命令“brctl addif br0 XXX”在網(wǎng)橋br0下加入接口eth1、eth2,然后可以觀察到網(wǎng)橋br0底下有這兩個(gè)接口;同時(shí)網(wǎng)橋br0的MAC地址表還加入了兩個(gè)靜態(tài)的MAC地址,分別是接口eth1和eth2的MAC地址,這時(shí)如果從eth1接口進(jìn)入屬于網(wǎng)橋br0的報(bào)文,并且該報(bào)文的目的MAC地址與eth2接口的MAC地址相同,那么報(bào)文將被從eth2接口轉(zhuǎn)發(fā)出去,并且會(huì)記錄該報(bào)文的源MAC地址和進(jìn)入接口eth1的對(duì)應(yīng)關(guān)系作為網(wǎng)橋br0的一個(gè)動(dòng)態(tài)MAC地址條目。
再如,我們的網(wǎng)關(guān)設(shè)備做測(cè)試時(shí),如需測(cè)試二層業(yè)務(wù)流性能,經(jīng)常把wan接口和vlan1接口做橋接,然后即可打雙向二層業(yè)務(wù)流,同樣是通過(guò)網(wǎng)橋?qū)W習(xí)兩個(gè)接口進(jìn)入報(bào)文的源MAC地址和進(jìn)入接口的對(duì)應(yīng)關(guān)系,實(shí)現(xiàn)網(wǎng)橋的兩個(gè)接口對(duì)打二層業(yè)務(wù)流,由此可見(jiàn),這和二層交換機(jī)的MAC地址學(xué)習(xí)和轉(zhuǎn)發(fā)的道理是一樣的。
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【977878001】整理一些個(gè)人覺(jué)得比較好得學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!!!前100進(jìn)群領(lǐng)取,額外贈(zèng)送一份價(jià)值699的內(nèi)核資料包(含視頻教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)內(nèi)核資料直通車:Linux內(nèi)核源碼技術(shù)學(xué)習(xí)路線+視頻教程代碼資料
學(xué)習(xí)直通車:Linux內(nèi)核源碼/內(nèi)存調(diào)優(yōu)/文件系統(tǒng)/進(jìn)程管理/設(shè)備驅(qū)動(dòng)/網(wǎng)絡(luò)協(xié)議棧
此外,linux的網(wǎng)橋同樣還實(shí)現(xiàn)了多種多樣的報(bào)文處理功能,同樣依托netfilter框架,通過(guò)不同的hook點(diǎn)掛載不同的包處理環(huán)節(jié),其qos功能可以比二層交換機(jī)還要豐富。
1、linux的網(wǎng)橋?qū)崿F(xiàn):
1.1、涉及文件:
Linux網(wǎng)橋?qū)崿F(xiàn)在代碼樹(shù)的net/bridge/目錄下,主要文件如下:
- l br.c:網(wǎng)橋模塊初始化;
- l br_device.c:網(wǎng)橋net_device的ops實(shí)現(xiàn);
- l br_fdb.c:網(wǎng)橋的MAC地址表實(shí)現(xiàn);
- l br_forward.c:網(wǎng)橋的報(bào)文轉(zhuǎn)發(fā)邏輯實(shí)現(xiàn);
- l br_if.c:網(wǎng)橋及橋端口的創(chuàng)建增刪操作;
- l br_input.c:網(wǎng)橋的報(bào)文處理函數(shù);
- l br_ioctl.c:網(wǎng)橋的用戶ioctl接口;
- l br_netfilter.c:網(wǎng)橋的netfilter框架及默認(rèn)掛載的hook;
- l br_netlink.c:網(wǎng)橋的netlink接口;
- l br_notify.c:網(wǎng)橋的內(nèi)核通知鏈;
- l 其余文件為網(wǎng)橋的STP協(xié)議相關(guān)和默認(rèn)的netfilter處理函數(shù)實(shí)現(xiàn);
1.2、重要數(shù)據(jù)結(jié)構(gòu):
1.2.1、網(wǎng)橋創(chuàng)建:
我們知道linux內(nèi)核協(xié)議棧的鏈路層中,任何一個(gè)收發(fā)實(shí)體都是以結(jié)構(gòu)體net_device描述的,這一個(gè)個(gè)的收發(fā)實(shí)體可以是有實(shí)際物理設(shè)備支持的,如常見(jiàn)的以太網(wǎng)卡設(shè)備ethX、usb網(wǎng)卡設(shè)備、無(wú)線網(wǎng)卡設(shè)備等等,也可以是沒(méi)有實(shí)際物理設(shè)備支持的虛擬網(wǎng)卡設(shè)備,如vlan接口、網(wǎng)橋接口,之所以這樣做是因?yàn)樵趦?nèi)核中對(duì)收發(fā)實(shí)體的一切處理邏輯都是統(tǒng)一的接口,事實(shí)上這體現(xiàn)的就是linux內(nèi)核面向?qū)ο蟮闹匾枷搿?/p>
所以每一個(gè)網(wǎng)橋在linux內(nèi)核中也都是以net_device結(jié)構(gòu)體描述,不同的是網(wǎng)橋net_device的私貨部分是結(jié)構(gòu)體net_bridge,它描述了網(wǎng)橋與其他類型net_device諸如以太網(wǎng)卡設(shè)備、vlan接口等的區(qū)別,事實(shí)上不同類型的net_device,其區(qū)別主要是通過(guò)私貨部分標(biāo)識(shí),對(duì)于網(wǎng)橋net_device它的私貨就是結(jié)構(gòu)體net_bridge,如下圖:
如不考慮STP生成樹(shù)協(xié)議部分的內(nèi)容,net_bridge結(jié)構(gòu)最值得注意的字段如下:
1、dev:它標(biāo)識(shí)該網(wǎng)橋自身的net_device,對(duì)于IP層及以上協(xié)議,鏈路層可見(jiàn)的是網(wǎng)橋,而不是網(wǎng)橋底下的接口,所以上層操作的net_device都是網(wǎng)橋的net_device;另外網(wǎng)橋自身的net_device也是區(qū)分不同網(wǎng)橋的依據(jù),這些是該字段存在的重要意義;
2、ageing_time:動(dòng)態(tài)MAC地址的老化時(shí)間;
3、stp_enabled:標(biāo)識(shí)該網(wǎng)橋是否開(kāi)啟STP功能,默認(rèn)為關(guān)閉,本文不討論STP協(xié)議相關(guān)的內(nèi)容
創(chuàng)建了一個(gè)網(wǎng)橋就如同創(chuàng)建了一個(gè)交換機(jī),但此時(shí)這個(gè)“交換機(jī)”底下還沒(méi)有接口
用戶應(yīng)用程序(典型如brctl)創(chuàng)建網(wǎng)橋的過(guò)程如下:
創(chuàng)建網(wǎng)橋的核心函數(shù)是br_add_bridge,它創(chuàng)建了網(wǎng)橋的net_device并將其注冊(cè)進(jìn)內(nèi)核,注意用戶創(chuàng)建網(wǎng)橋時(shí)只需傳入網(wǎng)橋名稱即可;
網(wǎng)橋net_device的私貨是結(jié)構(gòu)體net_bridge,new_bridge_dev函數(shù)對(duì)它進(jìn)行初始化,主要內(nèi)容包括:
- 創(chuàng)建了網(wǎng)橋自身的net_device并由私貨回指(br->dev= dev);
- 設(shè)置默認(rèn)關(guān)閉STP協(xié)議(br->stp_enabled= BR_NO_STP);
- 設(shè)置網(wǎng)橋的默認(rèn)動(dòng)態(tài)MAC地址老化時(shí)間為300秒(br->ageing_time= 300 * HZ);
- 開(kāi)啟動(dòng)態(tài)MAC地址老化定時(shí)器(br_stp_timer_init(br));
1.2.2、網(wǎng)橋接口添加:
創(chuàng)建網(wǎng)橋后,需要再加入接口,網(wǎng)橋的每一個(gè)接口在linux內(nèi)核中以net_bridge_port結(jié)構(gòu)體描述,在內(nèi)核中稱為橋端口,如下:
同樣如果不考慮STP協(xié)議相關(guān)內(nèi)容,只需關(guān)注如下字段:
- 1、br:標(biāo)識(shí)該橋端口屬于哪個(gè)網(wǎng)橋;
- 2、dev:標(biāo)識(shí)該橋端口實(shí)際對(duì)應(yīng)哪個(gè)接口;
- 3、state:標(biāo)識(shí)該橋端口的狀態(tài),一般為BR_STATE_FORWARDING即轉(zhuǎn)發(fā);
在創(chuàng)建好網(wǎng)橋后,應(yīng)用程序通過(guò)網(wǎng)橋的ops在網(wǎng)橋中加入接口,過(guò)程如下:
有了網(wǎng)橋,并在網(wǎng)橋下加入了接口,那么該網(wǎng)橋就可以發(fā)揮二層交換機(jī)的作用了。需要注意的問(wèn)題如下:
1、同一個(gè)接口不能作為不同網(wǎng)橋的橋端口;
2、網(wǎng)橋下的橋端口,都必須是混雜模式,但網(wǎng)橋自身不一定是混雜模式,往往在有特殊需求時(shí)如需要抓包時(shí),會(huì)把網(wǎng)橋自身接口設(shè)置為混雜模式,即網(wǎng)橋下所有橋端口接收到的報(bào)文都要送給本機(jī)一份;
3、每創(chuàng)建一個(gè)橋端口,都會(huì)把該橋端口對(duì)應(yīng)接口的MAC地址作為靜態(tài)MAC地址記錄在所屬網(wǎng)橋的MAC地址表中,靜態(tài)MAC地址不會(huì)被老化,因?yàn)槟康牡刂肥窃摻涌贛AC地址,說(shuō)明是送給該接口所在主機(jī)的報(bào)文即送本地的報(bào)文,所以不能老化掉這樣的MAC地址;
4、網(wǎng)橋自身接口的mtu和MAC地址是其底下所有橋接口的mtu最小值和MAC地址最小值,都也可以由用戶配置修改;
5、不考慮STP協(xié)議情況下,橋端口的狀態(tài)是轉(zhuǎn)發(fā)(BR_STATE_FORWARDING),一般情況下不必考慮橋端口的其他狀態(tài);
2、網(wǎng)橋報(bào)文接收處理:
前面已經(jīng)提到,linux內(nèi)核對(duì)于報(bào)文收發(fā)處理使用統(tǒng)一的接口,在報(bào)文接收處理中,都是由驅(qū)動(dòng)層接收到報(bào)文后調(diào)用函數(shù)netif_receive_skb進(jìn)入?yún)f(xié)議棧處理,網(wǎng)橋的處理入口函數(shù)為handle_bridge,實(shí)質(zhì)處理函數(shù)是br_handle_frame,流程如下:
結(jié)合上圖,網(wǎng)橋處理的重點(diǎn)如下:
1、需要進(jìn)行橋接處理的報(bào)文,其輸入接口必須屬于某網(wǎng)橋;
2、暫不考慮STP協(xié)議報(bào)文的處理,對(duì)于上圖重點(diǎn)關(guān)注“報(bào)文轉(zhuǎn)發(fā)流程”框之后的內(nèi)容;
3、橋接處理前會(huì)檢查用戶是否通過(guò)ebtables工具在鏈路層對(duì)報(bào)文進(jìn)行過(guò)濾或其他處理,ebtables工具類似iptables工具,可以加不同的規(guī)則,區(qū)別在于它工作在鏈路層,這實(shí)現(xiàn)了類似二層交換機(jī)的qos功能;
4、每次報(bào)文處理都首先進(jìn)行動(dòng)態(tài)MAC地址的學(xué)習(xí)或更新老化時(shí)間;
5、對(duì)于某些操作,如對(duì)網(wǎng)橋進(jìn)行抓包,這會(huì)使網(wǎng)橋自身接口被設(shè)置為混雜模式,這時(shí)必須把報(bào)文復(fù)制一份送至本地;
6、 組播/廣播/未知單播報(bào)文會(huì)洪泛到每個(gè)橋端口,已知單播報(bào)文若目的端口為本機(jī)則送至本機(jī),若非本機(jī)則從對(duì)應(yīng)橋端口轉(zhuǎn)發(fā)出去;可見(jiàn)網(wǎng)橋與二層交換機(jī)在單播和廣播報(bào)文的轉(zhuǎn)發(fā)方面是一樣的,唯一區(qū)別在于組播報(bào)文的處理,在我們的網(wǎng)關(guān)設(shè)備上通過(guò)修改內(nèi)核,是不允許組播報(bào)文在網(wǎng)橋上傳播的;
3、網(wǎng)橋報(bào)文發(fā)送處理:
前面一節(jié)中已經(jīng)提到,網(wǎng)橋net_device的ops實(shí)現(xiàn)在內(nèi)核的br_device.c文件中,如同網(wǎng)卡驅(qū)動(dòng)一樣,網(wǎng)橋作為一種特殊的網(wǎng)絡(luò)設(shè)備,它也有它的ops方法集,linux已定義好它,如下圖:
其中指定了網(wǎng)橋這種網(wǎng)絡(luò)設(shè)備的發(fā)送方法為函數(shù)br_dev_xmit,即比如應(yīng)用程序使用send函數(shù)族系統(tǒng)調(diào)用從網(wǎng)橋發(fā)送報(bào)文時(shí),將最終調(diào)用br_dev_xmit函數(shù),其處理邏輯依然遵循網(wǎng)橋原理或者說(shuō)就是二層交換原理,已知單播報(bào)文即按MAC地址轉(zhuǎn)發(fā),廣播/組播/未知單播報(bào)文洪泛到所有橋端口,處理流程如下:
4、網(wǎng)橋不同情況下的報(bào)文流向:
4.1、傳入本機(jī):
切記這里的傳入本機(jī),并不一定是要傳入本機(jī)傳輸層,而僅僅是意味著該報(bào)文的目的MAC地址是該網(wǎng)橋下某橋端口對(duì)應(yīng)接口的MAC地址,即報(bào)文穿過(guò)網(wǎng)橋繼續(xù)走本機(jī)協(xié)議棧進(jìn)行進(jìn)一步處理,如下圖:
4.2、轉(zhuǎn)發(fā)出去:
轉(zhuǎn)發(fā)最終均調(diào)用dev_queue_xmit,這和所有的報(bào)文發(fā)送的道理是一樣的,需要注意的是轉(zhuǎn)發(fā)接口的更換和網(wǎng)橋轉(zhuǎn)發(fā)的兩次netfilter,如下圖:
4.3、傳入本機(jī)后再?gòu)木W(wǎng)橋轉(zhuǎn)發(fā):
這個(gè)情況實(shí)際是7.2.4.1中后續(xù)可能發(fā)生情況的一種,即在路由判決后,該報(bào)文應(yīng)從一個(gè)網(wǎng)橋接口轉(zhuǎn)發(fā),如下圖:
同理,該報(bào)文也可在傳入本機(jī)后再?gòu)哪硞€(gè)其他接口轉(zhuǎn)發(fā),如從某個(gè)以太網(wǎng)卡接口、usb接口、wlan接口等等。
總結(jié)
以上是生活随笔為你收集整理的Linux 网络协议栈开发—— 二层桥实现原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: NEON----ARM通用 SIMD 引
- 下一篇: OrangePi3开发板使用指南