色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

結(jié)合pppoe協(xié)議分析Linux網(wǎng)絡(luò)棧的實(shí)現(xiàn)方式

454398 ? 來(lái)源:博客園 ? 作者: zmkeil ? 2020-10-26 15:21 ? 次閱讀

這個(gè)標(biāo)題起得比較糾結(jié),之前熟知的PPPOE是作為PPP協(xié)議的底層載體,而實(shí)際上它也是一個(gè)完整的協(xié)議,不過(guò)它的實(shí)現(xiàn)比較簡(jiǎn)單,由它出發(fā),可以很容易理清楚Linux網(wǎng)絡(luò)棧的實(shí)現(xiàn)方式。

1.總述

Linux中用戶空間的網(wǎng)絡(luò)編程,是以socket為接口,一般創(chuàng)建一個(gè)sockfd = socket(family,type,protocol),之后以該sockfd為參數(shù),進(jìn)行各種系統(tǒng)調(diào)用來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)通信功能。其中family指明使用哪種協(xié)議域(如INET、UNIX等),protocol指明該協(xié)議域中具體哪種協(xié)議(如INET中的TCP、UDP等),type表明該接口的類(lèi)型(如STREAM、DGRAM等),一般設(shè)protocol=0,那么就會(huì)用該family中該type類(lèi)型的默認(rèn)協(xié)議(如INET中的STREAM默認(rèn)就是TCP協(xié)議)。

Linux中利用module機(jī)制,層次分明地實(shí)現(xiàn)了這套協(xié)議體系,并具有很好的擴(kuò)展性,其基本模塊構(gòu)成如下:

先看右邊,頂層的socket模塊提供一個(gè)sock_register()函數(shù),供各個(gè)協(xié)議域模塊使用,在全局的net_family[]數(shù)組中增加一項(xiàng);各個(gè)協(xié)議域模塊也提供一個(gè)類(lèi)似的register_xx_proto()函數(shù),供各個(gè)具體的協(xié)議使用,在該協(xié)議域私有的xx_proto[]數(shù)組中增加一項(xiàng)。這兩個(gè)數(shù)組中的存放的都是指針,指向的數(shù)據(jù)結(jié)構(gòu)如下圖所示:

很明顯它們是用來(lái)創(chuàng)建不同類(lèi)型的socket接口的,且是一種分層次的創(chuàng)建過(guò)程,可想而知,頂層socket_create()完成一些共有的操作,如分配內(nèi)存等,然后調(diào)用下一層create;協(xié)議域內(nèi)的create()完成一些該協(xié)議域內(nèi)共有的初始化工作;最后具體協(xié)議中的create()完成協(xié)議特有的初始化。具體的下一節(jié)講。

再來(lái)看上圖右邊的,也是頂層socket模塊提供的4個(gè)函數(shù),前兩個(gè)一般由具體協(xié)議模塊調(diào)用,由于協(xié)議棧與應(yīng)用層的交互,具體的后面會(huì)講到。后兩個(gè)一般有協(xié)議域模塊調(diào)用,用于底層設(shè)備與協(xié)議棧間的交互。但這也不絕對(duì),如在PPPOE協(xié)議中,這4個(gè)函數(shù)都由具體協(xié)議模塊調(diào)用,這是因?yàn)镻PPOX協(xié)議域內(nèi)的共有部分不多,各個(gè)協(xié)議間幾乎獨(dú)立。這4個(gè)函數(shù)的功能及所用到的數(shù)據(jù)結(jié)構(gòu),在后面具體用到時(shí)會(huì)詳細(xì)說(shuō)明。

2.socket插口創(chuàng)建

首先來(lái)看一下最終創(chuàng)建好的socket插口由哪些部分組成,該結(jié)構(gòu)是相當(dāng)龐大的,這里只給出框架:

基本屬性有state(listen、accept等),flags標(biāo)志(blocked等),type類(lèi)型,這里family和protocol都沒(méi)有了,因?yàn)樗鼈冊(cè)賱?chuàng)建時(shí)使用過(guò)了,已經(jīng)被融入到socket結(jié)構(gòu)中。

File指針指向一個(gè)file結(jié)構(gòu),在Linux中一個(gè)socket也被抽象為一個(gè)文件,所以在應(yīng)用層一般通過(guò)標(biāo)準(zhǔn)的文件操作來(lái)操作它。

Ops指向一個(gè)struct proto_ops結(jié)構(gòu),它是每種協(xié)議特有的,應(yīng)用層的系統(tǒng)調(diào)用,最終映射到網(wǎng)絡(luò)棧中具體協(xié)議的操作方法。

