楊 惠,李 韜,呂高鋒,全 巍,戴幻堯
(1. 國防科技大學(xué) 計算機學(xué)院, 湖南 長沙 410073; 2. 中國洛陽電子裝備試驗中心, 河南 洛陽 471003)
隨著互聯(lián)網(wǎng)規(guī)模的不斷擴大和新興網(wǎng)絡(luò)技術(shù)的應(yīng)用,不斷增長的網(wǎng)絡(luò)流量對網(wǎng)絡(luò)核心設(shè)備的處理能力提出了更高要求。多核處理器計算性能高和軟件編程靈活性強的優(yōu)勢,使得大量的軟件路由器和軟件交換機在多核平臺上被部署。具備高可編程性的通用多核處理器是網(wǎng)絡(luò)設(shè)備中廣泛采用的數(shù)據(jù)平面處理核心器件[1-5]。然而,傳統(tǒng)網(wǎng)卡只能支持最大分段長度(Max Segment Size,MSS)大小的數(shù)據(jù)傳輸,當(dāng)請求大量數(shù)據(jù)時,傳輸控制協(xié)議(Transmission Control Protocol,TCP)發(fā)送方必須將大塊數(shù)據(jù)拆分成MSS大小的數(shù)據(jù)塊,然后進一步封裝為數(shù)據(jù)包形式,以便最終在網(wǎng)絡(luò)中進行傳輸。由于多核處理器需要對每個分段進行處理,降低了其處理效率。TCP分段卸載(TCP Segment Offload, TSO)技術(shù)的提出[5],利用網(wǎng)卡分割大數(shù)據(jù)包,降低中央處理器(Central Processing Unit,CPU)發(fā)送數(shù)據(jù)包的負載,從而支持大報文的直接發(fā)送,報文的切分與校驗等分組深度處理全部交給硬件實現(xiàn)。然而,基于TSO技術(shù)的網(wǎng)絡(luò)分組深度處理需要軟硬件的協(xié)同工作,在軟硬件協(xié)同分組處理流程中,軟硬件的通信開銷過大會嚴重影響系統(tǒng)進行分組深度處理的性能。另外,報文的拆分校驗等處理流程全部交由硬件實現(xiàn),硬件復(fù)雜度高。
本文通過分析基于多核的大報文發(fā)送流程中的軟硬件各個部分的開銷,消除和弱化大報文發(fā)送的性能瓶頸,基于軟硬件協(xié)同的輕量級分組輸入/輸出(Input/Output,I/O)技術(shù)和支持大報文發(fā)送的傳統(tǒng)TSO技術(shù),提出了一種面向高速分組轉(zhuǎn)發(fā)的數(shù)據(jù)分段卸載發(fā)送機制。
TSO技術(shù)支持TCP發(fā)送方CPU直接將大塊數(shù)據(jù)(最大支持64 KB大小)交給網(wǎng)絡(luò)設(shè)備處理,由網(wǎng)絡(luò)設(shè)備進行TCP段的分割,將一部分CPU的處理工作轉(zhuǎn)移到網(wǎng)卡,從而減少CPU必須處理的數(shù)據(jù)包數(shù)量,達到提高網(wǎng)絡(luò)處理性能的目的。支持TSO技術(shù)的網(wǎng)卡,需要支持TSO和分散-聚集(Scatter-Gather, SG)技術(shù),以及TCP校驗和計算功能,由網(wǎng)卡驅(qū)動或網(wǎng)卡硬件完成報文分段和TCP校驗和計算功能,因而TSO技術(shù)需要網(wǎng)絡(luò)設(shè)備驅(qū)動或者網(wǎng)絡(luò)設(shè)備提供報文分段功能,對于網(wǎng)絡(luò)設(shè)備的要求較高,軟硬復(fù)雜度高。更為通用的分段卸載(General Segment Offload, GSO)技術(shù)將大報文分段的時機推遲到將數(shù)據(jù)報文提交給網(wǎng)絡(luò)設(shè)備驅(qū)動之前完成,并且支持TCPv4之外的其他協(xié)議類型,如TCPv6、UDP和DCCP等。該技術(shù)需要網(wǎng)絡(luò)設(shè)備支持通用GSO和SG功能,性能提升效果比TSO技術(shù)低。
Scatter-Gather是一種與非連續(xù)物理地址傳輸?shù)膲K直接內(nèi)存存取(Direct Memory Access,DMA)[6]方式相對應(yīng)的DMA方式。它通過一個鏈表描述物理不連續(xù)的內(nèi)存地址,將鏈表首地址送往DMA控制器。DMA 控制器傳輸完一塊物理連續(xù)的數(shù)據(jù)后,不發(fā)中斷,根據(jù)鏈表記錄內(nèi)容傳輸下一塊物理不連續(xù)的數(shù)據(jù),直到鏈表中所有描述符內(nèi)容傳輸完成發(fā)起一次中斷。網(wǎng)絡(luò)設(shè)備支持該技術(shù)需要支持從多個不同區(qū)域獲取報文數(shù)據(jù)并且組裝在一起。
為了減少報文處理過程中軟硬件交互中斷的代價,Packetshader采用大報文緩沖區(qū)的方式,靜態(tài)地預(yù)分配兩個大的緩沖區(qū)(skb控制信息緩沖區(qū)和分組數(shù)據(jù)緩沖區(qū)),通過連續(xù)存儲每個接收分組的skb控制信息和分組數(shù)據(jù),避免緩沖區(qū)申請/釋放以及描述符的轉(zhuǎn)換操作,有效降低分組I/O開銷和訪存開銷。[3]面向高速分組轉(zhuǎn)發(fā)提出的自描述緩沖區(qū) (Self-Described Buffer, SDB)管理機制[7-8],將描述符、skb控制信息以及分組數(shù)據(jù)連續(xù)存儲在一個緩沖區(qū)中,大大降低系統(tǒng)的緩沖區(qū)管理開銷,實現(xiàn)了無中斷的報文傳輸,但所有報文在發(fā)送給網(wǎng)絡(luò)設(shè)備之前,都要拷貝到SDB管理的固定緩沖區(qū)中,拷貝代價高,成為制約大報文發(fā)送性能的瓶頸。
圖1 支持輕量級I/O的報文發(fā)送機制Fig.1 Packet sending mechanism with lightweight I/O
多核輕量級的分組I/O技術(shù),是一種低開銷的分組處理軟硬件通信機制,通過緩沖區(qū)管理卸載技術(shù)等,實現(xiàn)分組的零拷貝、無中斷的下發(fā),從而降低分組在軟硬件的通信開銷[9-10]。支持輕量級I/O的軟硬件協(xié)同分組處理系統(tǒng)[11]將包含控制信息的描述符和分組數(shù)據(jù)連續(xù)存儲在多核共享的地址連續(xù)的存儲緩沖區(qū)中。共享緩沖區(qū)不再采用核調(diào)度的軟件管理方法,而是卸載到專用網(wǎng)絡(luò)加速引擎上由硬件管理。在系統(tǒng)初始化時,將共享緩沖區(qū)的描述符填入硬件管理的空閑描述符塊隊列中;當(dāng)數(shù)據(jù)報文到達,根據(jù)空閑描述符隊列存儲的地址,分配一個空閑描述符,與數(shù)據(jù)報文組裝好通過外設(shè)組建高速互聯(lián)(Peripheral Component Interconnect Express, PCIE)送往共享緩沖區(qū)對應(yīng)的地址空間;而數(shù)據(jù)報文從共享緩沖區(qū)地址空間下發(fā)時,如圖1所示,首先為要發(fā)送的報文獲取一個共享緩沖區(qū)區(qū)域,將報文內(nèi)容直接由skb->data指向的線性緩沖區(qū)拷貝到共享緩沖區(qū)中,完成拷貝后,將skb釋放,構(gòu)造一個發(fā)送描述符控制塊,通知專用網(wǎng)絡(luò)加速引擎有新的報文需要發(fā)送,專用網(wǎng)絡(luò)加速引擎根據(jù)發(fā)送描述符控制塊指示的報文DMA地址,讀取共享緩沖區(qū)中的報文內(nèi)容,完成報文發(fā)送。專用網(wǎng)絡(luò)加速引擎硬件回收對應(yīng)的描述符,并重新進入空閑描述符隊列,等待新的數(shù)據(jù)報文使用。該共享緩沖區(qū)以塊為單位組織、申請和釋放,解放了核對共享緩沖區(qū)地址的管理。描述符和報文塊以單向鏈表的形式,在共享緩沖區(qū)內(nèi)組織。因此,系統(tǒng)在處理分組時,只要空閑描述符隊列具有空閑描述符,數(shù)據(jù)報文即可上傳至共享緩沖區(qū),等待CPU核處理,無須中斷響應(yīng),也無須多次訪存緩沖區(qū)。
為對報文發(fā)送開銷進行分析,做出如表1所示的假設(shè)。
表1 發(fā)送分段開銷假設(shè)
標準網(wǎng)卡不支持大報文發(fā)送流程如圖2所示,skb指向應(yīng)用需要傳輸?shù)臄?shù)據(jù)及其報文頭內(nèi)容,使用線性緩沖區(qū)存放報文內(nèi)容,構(gòu)造報文時,skb指向的報文長度最大僅為1514 B。網(wǎng)卡硬件根據(jù)描述符指向的地址獲取報文內(nèi)容并將報文發(fā)送。標準網(wǎng)卡普通發(fā)送n個1.5 KB報文的報文處理開銷可表示為:n·Na+n·NS+n·ND+n·NDMA-R。
圖3為標準網(wǎng)卡支持大報文發(fā)送TSO機制流程圖,大報文被發(fā)送到網(wǎng)卡硬件才進行報文的分段。發(fā)送n·1.5 KB報文處理開銷可表示為:n·Na+NS+ND+n2·NDMA-R+n·NHF。
圖2 標準網(wǎng)卡不支持大報文發(fā)送流程圖Fig.2 Sending flow on standard network card (large packet sending is not supported)
圖3 標準網(wǎng)卡支持大報文發(fā)送TSO機制流程圖Fig.3 Sending flow on standard network card (TSO)
圖4 支持輕量級分組I/O的網(wǎng)卡大報文發(fā)送流程圖Fig.4 Diagram of sending flow for based on the multi-core packet processing system with lightweight I/O
圖4為支持輕量級分組I/O的網(wǎng)卡實現(xiàn)大報文發(fā)送流程圖,大報文被發(fā)送到網(wǎng)卡驅(qū)動軟件進行處理后,完成報文的分段,為每個分段添加報文頭部、重新計算每個分段的校驗和等功能,并拷貝到指定的多核共享緩沖區(qū)中,也就是skb指向報文的內(nèi)容需分段拷貝至共享緩沖區(qū)后才能發(fā)送出去,無須硬件支持報文拆分組裝功能,減小了大報文在協(xié)議棧處理的開銷,但驅(qū)動層存在報文拷貝開銷,且報文分段效率相較于硬件分段較低。發(fā)送n·1.5 KB路徑報文處理開銷約表示為:n·Na+NS+n·ND+n·Nc+n·NDF+n·NDMA-R。
圖5為提出的數(shù)據(jù)分段卸載開銷示意圖,大報文被發(fā)送到網(wǎng)卡驅(qū)動軟件并被處理后,完成報文的分段,省去了報文拷貝到指定軟件緩沖區(qū)中的開銷。發(fā)送n·1.5 KB報文發(fā)送路徑報文處理開銷約表示為:n·Na+NS+ND+n·NDF+n·NDMA-R。
圖5 數(shù)據(jù)分段卸載開銷Fig.5 Cost for packet segment offloading
為了降低硬件分段的處理和緩沖區(qū)報文拷貝開銷,將大報文在驅(qū)動層完成切分,只拷貝報文頭到共享緩沖區(qū),拷貝的同時驅(qū)動完成報文頭內(nèi)容的更新,報文體切分后依然存放在原內(nèi)存空間。相較于網(wǎng)卡支持的TSO機制,硬件切分報文頭,更新報文頭內(nèi)容的工作卸載到驅(qū)動實現(xiàn),同時降低了發(fā)送拷貝代價。于是驅(qū)動拆分報文后,分段報文的存儲方式為,分段報文頭存儲在共享緩沖區(qū)中,分段報文體依然存放在線性緩沖區(qū)和頁緩沖區(qū)中。
圖6為數(shù)據(jù)分段卸載方法中驅(qū)動分段及分段報文存儲原理圖。解析報文頭,對于TCP報文,確認報文分段數(shù)目以及是否需要進行報文分片。對于需要分片的報文,根據(jù)需要分片的數(shù)目,將一個大報文的報文頭拷貝多份至共享緩沖區(qū)中,并同時更新報文頭,形成切分后的報文頭1、2、3、4。分段后的小報文,第一段的報文頭存儲在共享緩沖區(qū),第一段的報文體依舊存儲在線性緩沖區(qū),第二段的報文頭存儲在共享緩沖區(qū),第二段的報文體一部分存儲在線性緩沖區(qū),其余部分存儲在頁緩沖區(qū)中。為所有的分段報文的頭和體構(gòu)造一個發(fā)送描述符鏈,硬件根據(jù)發(fā)送描述符鏈獲取每個報文分段或所有分片的每個報文分段所在位置,并獲取每個報文分段或所有分片的每個分段報文內(nèi)容。將多個報文分段拼裝成一個報文或多個分片報文,完成TCP校驗和計算以及循環(huán)冗余校驗(Cyclic Redundancy Check,CRC)和計算后,完成報文發(fā)送。
圖6 驅(qū)動分段及分段報文存儲原理圖Fig.6 Drive segmentation and storage principle diagram
數(shù)據(jù)分段卸載發(fā)送方法流程如圖7所示。
圖7 數(shù)據(jù)分段卸載發(fā)送方法流程圖Fig.7 Sending flow for data segment offloading and sending mechanism
步驟1:獲取skb線性緩沖區(qū)和頁緩沖區(qū)數(shù)目,解析報文頭,對于TCP報文,確認報文分段數(shù)目以及是否需要進行報文分片(skb->len>1514 B);
步驟2:對于需要分片的報文,根據(jù)需要分片的數(shù)目,將報文頭拷貝至共享緩沖區(qū)的多個分區(qū)中,完成每個分片報文頭內(nèi)容的更新,無須分片則跳過此步驟;
步驟3:根據(jù)報文分段,為每個分段完成DMA映射;
步驟4:為每個分片的每個報文分段,包括專用緩沖區(qū)、線性緩沖區(qū)、頁緩沖區(qū)分別獲取一個發(fā)送描述符,填充相關(guān)字段,構(gòu)造描述符鏈表。在獲取描述符時需獲得鎖,確保不會有多個進程獲得同一個描述符;
步驟5:將skb緩存到skb緩沖區(qū)環(huán),并更新發(fā)送描述符緩沖區(qū)環(huán)的寫write_p指針;
步驟6:構(gòu)造一個發(fā)送描述符控制塊,通知硬件有新的報文需要發(fā)送;
步驟7:硬件根據(jù)發(fā)送描述符控制塊的內(nèi)容DMA讀發(fā)送描述符鏈,獲取所有分片中每個報文分段所在的位置;
步驟8:根據(jù)描述符中指示報文分段地址,DMA讀取所有分片的每個分段報文內(nèi)容。將屬于同一個分片的多個報文分段拼裝成一個分片報文;
步驟9:網(wǎng)卡硬件計算TCP校驗以及CRC,完成報文發(fā)送后,向發(fā)送描述符進行回寫,通知軟件報文發(fā)送完成;
步驟10:驅(qū)動處理中斷或軟中斷,檢查發(fā)送描述符的回寫狀態(tài),若發(fā)送完成則將skb從skb緩沖區(qū)環(huán)出隊,完成skb的釋放,并更新發(fā)送描述符緩沖區(qū)環(huán)的read_p指針。
上述步驟4中,為每個分片的每個報文分段,包括專用緩沖區(qū)、線性緩沖區(qū)、頁緩沖區(qū)分別獲取的發(fā)送描述符所構(gòu)造的描述符鏈表,以支持鏈式DMA,允許碎片化的存儲中的數(shù)據(jù)一次DMA完成,描述符鏈表中的每個發(fā)送描述符,都包含了64位存儲地址信息、長度信息等。
上述步驟6中,構(gòu)造的描述符控制塊描述的信息為描述符鏈表存儲的地址及長度信息,描述符控制塊由驅(qū)動構(gòu)造好之后,以寫寄存器的方式通知網(wǎng)卡硬件,以實現(xiàn)將整個描述符鏈表讀取到硬件的功能。
為有效驗證大報文數(shù)據(jù)分段卸載發(fā)送功能和性能,設(shè)計并實現(xiàn)了原型系統(tǒng)。原型系統(tǒng)基于國防科技大學(xué)計算機學(xué)院自主研發(fā)的高性能通用64位CPU FT-1500A[12]與自主研制的網(wǎng)絡(luò)專用協(xié)加速引擎網(wǎng)絡(luò)處理引擎(Network Processing Engine,NPE)[7]構(gòu)建。其中網(wǎng)絡(luò)專用協(xié)加速引擎在現(xiàn)場可編程門陣列(Field-Programmable Gate Array,F(xiàn)PGA)上實現(xiàn),F(xiàn)PGA器件采用Stratix V 5SGXMA3K3F40C2X。
本實驗的軟件測試環(huán)境包括:ubuntu 14.04操作系統(tǒng)、NPDK 2.0版本軟件開發(fā)環(huán)境提供的NPE網(wǎng)口驅(qū)動[13-14]、用戶配置程序。
NPDK環(huán)境將所有軟硬件的初始化函數(shù)封裝在環(huán)境庫內(nèi),調(diào)用初始化函數(shù)create_net_device(dma_cnt,disp_mode),dma_cnt表示硬件啟動多少個DMA通道,與軟件處理線程數(shù)對應(yīng),每個DMA通道對應(yīng)一個處理線程,綁定在一個指定的CPU核上運行;disp_mode指定報文分派模式,循環(huán)分派或端口綁定分派。在不超過硬件最大支持DMA通道數(shù)情況下,通過重復(fù)調(diào)用pthread_create(&p_t,&attr,start_npe_thread,tp)函數(shù),選擇自由創(chuàng)建多個處理線程,創(chuàng)建線程數(shù)與dma_cnt數(shù)相同,start_npe_thread即為業(yè)務(wù)處理線程。線程創(chuàng)建后,顯示指定線程綁定到哪個CPU核上運行,線程的創(chuàng)建與CPU親和設(shè)置都使用標準的libpthread庫函數(shù)。線程輪詢到報文后,立即調(diào)用報文發(fā)送函數(shù)進行發(fā)送,完成一個報文的轉(zhuǎn)發(fā)操作。發(fā)送函數(shù)send_pkt(*pkt, outport, pkt_len),pkt表示報文指針,outport表示輸出端口號,pkt_len表示發(fā)送長度。
為支持提出的數(shù)據(jù)分段卸載發(fā)送機制,對軟件做出的修改有:增加驅(qū)動對大報文的各個分段進行DMA映射功能;增加對TSO功能的支持(netdev->features屬性修改);增加驅(qū)動報文分段功能;驅(qū)動下發(fā)描述符由單個變?yōu)槎鄠€,修改skb軟中斷,讀取發(fā)送狀態(tài)寄存器,修改skb回收機制。對硬件做出的修改有:增加skb發(fā)送狀態(tài)計數(shù)器寄存器;支持一次處理多個描述符,同一報文內(nèi)容可能需要從不同的區(qū)域獲取,將這幾個區(qū)域的報文內(nèi)容獲取后拼裝,完成TCP校驗、計算和更新。
數(shù)據(jù)發(fā)送性能測試場景如圖8所示。將由國產(chǎn)CPU、高性能FPGA和存儲陣列構(gòu)建的支持數(shù)據(jù)分段卸載發(fā)送機制的原型系統(tǒng),通過光纖和千兆網(wǎng)線連接服務(wù)器的萬兆網(wǎng)卡和千兆網(wǎng)卡接口。服務(wù)器萬兆網(wǎng)卡接口和原型系統(tǒng)配置成同一網(wǎng)段,由串口登錄到存儲板CPU。
圖8 數(shù)據(jù)發(fā)送性能測試場景Fig.8 Test scenario for data transmission performance
表2為支持數(shù)據(jù)分段卸載發(fā)送機制前后性能對比。由表2實驗數(shù)據(jù)可以看出,當(dāng)配置性能測試參數(shù)為單線程時,不管是iscsi的讀性能還是iperf的發(fā)送性能,在系統(tǒng)支持大報文的數(shù)據(jù)分段卸載發(fā)送機制后,降低了協(xié)議棧分段、驅(qū)動拷貝等開銷,性能有較大的提升。
表2 支持數(shù)據(jù)分段卸載發(fā)送機制前后性能對比Tab.2 Performance comparison before and after supporting data segmentation offloading and sending mechanism
受限于國產(chǎn)高性能CPU面向通用計算,并沒有針對網(wǎng)絡(luò)處理應(yīng)用的性能瓶頸,單線程單隊列單分區(qū)的iscsi讀性能并沒有達到線速。因此,建立iscsi多個鏈接,測試在CPU不構(gòu)成性能瓶頸的前提下,發(fā)送性能是否達到線速,如圖9所示。
圖9 自主原型系統(tǒng)與商用網(wǎng)卡系統(tǒng)iscsi讀性能對比Fig.9 The iscsi read performance comparison of domestic prototype system and business-used network
使用fdisk /dev/dfa命令,將SSD固態(tài)盤依次分為1~5個區(qū)進行測試,在/etc/iet/ietd.conf文件中為每個分區(qū)增加一個iscsi節(jié)點設(shè)置。每次分區(qū)完之后使用/etc/init.d/iscsi-target start命令,啟動iscsi-target服務(wù),建立基于多個分區(qū)的多個iscsi鏈接。在服務(wù)器上與存儲板建立1個或多個iscsi連接后,依次測試1~5個分區(qū)時iscsi讀性能,即數(shù)據(jù)發(fā)送性能,使用fio測試工具統(tǒng)計測試iscsi性能。
對比打開TSO功能的82599商用網(wǎng)卡[13]加Intel處理器構(gòu)建的系統(tǒng)[15],當(dāng)iscsi建立鏈接為5個時,支持數(shù)據(jù)分段卸載發(fā)送機制的自主原型系統(tǒng)與商用網(wǎng)卡構(gòu)建系統(tǒng)均達到了線速水平。
實驗結(jié)果顯示,支持數(shù)據(jù)分段卸載發(fā)送機制的自主原型系統(tǒng),iscsi讀性能和iperf發(fā)送性能均有較大提升,相較于商用網(wǎng)卡構(gòu)建系統(tǒng),均達到了線速水平。數(shù)據(jù)分段卸載發(fā)送機制支持輕量級分組I/O,軟硬件復(fù)雜度較低,能夠更好地支撐基于通用多核多線程的高速分組轉(zhuǎn)發(fā)。