0概述 在傳統的電信IT產(chǎn)品中,高性能網(wǎng)絡(luò )接口一般采用特殊的硬件模塊來(lái)實(shí)現,比如網(wǎng)絡(luò )處理器、ASIC、FPGA等等。這些特殊硬件模塊一般會(huì )采用特殊的架構和指令集對網(wǎng)絡(luò )數據收發(fā)過(guò)程進(jìn)行優(yōu)化以達到更好的性能。然而,這也相應使得開(kāi)發(fā)和維護這些模塊的成本非常的昂貴,同時(shí)還有一個(gè)無(wú)法解決的問(wèn)題是基于這些特殊硬件模塊實(shí)現的網(wǎng)絡(luò )接口不能移植到云中,因為它們跟硬件的耦合度太高了。摩爾定律的出現,使得通用處理器的性能得到了極大的提升,這也為基于通用處理器實(shí)現高性能網(wǎng)絡(luò )接口提供了可能,同時(shí)也為移植到云中提供了前提條件。 圖1 網(wǎng)絡(luò )接口實(shí)現的發(fā)展趨勢 本文對基于通用X86架構處理器和Linux下的傳統網(wǎng)絡(luò )接口實(shí)現模式進(jìn)行了分析,同時(shí)針對其不足提出了一種高性能網(wǎng)絡(luò )接口實(shí)現方案-HPNI. 1傳統網(wǎng)絡(luò )接口實(shí)現分析 傳統網(wǎng)絡(luò )接口實(shí)現如圖2所示,Linux下傳統網(wǎng)絡(luò )接口處理流程一般包含以下幾個(gè)步驟: 圖2 傳統網(wǎng)絡(luò )接口實(shí)現 (1)系統啟動(dòng)之后,內核中的驅動(dòng)程序進(jìn)行相應的資源分配以及網(wǎng)卡寄存器配置,比如分配數據包緩沖區,使能DMA傳輸通道等等; (2)網(wǎng)卡初始化完成以后,當網(wǎng)卡從網(wǎng)絡(luò )收到數據包的時(shí)候,會(huì )將數據包通過(guò)DMA方式傳送到內核中的數據包緩沖區中,并生成相應的數據包描述符存放在環(huán)形隊列里面; (3)網(wǎng)卡觸發(fā)硬中斷通知內核,內核在中斷處理程序中產(chǎn)生相應軟中斷給應用程序收包任務(wù); (4)應用程序收包任務(wù)通過(guò)系統調用收取數據包,數據包也將從內核空間拷貝到用戶(hù)空間; (5)收包任務(wù)通過(guò)共享隊列把數據包傳遞給處理任務(wù); (6)處理任務(wù)通過(guò)共享隊列把處理好的數據包傳遞給發(fā)包任務(wù); (7)發(fā)包任務(wù)通過(guò)系統調用把數據包傳遞給內核,通過(guò)采用一次內存拷貝實(shí)現; (8)驅動(dòng)程序根據存放在環(huán)形隊列里面的數據包描述符啟動(dòng)相應的DMA傳輸任務(wù); (9)數據包傳輸完成后,網(wǎng)卡觸發(fā)中斷通知內核做相應處理。 下面先對傳統網(wǎng)絡(luò )接口的性能關(guān)鍵點(diǎn)進(jìn)行分析。 1.1中斷和系統調用 Linux下傳統網(wǎng)絡(luò )接口實(shí)現的一個(gè)關(guān)鍵因素是中斷技術(shù),網(wǎng)卡通過(guò)中斷與內核保持同步。但中斷處理會(huì )引入很大的性能損失,因為當CPU處理中斷的時(shí)候,它必須儲存和恢復自己的狀態(tài),進(jìn)行上下文切換以及在進(jìn)入和退出中斷處理程序的時(shí)候可能引入緩存(cache)操作。在進(jìn)行大流量數據包處理的時(shí)候,由于CPU被頻繁地中斷,由此帶來(lái)的性能損失會(huì )非常嚴重。 當使用Linux系統提供的標準socket接口來(lái)實(shí)現網(wǎng)絡(luò )通信時(shí),會(huì )觸發(fā)大量的系統調用,當應用程序通過(guò)socket系統調用進(jìn)行網(wǎng)絡(luò )通信時(shí),需要經(jīng)歷從用戶(hù)態(tài)到內核態(tài)的切換以及其反向過(guò)程,在切換過(guò)程當中需要進(jìn)行上下文的保存,比如對相關(guān)寄存器進(jìn)行堆棧壓棧操作,保存當前指令指針等等。這些操作都會(huì )消耗系統資源,當處理高速的數據流量時(shí),隨著(zhù)系統調用數量的急劇增加而導致系統資源的大量消耗。 1.2內存相關(guān)性能問(wèn)題 1.2.1內存拷貝 在使用標準套接字進(jìn)行數據包收發(fā)時(shí),數據在應用程序和內核之間進(jìn)行傳遞必須通過(guò)內存拷貝來(lái)完成,原因在于用戶(hù)空間的內存和內核空間的內存是處在物理內存不同的位置上。內存拷貝是一個(gè)非常消耗資源的過(guò)程,當需要收發(fā)的數據包流量很大時(shí),這種開(kāi)銷(xiāo)將會(huì )極大地影響系統的性能。 1. 2.2內存訪(fǎng)問(wèn)效率 在絕大多數情況下,應用程序并不直接通過(guò)物理內存地址來(lái)訪(fǎng)問(wèn)內存,而是采用虛擬地址,當CPU收到內存訪(fǎng)問(wèn)指令時(shí)會(huì )先把虛擬地址轉換成實(shí)際的物理地址,然后進(jìn)行內存的訪(fǎng)問(wèn)操作。這種方式已經(jīng)被普遍接受,甚至被稱(chēng)作是IT時(shí)代最杰出的發(fā)明之一,但是這種非直接內存訪(fǎng)問(wèn)方式并不是沒(méi)有代價(jià)的,地址的翻譯需要通過(guò)頁(yè)表來(lái)完成,頁(yè)表通常情況下是儲存在內存當中的,訪(fǎng)問(wèn)速度很慢,為了解決這個(gè)問(wèn)題,大部分系統都采用了TLB(Tralaslation Lookaside Buffer)的方式,最近觸發(fā)的一些地址翻譯結果都會(huì )保存在TLB中,TLB實(shí)際上使用的是CPU的緩存(cache),訪(fǎng)問(wèn)速度非?,然而cache容量小,只有最近訪(fǎng)問(wèn)的一部分頁(yè)表項能保存下來(lái),因此出現了“TLB Miss”;當CPU發(fā)現當前虛擬地址無(wú)法在TLB里面找到相對應的表項時(shí),就引入了一個(gè)TLB Miss,此時(shí)CPU需要回到內存當中的頁(yè)表進(jìn)行查找,性能會(huì )顯著(zhù)降低。因此當程序需要進(jìn)行頻繁的內存操作時(shí),需要盡量減少TLBMiss的次數。當前系統定義的頁(yè)面大小一般是4k字節,當應用程序使用比如2G這樣的大內存時(shí),總共需要50多萬(wàn)個(gè)頁(yè)表項,這個(gè)數目是相當龐大的,同時(shí)因為只有一小部分的表項能夠裝載在TLB中,因此TLB Miss的幾率也很大。另外,一般情況下程序的虛擬內存空間都是連續的,但其對應的物理內存空間卻不一定是連續的,這樣會(huì )導致一次虛擬內存尋址操作可能需要進(jìn)行多次物理內存尋址操作才能完成,這也會(huì )成倍地增加內存訪(fǎng)問(wèn)消耗的時(shí)間。 1.3多核親和力 多核系統對提高系統的性能有很大的幫助,當前大部分系統的調度算法會(huì )把當前的任務(wù)放到最空閑的核上執行,這樣的好處是能夠增加CPU資源的利用率,但因為每個(gè)CPU核心都有自己獨立的寄存器和cache,當任務(wù)從一個(gè)核心遷移到另一個(gè)核心時(shí),會(huì )引發(fā)大量的核問(wèn)切換開(kāi)銷(xiāo),比如上下文切換,cache miss等等。另外,對于使用NUMA(Non-Uniform Memory Access)架構的系統而言,核間切換的開(kāi)銷(xiāo)會(huì )更大,在SMP(Svmmetric Multiprocessing)架構下,所有核心是通過(guò)共享接口訪(fǎng)問(wèn)內存的,因此每個(gè)核心訪(fǎng)問(wèn)內存的速度是一樣的,但在NUMA架構下,核心對內存的訪(fǎng)問(wèn)分為本地訪(fǎng)問(wèn)和遠程訪(fǎng)問(wèn)。核心訪(fǎng)問(wèn)本地內存的速度要比訪(fǎng)問(wèn)遠端內存的速度快很多,當任務(wù)從核心A切換到核心B的時(shí)候,如果它仍然使用之前在A(yíng)上分配的內存,那么其內存訪(fǎng)問(wèn)模式會(huì )從本地模式切換成遠程模式,從而引起內存訪(fǎng)問(wèn)速度的下降。 1.4共享隊列的訪(fǎng)問(wèn) 當把數據包從一個(gè)任務(wù)傳遞到另外一個(gè)任務(wù)的時(shí)候,需要用到共享隊列。通常情況下,在訪(fǎng)問(wèn)共享隊列的時(shí)候會(huì )用到Mutex鎖來(lái)保證訪(fǎng)問(wèn)的一致性。當應用程序申請Mutex鎖失敗之后會(huì )陷入內核態(tài)中睡眠,當鎖可用之后再從內核態(tài)切換到用戶(hù)態(tài)執行,這里也引入了上下文切換的開(kāi)銷(xiāo),而且當數據流量很大的時(shí)候,相應的開(kāi)銷(xiāo)也會(huì )非常大。為了消除這類(lèi)開(kāi)銷(xiāo),業(yè)界也提出了一些改進(jìn)的方法,比如自旋鎖(spinlock),自旋鎖一直在用戶(hù)態(tài)運行,不會(huì )陷入內核態(tài)中,因此也不會(huì )產(chǎn)生上下文切換的開(kāi)銷(xiāo),但是它還是存在一些弊端:一方面可能造成死鎖,如果一個(gè)線(xiàn)程拿到鎖之后被意外銷(xiāo)毀,其它等待此鎖的線(xiàn)程會(huì )發(fā)生死鎖;另一方面,當共享隊列和線(xiàn)程數量猛增時(shí),鎖的數量也會(huì )同時(shí)增加,對鎖的管理會(huì )給系統帶來(lái)很大的負擔。 2 HPNI實(shí)現原理 2.1傳統網(wǎng)絡(luò )接口實(shí)現模式的不足 從上述分析可以得出傳統網(wǎng)絡(luò )接口的實(shí)現主要有以下幾點(diǎn)不足: (1)上下文切換開(kāi)銷(xiāo)太多,這些開(kāi)銷(xiāo)主要是由中斷、系統調用、鎖以及核間切換引入; (2)內存拷貝的開(kāi)銷(xiāo)太多; (3)內存訪(fǎng)問(wèn)效率不高,缺乏相應的優(yōu)化; (4)采用帶鎖共享隊列進(jìn)行數據共享,引入額外開(kāi)銷(xiāo); (5)收發(fā)包操作必須經(jīng)過(guò)Linux內核單線(xiàn)程完成,無(wú)法擴展成多核多線(xiàn)程模式從而提高性能。 2. 2 HPNI的原理 針對上述不足,提出了一種新型的網(wǎng)絡(luò )接口實(shí)現模式,如圖3所示。 圖3 HPNI網(wǎng)絡(luò )接口實(shí)現 HPNI主要包括以下幾項關(guān)鍵技術(shù): (1)通過(guò)Linux提供的UIO框架,實(shí)現了網(wǎng)卡用戶(hù)空間驅動(dòng)程序,UIO能夠把網(wǎng)卡設備內存空間通過(guò)文件系統的方式傳遞給用戶(hù)空間,比如dev/uioXX,因此用戶(hù)空間程序能夠讀取到設備地址段并映射到用戶(hù)空間內存中,比如通過(guò)mmap()。通過(guò)上述方式可以在用戶(hù)空間程序中完成驅動(dòng)程序的功能。這種方法的優(yōu)點(diǎn)是去掉了內存拷貝,同時(shí)因為所有工作都在用戶(hù)空間完成,也節省了系統調用的開(kāi)銷(xiāo)。 (2)關(guān)掉網(wǎng)卡中斷,驅動(dòng)程序采用輪詢(xún)方式,消除中斷引起的開(kāi)銷(xiāo)。 (3)用戶(hù)空間的數據包緩沖區采用huge page分配的連續物理內存區,通過(guò)LinuX提供的huge page接口能夠分配大于4k的頁(yè),從而減少頁(yè)表的大小,降低TLB Miss發(fā)生的概率。另外連續的物理內存塊也能減少地址轉換引起的查表次數,進(jìn)一步提高性能。 (4)任務(wù)線(xiàn)程和CPU核心之間采用靜態(tài)綁定,比如接收包線(xiàn)程綁定1核,處理包線(xiàn)程綁定2核,發(fā)送包線(xiàn)程綁定3核,從而消除核間切換產(chǎn)生的開(kāi)銷(xiāo)。 另外,對于NUMA架構的CPU,每個(gè)任務(wù)都使用本地內存,進(jìn)一步提高內存訪(fǎng)問(wèn)速度。 (5)通過(guò)CAS(Compare And Swap)原子操作,多個(gè)任務(wù)可以在不加鎖的情況下對共享隊列進(jìn)行訪(fǎng)問(wèn),增加和刪除節點(diǎn)。在X86架構下CAS是通過(guò)CMPXCHG指令實(shí)現的,該指令的作用就是把一個(gè)指針指向內存的值同一個(gè)給定的值進(jìn)行比較,如果相等,就對對應內存賦一個(gè)新的值,否則不做任何操作。通過(guò)上述方法可以實(shí)現一種沖突檢測機制,當任務(wù)發(fā)現該隊列己經(jīng)被訪(fǎng)問(wèn)時(shí),主動(dòng)等待直到隊列空閑。無(wú)鎖隊列消除了加鎖引起的開(kāi)銷(xiāo),同時(shí)也能避免死鎖的情況。 (6)基于網(wǎng)卡RSS(Receive-side Scaling)功能可以平滑擴展成多任務(wù)模式,RSS功能可以將收到的數據包基于五元組做哈希運算,從而分發(fā)到不同的隊列當中進(jìn)行并行處理,每一個(gè)隊列可以對應一個(gè)收包任務(wù),從而成倍地提高處理性能。 3對比實(shí)驗及結果分析 3. 1實(shí)驗一 實(shí)驗環(huán)境描述如下:一臺數據包發(fā)生器,最大可產(chǎn)生流量為80Mpps的64字節的數據包。一臺服務(wù)器配置Intel的Sandy Bridge 8核處理器,每個(gè)核心2.0GHZ.操作系統采用RedHat Enterprise Linux 6.2.網(wǎng)卡采用Intel 82599 10G以太網(wǎng)控制器。運行的軟件包含三個(gè)線(xiàn)程,一個(gè)收包線(xiàn)程,一個(gè)轉發(fā)線(xiàn)程,一個(gè)發(fā)送線(xiàn)程。傳統網(wǎng)絡(luò )實(shí)現方式下采用了RAWSocket方式直接收發(fā)處理層二數據包,如圖4所示。 圖4 單線(xiàn)程模式下性能比較圖 實(shí)驗結果如圖5所示,可以得出傳統網(wǎng)絡(luò )接口實(shí)現模式下性能的峰值在180Kpps左右,而且隨著(zhù)網(wǎng)絡(luò )數據流量的增大,性能呈現下降趨勢,主要因為隨著(zhù)網(wǎng)絡(luò )流量的增加,額外的系統開(kāi)銷(xiāo)也在不斷增加。HPNI模式下性能峰值在1.8Mpps左右,而且隨著(zhù)網(wǎng)絡(luò )流量的增加,性能比較穩定,抗沖擊力比較強。 圖5 單線(xiàn)程模式下性能測試結果 3.2實(shí)驗二 采用與實(shí)驗一相同的硬件環(huán)境,同時(shí)開(kāi)啟多個(gè)相同的任務(wù)線(xiàn)程,每個(gè)線(xiàn)程在一個(gè)任務(wù)循環(huán)內完成收包、改包、發(fā)包的工作,比較兩種接口模式在多核多任務(wù)配置下的性能。另外,在HPNI模式下同時(shí)使能網(wǎng)卡的RSS功能,生成多個(gè)隊列分別對應每個(gè)任務(wù)線(xiàn)程,每個(gè)任務(wù)線(xiàn)程靜態(tài)綁定一個(gè)CPU核心,如圖6所示。 圖6 多核多線(xiàn)程模式下網(wǎng)絡(luò )接口性能分析 實(shí)驗結果如圖7所示,在傳統網(wǎng)絡(luò )接口實(shí)現模式下,因為受限于Linux內核處理的瓶頸,即使采用了多線(xiàn)程并發(fā),其性能峰值仍然處于180Kpps左右。HPNI卻能很好地利用多線(xiàn)程的并發(fā),在網(wǎng)卡RSS功能的配合之下性能得到成倍的提高。也可以看到多核下面HPNI的性能并不是一直隨著(zhù)核數的增加而線(xiàn)性增加的,主要因為CPU內的核心之間并不是完全獨立的,它們之間也存在一些共享資源的競爭,比如總線(xiàn)的訪(fǎng)問(wèn),從而對性能產(chǎn)生一些負面的影響。 圖7 多核多線(xiàn)程模式下網(wǎng)絡(luò )接口性能測試結果 4結語(yǔ) 本文分析了傳統Linux下網(wǎng)絡(luò )接口實(shí)現的性能瓶頸,針對其不足提出了一種新型的網(wǎng)絡(luò )接口實(shí)現模式。實(shí)驗結果表明,HPNI可以達到12Mpps的包轉發(fā)速率,完全可以勝任核心路由網(wǎng)絡(luò )以外網(wǎng)絡(luò )聚合點(diǎn)的工作,比如小型企業(yè)網(wǎng)關(guān)等。另外,因為HPNI的容量可以動(dòng)態(tài)調整,因此可以以較高的性?xún)r(jià)比實(shí)現各種性能要求的網(wǎng)絡(luò )轉發(fā)節點(diǎn);谕ㄓ锰幚砥骱蜆藴什僮飨到y的特性,也使得HPNI能夠快速地部署到SDN中。HPNI既可以直接部署在IT server上,也可以部署在虛擬機當中,從而實(shí)現高速NFV的功能。當然,HPNI也存在一點(diǎn)不足,因為采用了輪詢(xún)模式,雖然保證了數據處理的實(shí)時(shí)性,但也導致了較大的CPU負載,當網(wǎng)絡(luò )流量很低的時(shí)候,系統資源利用率不是很高。后續可以針對此點(diǎn)做一些優(yōu)化,比如結合機器學(xué)習算法對輸入數據流量進(jìn)行預測,當輸入流量降低時(shí)通過(guò)CPU提供的pause指令降低CPU負載,從而降低系統資源的使用。 |