Sk指向一個(gè)struct sock結(jié)構(gòu),而該結(jié)構(gòu)在分配空間時(shí),多分配了一點(diǎn)以作為該協(xié)議的私有部分,這里包含了該協(xié)議的具體信息,內(nèi)容相當(dāng)多。首先是一個(gè)struct sock_common結(jié)構(gòu),包含了協(xié)議的基本信息;然后是一個(gè)sk_prot_create指針,指向一個(gè)struct proto結(jié)構(gòu)體,該結(jié)構(gòu)體就是第一節(jié)中所述的,用proto_regsiter()注冊(cè)到內(nèi)核中的,它包含應(yīng)用層到協(xié)議棧的交互操作和信息(也可以說(shuō)成是Appàtransport layer的交互信息);然后還有一個(gè)sk_backlog_rcv函數(shù)指針,所指函數(shù)在協(xié)議棧處理完接收到的包之后調(diào)用,一般僅是把數(shù)據(jù)包放到該socket的接收隊(duì)列中,等待APP讀??;最后協(xié)議的私有部分里存放該協(xié)議的私有信息,如pppoe的sessionID、daddr,tcp的連接4元組等,這些信息很重要,利用它們來(lái)區(qū)分同一個(gè)協(xié)議中的多個(gè)socket。

創(chuàng)建的總體過(guò)程,第一節(jié)已講過(guò)了,下面以pppoe為例,描述一個(gè)socket插口的具體創(chuàng)建過(guò)程:

之前所述的關(guān)鍵點(diǎn)這里幾乎都涉及到了,要注意的是這里的struct proto結(jié)構(gòu)非常簡(jiǎn)單,因?yàn)镻PPOE協(xié)議幾乎沒(méi)有傳輸層,所以不需要有太多的中間操作,僅需要一個(gè)obj_size來(lái)指明struct sock結(jié)構(gòu)后需分配的私有結(jié)構(gòu)大小,關(guān)于私有結(jié)構(gòu)的內(nèi)容,一般在connect操作時(shí)才能初始化。

創(chuàng)建好socket之后,其中的fops,proto_ops,sk_backlog_rcv等操作是如何作用,來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)通信的功能?這是后面要講述的內(nèi)容。

3.主動(dòng)過(guò)程

主動(dòng)過(guò)程即在應(yīng)用層中通過(guò)系統(tǒng)調(diào)用,觸發(fā)socket完成某種動(dòng)作,有些系統(tǒng)調(diào)用和標(biāo)準(zhǔn)的文件操作類(lèi)似,因此可以直接用sockfd的fops來(lái)描述,如read、write、ioctl等,有些則是socket接口特有的,需重新定義系統(tǒng)調(diào)用接口,Linux中用SYSCALL_DEFINEn()宏來(lái)定義系統(tǒng)調(diào)用接口,如bind、accept等。這些系統(tǒng)調(diào)用一般都很簡(jiǎn)單,最終都會(huì)去調(diào)用socket內(nèi)部proto_ops中的接口函數(shù)。

如下圖所示,在socket層,并不是所有的文件操作都適用于socket,因此其特有的socket_file_ops中只指定了部分函數(shù);另外還封裝了幾個(gè)系統(tǒng)調(diào)用,是我們熟悉的bind、listen、connect、accept。這些系統(tǒng)調(diào)用接口都是靜態(tài)的,它們一般經(jīng)過(guò)簡(jiǎn)單的處理,就調(diào)用具體socket中的proto_ops操作。

在協(xié)議棧中,主要是socket特有的proto_ops操作,但對(duì)于一些復(fù)雜的協(xié)議,如TCP,還需要其它一些操作來(lái)支持,這些接口都放在struct sock中的struct proto中。PPPOE協(xié)議比較簡(jiǎn)單,不需要struct proto的操作來(lái)支持,但其中的obj_size仍然重要,如前所述。

如上圖所示,PPPOE協(xié)議中,并不是所有協(xié)議操作都需要,如bind、accept等,下面選幾個(gè)來(lái)詳細(xì)看一下socket的主動(dòng)過(guò)程的工作。

Ioctl系統(tǒng)調(diào)用:ioctl是通過(guò)標(biāo)準(zhǔn)的文件操作來(lái)調(diào)用的,具體如下圖所示:

其中頂層sock_ioctl中,對(duì)于一些特殊情況,如VLAN、BRIDGE等,它們并不是要對(duì)socket插口本身操作,而是要調(diào)用VLAN、BRIDGE模塊中的創(chuàng)建函數(shù),這看起來(lái)有點(diǎn)格格不入,但為了操作方便,且保證網(wǎng)絡(luò)相關(guān)的操作都封裝在socket中,這么做也是不得已。

在pppoe_ioctl中,根據(jù)cmd進(jìn)行相應(yīng)操作,其中有一個(gè)值得注意的,就是PPPIOCGCHAN選項(xiàng),它使得該pppoe_socket成為一個(gè)特殊的channel,這主要是pppoe為了給ppp協(xié)議提供服務(wù)而特有的,與網(wǎng)絡(luò)協(xié)議棧關(guān)系不大,以后會(huì)具體看。

Read系統(tǒng)調(diào)用:read也是標(biāo)準(zhǔn)的文件操作,但要注意,在網(wǎng)絡(luò)棧中,read并不是接收過(guò)程,而僅是從該sock的接收隊(duì)列中取出skb,提交給應(yīng)用層,如下圖所示。而這些skb是如何獲得的,那是一個(gè)復(fù)雜的被動(dòng)過(guò)程,下面再講。

Connect系統(tǒng)調(diào)用:connect是socket.c中封裝的一個(gè)系統(tǒng)特用,其代碼也很簡(jiǎn)單,最終調(diào)用協(xié)議棧中的pppoe_connect接口,該接口函數(shù)是pppoe協(xié)議中一個(gè)非常重要的操作,具體如下圖所示:

首先先一下通配地址的問(wèn)題,這是network programming中一個(gè)基本問(wèn)題,因?yàn)楦鱾€(gè)協(xié)議用到的地址結(jié)構(gòu)不同,在應(yīng)用層,為了方便可讀性,可以用協(xié)議特有的地址結(jié)構(gòu),只要符標(biāo)準(zhǔn)的模式即可(即第一個(gè)元素為family),然后強(qiáng)制轉(zhuǎn)換成sockaddr*類(lèi)型,傳遞給通用的系統(tǒng)調(diào)用接口。在最終調(diào)用協(xié)議模塊中的接口函數(shù)時(shí),再轉(zhuǎn)換回來(lái)。

再看pppoe_connect中,首先由sock結(jié)構(gòu)指針得到pn指針,它們是分配在一起的(如前所述),這很容易得到,同時(shí)還得到pppoe_net結(jié)構(gòu)的指針(它是該協(xié)議中全局共有的)。然后把用戶傳遞進(jìn)來(lái)的addr的數(shù)據(jù)放到socket中來(lái),并且執(zhí)行一個(gè)set_item函數(shù),該函數(shù)主要根據(jù)addr信息,把該socket指針?lè)诺絽f(xié)議全局的pppoe_net結(jié)構(gòu)中(這一步對(duì)接收過(guò)程很重要,后面會(huì)細(xì)講)。最后初始化了該socket中特有的chan結(jié)構(gòu),并調(diào)用ppp_register_net_channel(),這主要為ppp服務(wù),以后再看。

4.發(fā)送流程

這也是一個(gè)主動(dòng)過(guò)程,在協(xié)議體系中,它是一個(gè)比較重要的過(guò)程,所以單獨(dú)列出來(lái)。Socket框架中,發(fā)送過(guò)程是通過(guò)標(biāo)準(zhǔn)的文件操作write完成的, socket的write操作為sock_aio_write(),最終會(huì)調(diào)用proto_ops->sendmsg()函數(shù),即pppoe模塊中的pppoe_sendmsg(),如下圖所示:

首先從sock中獲得相關(guān)信息,最重要的當(dāng)然是dev設(shè)備,因?yàn)閜ppoe的設(shè)備是選定的(由useraddr提供),而有些協(xié)議如IP,則會(huì)根據(jù)協(xié)議地址,有協(xié)議棧自動(dòng)選擇dev。然后分配skb,并準(zhǔn)備其中的package,這是每個(gè)協(xié)議的關(guān)鍵,由于pppoe協(xié)議很簡(jiǎn)單,只需要設(shè)置好一個(gè)pppoe header即可。最后直接調(diào)用dev_queue_xmit(skb),通過(guò)設(shè)備將該package發(fā)送出去。

5.網(wǎng)絡(luò)協(xié)議棧結(jié)構(gòu)小結(jié)

這里想講一下的是,pppoe到底是什么層的協(xié)議,鏈路層。而通過(guò)上面的描述,更準(zhǔn)確的說(shuō)法應(yīng)該是,pppoe是一個(gè)完整的協(xié)議,是從應(yīng)用層到設(shè)備之間的協(xié)議模塊,從這個(gè)意義上來(lái)講,它和INET域中的協(xié)議是等價(jià)的。如下圖所示:

這里講的協(xié)議是從應(yīng)用層往下直到物理設(shè)備的完整過(guò)程,有些協(xié)議具有一定的相似性,(如TCP、UDP,還包括裸IP等都以IP協(xié)議為基礎(chǔ)),則把它們歸為一個(gè)協(xié)議域內(nèi)。至于協(xié)議分層,則是概念上的,如PPPOE協(xié)議的主要功能體現(xiàn)在鏈路層,則一般稱它為鏈路層協(xié)議, 而狹義上稱TCP、UDP為傳輸層協(xié)議(而前面講的廣義上的TCP、UDP則是包括傳輸層、以IP為基礎(chǔ)的網(wǎng)絡(luò)層、鏈路層的完整協(xié)議)。

有點(diǎn)饒人,不過(guò)沒(méi)關(guān)系,只要理解協(xié)議棧的功能就是從socket接口得到數(shù)據(jù),封裝成一定的包結(jié)構(gòu),最終由物理設(shè)備發(fā)送出去(接收過(guò)程反過(guò)來(lái))。至于具體的實(shí)現(xiàn),則是由具體協(xié)議的特點(diǎn)決定的,對(duì)于一些復(fù)雜協(xié)議,分層方式則是一種比較好的選擇。

而其中有些協(xié)議會(huì)比較特殊,如之前講的VLAN,它甚至從來(lái)都不會(huì)進(jìn)入到協(xié)議棧,僅在設(shè)備驅(qū)動(dòng)層,就被轉(zhuǎn)化成以太網(wǎng)協(xié)議,協(xié)議棧中根本不需要為它準(zhǔn)備處理接口。再如比較典型的ICMP協(xié)議,它既可以是一個(gè)完整的協(xié)議,被應(yīng)用層調(diào)用(如典型的Ping程序),也可以只作為T(mén)CP的附屬協(xié)議(只被TCP處理,對(duì)應(yīng)用層不可見(jiàn))。這里的PPPOE與此很類(lèi)似,本文講述了其作為完整協(xié)議的工作方式,另外它也可以作為PPP協(xié)議的底層基礎(chǔ),在下一篇中會(huì)講述其具體的實(shí)現(xiàn)方法。

6.被動(dòng)過(guò)程-接收流程

接收過(guò)程是一個(gè)被動(dòng)過(guò)程,在屋里設(shè)備層,它往往是由中斷觸發(fā),其實(shí)現(xiàn)的復(fù)雜度也較發(fā)送過(guò)程高很多。在協(xié)議棧中,其實(shí)現(xiàn)也同樣與發(fā)送過(guò)程很不對(duì)稱。因?yàn)榘l(fā)送時(shí),本身主機(jī)擁有控制權(quán),而接收時(shí),是一個(gè)數(shù)據(jù)包對(duì)多個(gè)接收模塊(一對(duì)多),只能從數(shù)據(jù)包中的信息中一點(diǎn)一點(diǎn)分析,并去尋找接收模塊。

先給出接收流程的框架,再逐步去分析其實(shí)現(xiàn)。如下圖所示:

先不看橙色部分,一個(gè)接收流程由物理設(shè)備的中斷觸發(fā),設(shè)備驅(qū)動(dòng)程序進(jìn)行相應(yīng)處理,得到協(xié)議棧中標(biāo)準(zhǔn)的數(shù)據(jù)結(jié)構(gòu)sk_buff(簡(jiǎn)稱skb),并根據(jù)一個(gè)特殊的全局?jǐn)?shù)據(jù)結(jié)構(gòu)packet_type,將數(shù)據(jù)交給相應(yīng)的協(xié)議;協(xié)議根據(jù)自身設(shè)計(jì)特點(diǎn)對(duì)skb數(shù)據(jù)進(jìn)行處理,并通過(guò)全局變量xx_net_id和各個(gè)協(xié)議私有的特殊數(shù)據(jù)結(jié)構(gòu)xx_net,尋找到該數(shù)據(jù)包對(duì)應(yīng)的應(yīng)用層socket插口,并將其放在該socket插口的接收隊(duì)列中;最后應(yīng)用層在某個(gè)時(shí)刻會(huì)通過(guò)read系統(tǒng)調(diào)用讀取該數(shù)據(jù)(如第3節(jié)所講)。

6.1設(shè)備驅(qū)動(dòng)層的處理

設(shè)備驅(qū)動(dòng)層的接收過(guò)程在之前的篇章中已經(jīng)講過(guò)了,一般是由硬件中斷觸發(fā),然后或是采用中斷模式、或是采用NAPI模式,總之其根本任務(wù)就是:根據(jù)設(shè)備的特點(diǎn)(先驗(yàn)知識(shí),如以太網(wǎng)設(shè)備驅(qū)動(dòng)事先就是知道以太網(wǎng)幀的基本結(jié)構(gòu)的),將接收到的裸數(shù)據(jù)轉(zhuǎn)換成協(xié)議棧所認(rèn)識(shí)的標(biāo)準(zhǔn)結(jié)構(gòu)skb(從而實(shí)現(xiàn)底層設(shè)備對(duì)上層的透明性),然后提交給相應(yīng)的協(xié)議。很明顯問(wèn)題有兩個(gè),skb是什么樣的,要準(zhǔn)備什么?怎么知道提交給誰(shuí)?

準(zhǔn)備skb結(jié)構(gòu)。首先來(lái)看一下sk_buff的構(gòu)成,如下圖所示。Skb只是一個(gè)控制結(jié)構(gòu),實(shí)際的數(shù)據(jù)放在一個(gè)data_buf中,并由skb中一些列參數(shù)索引,具體見(jiàn)下圖右所示,這之中有些參數(shù)是在分配data_buf、copy數(shù)據(jù)時(shí)就決定的,如head、end、data、tail等;有些則要經(jīng)過(guò)一定的識(shí)別才能得到,如mac_header一般在設(shè)備驅(qū)動(dòng)中得到,而network_header、transport_header則要到協(xié)議棧中才知道,且各個(gè)協(xié)議的處理各不相同,如PPPOE協(xié)議根本不需要只需要指明network_header,而TCP協(xié)議則有復(fù)雜的頭部信息。最終由skb->data指針和頭部長(zhǎng)可得到app_data的位置,因此應(yīng)用層可以只讀取應(yīng)用數(shù)據(jù)即可。

Skb中另外一些參數(shù)也相當(dāng)重要,如vlan_tci用于指明vlan的id,其用法在前面已講過(guò)。dev參數(shù)則是要貫穿整個(gè)流程的,因?yàn)樵擙嫶蠼Y(jié)構(gòu)中的多個(gè)信息會(huì)在整個(gè)網(wǎng)絡(luò)系統(tǒng)中用到,要注意的是該參數(shù)由設(shè)備驅(qū)動(dòng)程序決定,一般就是接收的物理設(shè)備,但在Linux中,網(wǎng)絡(luò)設(shè)備是由net_device結(jié)構(gòu)指示的,一個(gè)物理設(shè)備可有多個(gè)協(xié)議設(shè)備,這在VLAN、BRIDGE中很明顯,其實(shí)在PPP協(xié)議中,這也是一個(gè)關(guān)鍵點(diǎn),后面會(huì)講到。Sk參數(shù)指示了該數(shù)據(jù)包屬于哪個(gè)應(yīng)用層socket插口,它由具體協(xié)議根據(jù)特定方法得到,后面會(huì)講到。Protocol參數(shù)是本節(jié)的重點(diǎn),它由mac_header中的字節(jié)決定。

設(shè)備驅(qū)動(dòng)程序只關(guān)心mac_header,即數(shù)據(jù)包最初始的部分。前面也提到了,這需要一定的先驗(yàn)知識(shí),如ethernet設(shè)備驅(qū)動(dòng),它先驗(yàn)的指導(dǎo)以太網(wǎng)頭部由DMAC、SMAC和兩字節(jié)的協(xié)議構(gòu)成,下面是一個(gè)RTL8012驅(qū)動(dòng)的接收片段(~/dev/net/Ethernet/realtek/apt.c):

提交協(xié)議棧。主要就是根據(jù)skb->protocol參數(shù),當(dāng)然還需要另一個(gè)重要的數(shù)據(jù)結(jié)構(gòu)packet_type。

設(shè)備驅(qū)動(dòng)中最后提交過(guò)程有netif_skb_receive()函數(shù)完成,它會(huì)遍歷系統(tǒng)中所有的packet_type,找到protocol和dev(這個(gè)是啥意思)都相同,就調(diào)用該ptype中的func函數(shù),如ip_packet中的func為ip_rcv()函數(shù),這樣skb就到了協(xié)議棧中。

系統(tǒng)中所有全局的packet_type構(gòu)成一個(gè)list,并由全局變量ptype_all索引,另外還提供ptype_base[]全局?jǐn)?shù)組,將type相同的packet_type單獨(dú)成鏈,為遍歷提供方便。

這些全局的packet_type結(jié)構(gòu)是從哪來(lái)的,這就要看第一節(jié)圖中,左邊4個(gè)函數(shù)中的一個(gè)dev_add_packet(struct packet_type*)。協(xié)議模塊在加載時(shí),調(diào)用該函數(shù),將自己特有的packet_type結(jié)構(gòu)注冊(cè)進(jìn)內(nèi)核中,而其中的(*func)則有協(xié)議自己定義。

最后要注意的是,打開(kāi)if_ether.h文件,可以看到現(xiàn)在已定義的協(xié)議protocol有_P_IP、_P_ARP、_P_8021Q、_P_PPP_SES、_P_PPP_DIS等,如果根據(jù)傳統(tǒng)的分層協(xié)議來(lái)看它們,會(huì)覺(jué)得很亂,有網(wǎng)絡(luò)層的、鏈路層的、甚至同一種協(xié)議還有兩個(gè),但如果用第5節(jié)的概念來(lái)看,則很容易理解。再看由什么模塊注冊(cè),TCP、UDP都是以IP協(xié)議為基礎(chǔ),只要有INET協(xié)議域模塊注冊(cè)一個(gè)即可,而ARP雖然也屬于INET域,但它卻必須自己有一個(gè)packet_type,PPPOE協(xié)議雖然只是一個(gè)協(xié)議,但卻有兩個(gè)階段,所以它有兩個(gè)不同的packet_tpye。可見(jiàn)這種實(shí)現(xiàn)是很靈活的,根據(jù)具體協(xié)議的特點(diǎn)決定。

6.2協(xié)議棧接收處理

協(xié)議棧的處理由各協(xié)議決定,如TCP協(xié)議的處理過(guò)程是相當(dāng)復(fù)雜的,而這里的pppoe的處理卻非常簡(jiǎn)單,但由它卻可以避開(kāi)細(xì)節(jié),更清楚地看到流程的梗概,如下圖所示:

可以看到pppoe協(xié)議的處理過(guò)程幾乎沒(méi)有,僅是設(shè)置了skb的network_header, transport_header,然后就利用get_item()函數(shù)找到它所屬的socket插口,直接把它提交給上層。如上圖右所示,是典型的TCP接收流程,是相當(dāng)復(fù)雜的,其中TCP與IP的接頭處還需用到額外的私有數(shù)據(jù)結(jié)構(gòu)。

提交函數(shù)sk_backlog_rcv,即這里的pppoe_rcv_core(sk,skb)函數(shù),首先判斷是否為ppp通道的數(shù)據(jù),若是則提交給ppp協(xié)議。一般正常情況下,直接用sock_queue_rcv_skb(sk,skb)函數(shù)將它放在socket的接收隊(duì)列中。

匹配應(yīng)用層接口:協(xié)議棧在對(duì)數(shù)據(jù)包進(jìn)行處理后,需要確定該包屬于哪個(gè)socket插口,這個(gè)過(guò)程在內(nèi)核中有一套完整的機(jī)制來(lái)完成,其框架如下圖所示:

首先內(nèi)核有個(gè)全局結(jié)構(gòu)net_generic,其中一個(gè)最重要的元素是指針數(shù)組。然后每個(gè)協(xié)議module加載時(shí),會(huì)調(diào)用register_pernet_device(struct pernet_operations*)(見(jiàn)第一節(jié)圖),pernet_operations結(jié)構(gòu)中最關(guān)鍵的兩個(gè)參數(shù),一個(gè)是size,它指示內(nèi)核為該模塊分配一個(gè)私有數(shù)據(jù)結(jié)構(gòu)(如pppoe即為struct pppoe_net),另一個(gè)是xx_net_id,它指示由net_generic.ptr[xx_net_id]來(lái)指向該數(shù)據(jù)結(jié)構(gòu),這樣每個(gè)協(xié)議模塊中,就可以根據(jù)自己的xx_net_id很容易尋找到內(nèi)核分配給自己的私有結(jié)構(gòu)。最后協(xié)議的私有模塊中一般也有一個(gè)指針數(shù)組,用以索引屬于它的各個(gè)socket。

工作流程就很清楚了,具體的工作方式還要看兩個(gè)函數(shù),

就不看細(xì)節(jié)了,僅看兩個(gè)函數(shù)的原型就能明白,其中pn參數(shù)就是上面所述的用全局結(jié)構(gòu)net_generic和各協(xié)議私有xx_net_id獲得的。Set_item()函數(shù)在connect時(shí)調(diào)用(參見(jiàn)第3節(jié)),它根據(jù)pppox_sock中的sessionID、remoteMAC(這兩個(gè)參數(shù)由*useraddr傳入,詳見(jiàn)下一篇協(xié)議分析),根據(jù)一個(gè)hash算法得到一個(gè)hashInt值,然后用pn->hash_ptr[hashInt]指向該socket結(jié)構(gòu)。那反過(guò)來(lái),接收時(shí)由這兩個(gè)參數(shù)(由數(shù)據(jù)包的協(xié)議頭中獲得)得到hashInt,便能很容易找到對(duì)應(yīng)的socket了。

各個(gè)協(xié)議使用的方法及參數(shù)都不同,但思路都一樣,就是依據(jù)協(xié)議本身特有的參數(shù)(如TCP中的連接4元組),在socket創(chuàng)建、或連接的時(shí)候(接收數(shù)據(jù)之前),根據(jù)一定的算法,將它的指針?lè)旁谠搮f(xié)議私有的xx_net中,這樣接收時(shí)就可以由數(shù)據(jù)報(bào)的協(xié)議參數(shù)找到它了。

6.3命名空間namespace

上述的socket索引方法有個(gè)繞彎的地方:就是每個(gè)協(xié)議私有的xx_net結(jié)構(gòu)可以直接由協(xié)議模塊本身分配,索引起來(lái)也方便,不要用到全局的net_generic。而目前內(nèi)核所用的方法,其實(shí)是為了另外的目的,那就是命名空間namespace。也就是虛擬多用戶的一套機(jī)制,具體的也沒(méi)細(xì)看,好像目前內(nèi)核整個(gè)namespace還沒(méi)有全部完成。

network的命名空間問(wèn)題主要在于,每個(gè)協(xié)議模塊的xx_net私有結(jié)構(gòu)不僅是一個(gè),而是由內(nèi)核全局決定的,即每注冊(cè)一個(gè)新的用戶(有點(diǎn)像虛擬機(jī)機(jī)制),就分配一個(gè)新的xx_net結(jié)構(gòu),這樣多用戶間可以用參數(shù)相同的socket連接,但卻指向不同的socket。

可以看到前面所述的很多內(nèi)容中,都會(huì)有個(gè)net參數(shù),就是為了這個(gè)作用,主要實(shí)現(xiàn)函數(shù)在namespace.c中。

7.總結(jié)

主要結(jié)合pppoe協(xié)議,學(xué)習(xí)了Linux中網(wǎng)絡(luò)棧的實(shí)現(xiàn)。由于pppoe協(xié)議本身很簡(jiǎn)單,代碼量少,更容易抓住協(xié)議實(shí)現(xiàn)的梗概。Linux網(wǎng)絡(luò)棧,繼承Unix,采用socket插口作為主線,主要包括創(chuàng)建、協(xié)議連接、主動(dòng)過(guò)程、匹配機(jī)制、被動(dòng)過(guò)程等內(nèi)容。

要注意的是,實(shí)際應(yīng)用中,很少有直接利用pppoe協(xié)議通信的,而是把它作為ppp協(xié)議的底層基礎(chǔ)來(lái)用,而這需要協(xié)議實(shí)現(xiàn)中的一些技巧來(lái)支持。
編輯:hfy

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11292

    瀏覽量

    209333
  • Socket
    +關(guān)注

    關(guān)注

    0

    文章

    212

    瀏覽量

    34664
  • PPPoE
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    12148
  • TCP協(xié)議
    +關(guān)注

    關(guān)注

    1

    文章

    91

    瀏覽量

    12070
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    hart協(xié)議協(xié)議結(jié)構(gòu)分析

    的智能化水平,同時(shí)保持與現(xiàn)有模擬系統(tǒng)的兼容性。 2. HART協(xié)議概述 HART協(xié)議可以分為幾個(gè)層次,每個(gè)層次負(fù)責(zé)不同的功能: 2.1 物理層(Physical Layer) 物理
    的頭像 發(fā)表于 12-02 09:43 ?197次閱讀

    明達(dá)技術(shù)為您剖析軟&硬協(xié)議

    在當(dāng)今這個(gè)科技日新月異的時(shí)代,每一個(gè)細(xì)微之處都蘊(yùn)含著無(wú)限可能。今天,讓我們一同深入探索網(wǎng)絡(luò)協(xié)議領(lǐng)域的兩大核心實(shí)現(xiàn)方式——軟
    的頭像 發(fā)表于 11-23 16:28 ?106次閱讀
    明達(dá)技術(shù)為您剖析軟&amp;硬<b class='flag-5'>協(xié)議</b><b class='flag-5'>棧</b>

    DoIP協(xié)議簡(jiǎn)介及主要功能

    的修改,使用單對(duì)雙絞線即可實(shí)現(xiàn)穩(wěn)定的100Mb/s全雙工通信。正是由于車(chē)載以太網(wǎng)的普及應(yīng)用,對(duì)應(yīng)的車(chē)輛診斷協(xié)議DoIP應(yīng)運(yùn)而生,本文將基于ISO13400、ISO14229和求遠(yuǎn)電子在DoCAN協(xié)議
    的頭像 發(fā)表于 11-13 15:35 ?465次閱讀
    DoIP<b class='flag-5'>協(xié)議</b><b class='flag-5'>棧</b>簡(jiǎn)介及主要功能

    什么是協(xié)議分析儀和訓(xùn)練器

    長(zhǎng)時(shí)間、大規(guī)模的分析。 軟件型協(xié)議分析儀:基于計(jì)算機(jī)軟件的工具,通過(guò)安裝在計(jì)算機(jī)上實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)包的捕獲、解析和
    發(fā)表于 10-29 14:33

    Linux網(wǎng)絡(luò)協(xié)議實(shí)現(xiàn)

    網(wǎng)絡(luò)協(xié)議是操作系統(tǒng)核心的一個(gè)重要組成部分,負(fù)責(zé)管理網(wǎng)絡(luò)通信中的數(shù)據(jù)包處理。在 Linux 操作系統(tǒng)中,
    的頭像 發(fā)表于 09-10 09:51 ?302次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>協(xié)議</b><b class='flag-5'>棧</b>的<b class='flag-5'>實(shí)現(xiàn)</b>

    串口服務(wù)器和TCP/IP協(xié)議是什么關(guān)系

    串口服務(wù)器與TCP/IP協(xié)議之間存在著緊密而復(fù)雜的關(guān)系。這種關(guān)系主要體現(xiàn)在串口服務(wù)器如何利用TCP/IP協(xié)議來(lái)實(shí)現(xiàn)串口設(shè)備與
    的頭像 發(fā)表于 08-25 17:35 ?1542次閱讀

    調(diào)試ESP8266集成LWIP協(xié)議用UDP方式發(fā)送數(shù)據(jù)時(shí),無(wú)法正常發(fā)送數(shù)據(jù)是哪里的問(wèn)題?

    我在調(diào)試8266集成LWIP協(xié)議用UDP方式發(fā)送數(shù)據(jù)時(shí),參考別的環(huán)境的UDP例程,發(fā)現(xiàn)無(wú)法正常發(fā)送數(shù)據(jù),反復(fù)檢查了,并確認(rèn)8266已經(jīng)通過(guò)WIFI連上網(wǎng)了,但是使用LWIP協(xié)議
    發(fā)表于 07-12 07:44

    TCP/IP協(xié)議的設(shè)計(jì)與實(shí)現(xiàn)_中文

    電子發(fā)燒友網(wǎng)站提供《TCP/IP協(xié)議的設(shè)計(jì)與實(shí)現(xiàn)_中文.pdf》資料免費(fèi)下載
    發(fā)表于 07-03 11:28 ?4次下載

    LwIP協(xié)議源碼詳解—TCP/IP協(xié)議實(shí)現(xiàn)

    電子發(fā)燒友網(wǎng)站提供《LwIP協(xié)議源碼詳解—TCP/IP協(xié)議實(shí)現(xiàn).pdf》資料免費(fèi)下載
    發(fā)表于 07-03 11:22 ?3次下載

    基于MM32G5330的FlexCAN實(shí)現(xiàn)CANopenNode協(xié)議移植

    本文將介紹如何基于靈動(dòng)MM32G5330的FlexCAN實(shí)現(xiàn)CANopenNode協(xié)議的移植,并使用靈動(dòng)官方提供的開(kāi)發(fā)板Mini-G5333進(jìn)行驗(yàn)證。
    發(fā)表于 04-12 09:15 ?1464次閱讀
    基于MM32G5330的FlexCAN<b class='flag-5'>實(shí)現(xiàn)</b>CANopenNode<b class='flag-5'>協(xié)議</b><b class='flag-5'>棧</b>移植

    ethernetif_input和tcpip協(xié)議線程的作用

    tcpip協(xié)議線程是lwIP協(xié)議的核心線程,負(fù)責(zé)處理TCP/IP協(xié)議的各種功能,包括TCP
    的頭像 發(fā)表于 03-20 10:01 ?1317次閱讀

    PROFINET協(xié)議通信技術(shù)介紹

    PROFINET協(xié)議是PROFINET通信協(xié)議實(shí)現(xiàn)基礎(chǔ),它由多個(gè)層次組成,每個(gè)層次都有特定的功能和作用。
    的頭像 發(fā)表于 02-03 16:22 ?2464次閱讀

    使用LwIP協(xié)議淺析實(shí)戰(zhàn)分析(i.MX RT)

    LWIP協(xié)議網(wǎng)絡(luò)分層 LwIP(Light weight IP),是一種輕量化且開(kāi)源的TCP/IP協(xié)議,它可以在有限的RAM和ROM條件下,實(shí)現(xiàn)
    的頭像 發(fā)表于 02-02 17:05 ?1709次閱讀
    使用LwIP<b class='flag-5'>協(xié)議</b><b class='flag-5'>棧</b>淺析實(shí)戰(zhàn)<b class='flag-5'>分析</b>(i.MX RT)

    通信網(wǎng)絡(luò)協(xié)議之UDP協(xié)議技術(shù)解析

    在通常的網(wǎng)絡(luò)協(xié)議中,TCP/IP協(xié)議是一個(gè)常見(jiàn)的示例,其中UDP和TCP都是傳輸層協(xié)議。傳輸
    發(fā)表于 02-01 11:00 ?972次閱讀
    通信<b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>協(xié)議</b><b class='flag-5'>棧</b>之UDP<b class='flag-5'>協(xié)議</b>技術(shù)解析

    PPPoe的報(bào)文結(jié)構(gòu)和抓包分析

    PPPoe的頭部后面就是PPP的報(bào)文了,因?yàn)槲覀冃枰氖莗pp協(xié)議中的認(rèn)證功能,所以自然需要有完整的ppp報(bào)文去完成這一部分的功能。
    的頭像 發(fā)表于 01-02 09:47 ?3984次閱讀
    <b class='flag-5'>PPPoe</b>的報(bào)文結(jié)構(gòu)和抓包<b class='flag-5'>分析</b>
    主站蜘蛛池模板: 亚洲粉嫩美白在线| 国产超嫩一线天在线播放| 色翁荡熄月月| 久久免费电影| 国产69精品久久久久乱码 | 亚洲日韩中文字幕区| 女性私密五月天| 精品精品国产yyy5857香蕉| 超碰97人人做人人爱亚洲尤物| 亚洲中文无码AV在线观看| 肉多的小说腐小说| 麻豆免费高清完整版| 黄得让人湿的片段| 国产成人精品免费视频大全可播放的| 中文字幕无线手机在线| 邪恶肉肉全彩色无遮琉璃神社| 欧美一区二区视频在线观看| 久久毛片基地| 狠狠婷婷综合久久久久久| 国产成人无码区免费内射一片色欲 | 亚洲成人综合在线| 日韩精品一区二区三区色欲AV| 另类专区hy777| 精品亚洲永久免费精品| 国产日韩成人内射视频| 高h超辣bl文| 成人免费视频无遮挡在线看| 99精品电影| 97在线国内自拍视频| 最近中文字幕完整版高清| 亚洲偷自拍精品视频在线观看| 无码专区aaaaaa免费视频| 收集最新中文国产中文字幕| 全部免费特黄特色大片看片| 男人的天堂黄色片| 免费观看a视频| 男女边吃奶边做边爱视频| 邻家美姨在线观看全集免费| 久久这里只有是精品23| 久久亚洲伊人| 美女张开腿让我了一夜|