齊戰(zhàn)勝 林立友
廈門市美亞柏科信息股份有限公司北京分公司 北京 100025
一個(gè)好的包捕獲系統(tǒng)應(yīng)該盡可能少的丟包,實(shí)時(shí)捕獲流經(jīng)系統(tǒng)的所有數(shù)據(jù)包,而且應(yīng)該較少地占用CPU資源,使得系統(tǒng)擁有更多的時(shí)間來對數(shù)據(jù)包內(nèi)容的進(jìn)行處理。
在包捕獲硬件方面,當(dāng)前市場上有很多千兆以太網(wǎng)報(bào)文處理網(wǎng)卡,如Endace 公司生產(chǎn)的DAG網(wǎng)卡、Liberouter及SCAMPI項(xiàng)目開發(fā)的COMBO網(wǎng)卡等。由于基于硬件的捕包方式價(jià)格比較昂貴,而且系統(tǒng)缺乏一定的靈活性,難以適應(yīng)當(dāng)今瞬息萬變的網(wǎng)絡(luò)發(fā)展現(xiàn)狀與具體的流量分析需求。
在包捕獲軟件方面,設(shè)計(jì)了很多優(yōu)秀的包捕獲函數(shù)庫如Libpcap、nCap、DMA-Ring和PF_RING等。Libpcap是一個(gè)優(yōu)秀的數(shù)據(jù)包捕獲函數(shù)庫,由網(wǎng)卡驅(qū)動(dòng)、操作系統(tǒng)內(nèi)核協(xié)議棧以及套接字接口三個(gè)部分組成,由于消耗了較高的CPU資源、引入了較高的包傳輸延時(shí)等問題,效率較低。為了提高包捕獲的效率,很多研究人員已經(jīng)做了大量的工作,包括從操作系統(tǒng)和應(yīng)用軟件兩個(gè)方面進(jìn)行優(yōu)化。在操作系統(tǒng)方面:由于很多網(wǎng)絡(luò)應(yīng)用都有實(shí)時(shí)性的要求,增加了一些實(shí)時(shí)的內(nèi)核來提高網(wǎng)絡(luò)的實(shí)時(shí)性;為了避免頻繁的中斷造成的中斷活鎖現(xiàn)象,Linux內(nèi)核中引入了一些新的 API函數(shù),簡稱NAPI(NewAPI),通過在重負(fù)載的情況下采用輪詢的方式來提高包捕獲系統(tǒng)的性能。在應(yīng)用軟件方面:一種方式是減少內(nèi)存拷貝次數(shù),Libpcap-mmap、nCap、DMA-RING和PF_RING都采用了這種方式;第二種方式是減少系統(tǒng)調(diào)用的次數(shù)。
綜合分析以上包捕獲技術(shù),發(fā)現(xiàn)以上沒有任何一種包捕獲接口的速度能達(dá)到千兆線速的處理目標(biāo),即使它們的設(shè)計(jì)目標(biāo)是這樣;第二,都是基于單核的系統(tǒng)來進(jìn)行設(shè)計(jì),沒有考慮到發(fā)揮多核平臺和多收發(fā)隊(duì)列網(wǎng)卡的優(yōu)勢來增加系統(tǒng)的吞吐量。
本文在基于PCI-E總線的 Intel X86 多核平臺下,通過充分利用RPS和RFS的包分發(fā)技術(shù)、PF_RING的零拷貝技術(shù)和多核CPU的計(jì)算資源,解決了 Gbit 及其以上鏈路帶寬下的包捕獲問題。
多核處理器是指在一枚處理器中集成兩個(gè)或多個(gè)完整的計(jì)算引擎(內(nèi)核)。操作系統(tǒng)通過在多個(gè)執(zhí)行內(nèi)核之間劃分任務(wù),多核處理器可在特定的時(shí)鐘周期內(nèi)執(zhí)行更多的任務(wù)。
多隊(duì)列網(wǎng)卡是一種技術(shù),最初是用來解決網(wǎng)絡(luò) IO QoS問題的,后來隨著網(wǎng)絡(luò)IO的帶寬的不斷提升,單核CPU不能完全處滿足網(wǎng)卡的需求,通過多隊(duì)列網(wǎng)卡驅(qū)動(dòng)的支持,將各個(gè)隊(duì)列通過中斷綁定到不同的核上,以滿足網(wǎng)卡的需求。常見的有Intel的 82575、82576、82599、82580,Boardcom的57711等。
為了充分利用多核處理器的計(jì)算資源和多隊(duì)列網(wǎng)卡的吞吐能力,本文提出了以下包捕獲模型,如圖1所示。
圖1 包捕獲模型
此模型中采用的是Intel 82576多隊(duì)列網(wǎng)卡,模型工作流程如下:
(1) 數(shù)據(jù)包到達(dá)網(wǎng)卡后,產(chǎn)生硬中斷,網(wǎng)卡RSS根據(jù)數(shù)據(jù)包的IP和端口計(jì)算出hash值,hash值跟中斷個(gè)數(shù)取模后,分成若干個(gè)接收隊(duì)列。
(2) 為了保證分發(fā)到每個(gè)包處理線程的數(shù)據(jù)鏈的完整性(一個(gè)鏈接上的上行和下行數(shù)據(jù)都分發(fā)到一個(gè)包處理線程),所以這里需要利用RPS和RFS技術(shù)對數(shù)據(jù)包進(jìn)行重新計(jì)算Hash值,然后取模分發(fā)到相應(yīng)的CPU核心上。
(3) 改進(jìn)后的PF_RING為每一個(gè)接收隊(duì)列創(chuàng)建一個(gè)虛擬的網(wǎng)絡(luò)接口,通過在內(nèi)核注冊的函數(shù)接收RFS分發(fā)下來的數(shù)據(jù)包,然后送到相應(yīng)的虛擬網(wǎng)絡(luò)接口。
(4) 用戶空間的包處理線程通過PF_RING的虛擬網(wǎng)絡(luò)接口讀取數(shù)據(jù)包并處理。
多隊(duì)列數(shù)據(jù)包分發(fā)技術(shù)接收方擴(kuò)展 (RSS,Receive Side Scaling)。目前的NICs支持多個(gè)接收和傳輸隊(duì)列,即多隊(duì)列。接收的時(shí)候,一個(gè)網(wǎng)卡能夠發(fā)送不同的包到不同的隊(duì)列,為了在不同的CPU之間分散處理。NIC針對每一個(gè)包,通過一個(gè)過濾器來指定這個(gè)包屬于少數(shù)幾個(gè)流中的一個(gè)流。每個(gè)流中的數(shù)據(jù)包被控制在一個(gè)單獨(dú)的接收隊(duì)列中,而隊(duì)列輪回的被CPU進(jìn)行處理。這種機(jī)制就叫做RSS。RSS的目標(biāo)和其他控制技術(shù)目的都是為了提高數(shù)據(jù)吞吐性能。
RSS中的過濾器是一個(gè)基于L3和L4層頭部的hash函數(shù)。例如,基于IP地址和TCP端口的4元組的hash函數(shù)。最常見的RSS硬件實(shí)現(xiàn)中,使用了128個(gè)間接表,其中每個(gè)表存儲一個(gè)隊(duì)列號(注,網(wǎng)卡的隊(duì)列數(shù)比較少,比如igb是8個(gè),bnx2是5個(gè))。針對某個(gè)包而言,使用這個(gè)包計(jì)算出的hash值(hash是Toeplitz算法)的低7位先確定間接表,再從間接表中的值訪問隊(duì)列。
多隊(duì)列網(wǎng)卡的驅(qū)動(dòng)提供了一個(gè)內(nèi)核模塊參數(shù),用來指定硬件隊(duì)列個(gè)數(shù)。一個(gè)典型的RSS配置中,最好的是一個(gè)CPU對應(yīng)一個(gè)接收隊(duì)列。每個(gè)接收隊(duì)列有一個(gè)單獨(dú)的IRQ,即中斷號。NIC通過IRQ來通知CPU什么時(shí)候新的數(shù)據(jù)包到達(dá)了指定的隊(duì)列。有效的隊(duì)列到IRQ的映射是由/proc/interrupts來指定的。一些系統(tǒng)會運(yùn)行 irqbalance服務(wù),這個(gè)服務(wù)會動(dòng)態(tài)的優(yōu)化IRQ的親和性。
RPS(Receive Packet Steering) 邏輯上是一種以軟件的方式來實(shí)現(xiàn)RSS。在數(shù)據(jù)包被從網(wǎng)卡驅(qū)動(dòng)傳向網(wǎng)絡(luò)協(xié)議棧時(shí),RPS在底半環(huán)境(通過軟中斷來實(shí)現(xiàn)的,在硬中斷處理函數(shù)之后)中被調(diào)用。通過把數(shù)據(jù)包放在目標(biāo)CPU的backlog隊(duì)列,并喚醒CPU來處理,之后隊(duì)列中數(shù)據(jù)包被發(fā)送到網(wǎng)絡(luò)協(xié)議棧進(jìn)行處理。
RPS相比RSS有幾個(gè)好處:
(1) RPS能夠被任何NIC使用。
(2) 軟件過濾器能夠輕易的被添加,用來hash新的協(xié)議。
(3) 它不會增加硬件設(shè)備的中斷。
決定目標(biāo)CPU的第一步是基于包的地址和端口(有的協(xié)議是2元組,有的協(xié)議是4元組)來計(jì)算hash值。這個(gè)值與這個(gè)包的流保持一致。這個(gè)hash值要么是由硬件來提供的,要么是由協(xié)議棧來計(jì)算的。每一個(gè)接收硬件隊(duì)列有一個(gè)相關(guān)的CPU列表,RPS可以將包放到這個(gè)隊(duì)列中進(jìn)行處理。對于每一個(gè)接收到的包,指向這個(gè)列表的索引是通過流hash值對列表大小取模來計(jì)算的。被指向的 CPU是處理包的目標(biāo)CPU,并且這個(gè)包被加到CPU的backlog隊(duì)列的尾部。經(jīng)過底半處理后,IPI被發(fā)送到這個(gè)包所插到的那個(gè)CPU。IPI喚醒遠(yuǎn)程CPU來處理backlog隊(duì)列,之后隊(duì)列中數(shù)據(jù)包被發(fā)送到網(wǎng)絡(luò)協(xié)議棧進(jìn)行處理。
RPS要求內(nèi)核編譯了CONFIG_RPS選項(xiàng)(SMP上默認(rèn)是打開的)。盡管編譯到內(nèi)核,直到被配置了才能啟用。對于某個(gè)接收隊(duì)列,RPS可以轉(zhuǎn)發(fā)流量到哪個(gè) CPU,是由/sys/class/net/queues/rx-/rps_cpus來控制的。這個(gè)文件實(shí)現(xiàn)了CPU的位圖。默認(rèn),當(dāng)值是0,RPS是無效的,數(shù)據(jù)包是由中斷的CPU來處理的。
RFS(Receive Flow Steering),RPS只依靠hash來控制數(shù)據(jù)包,提供了好的負(fù)載平衡,但是它沒有考慮應(yīng)用程序的位置(注:這個(gè)位置是指程序在哪個(gè) cpu上執(zhí)行)。RFS則考慮到了應(yīng)用程序的位置。RFS的目標(biāo)是通過指派應(yīng)用線程正在運(yùn)行的CPU來進(jìn)行數(shù)據(jù)包處理,以此來增加數(shù)據(jù)緩存的命中率。RFS依靠RPS的機(jī)制插入數(shù)據(jù)包到指定CPU的backlog隊(duì)列,并喚醒那個(gè)CPU來執(zhí)行。
RFS中,數(shù)據(jù)包并不會直接的通過數(shù)據(jù)包的hash值被轉(zhuǎn)發(fā),但是hash值將會作為流查詢表的索引。這個(gè)表映射數(shù)據(jù)流與處理這個(gè)流的CPU。這個(gè)數(shù)據(jù)流的hash值(就是這個(gè)流中的數(shù)據(jù)包的 hash值)將被用來計(jì)算這個(gè)表的索引。流查詢表的每條記錄中所記錄的CPU是上次處理數(shù)據(jù)流的CPU。如果記錄中沒有CPU,那么數(shù)據(jù)包將會使用RPS來處理。多個(gè)記錄會指向相同的CPU。確實(shí),當(dāng)流很多而CPU很少時(shí),很有可能一個(gè)應(yīng)用線程處理多個(gè)不同hash值的數(shù)據(jù)流。
RFS需要內(nèi)核編譯 CONFIG_RPS選項(xiàng),直到明顯的配置,RFS才起作用。全局?jǐn)?shù)據(jù)流表(rps_sock_flow_table)的總數(shù)可以通過下面的參數(shù)來設(shè)置:/proc/sys/net/core/rps_sock_flow_entries每個(gè)隊(duì)列的數(shù)據(jù)流表總數(shù)可以通過下面的參數(shù)來設(shè)置:/sys/class/net//queues/rx-/rps_flow_cnt。
通過調(diào)用 SetThreadAffinityMask,就能為各個(gè)線程設(shè)置親緣性屏蔽:
該函數(shù)中的 hThread參數(shù)用于指明要限制哪個(gè)線程,dwThreadAffinityMask用于指明該線程能夠在哪個(gè)CPU上運(yùn)行。dwThreadAffinityMask必須是進(jìn)程的親緣性屏蔽的相應(yīng)子集。返回值是線程的前一個(gè)親緣性屏蔽。
例如,可能有一個(gè)包含4個(gè)線程的進(jìn)程,它們在擁有4個(gè)CPU的計(jì)算機(jī)上運(yùn)行。如果這些線程中的一個(gè)線程正在執(zhí)行非常重要的操作,而你想增加某個(gè)CPU始終可供它使用的可能性,為此你對其他3個(gè)線程進(jìn)行了限制,使它們不能在CPU 0上運(yùn)行,而只能在CPU 1、2和3上運(yùn)行。因此,若要將3個(gè)線程限制到CPU 1、2和3上去運(yùn)行,可以這樣操作:
2.5.1 PF_RING技術(shù)簡介
PF_RING是Luca研究出來的基于Linux內(nèi)核級的高效數(shù)據(jù)包捕獲技術(shù)。PF_RING基本原理是將網(wǎng)卡接收的數(shù)據(jù)包存儲在一個(gè)環(huán)狀緩存,這也是為什么叫RING的原因,這個(gè)環(huán)狀緩存有兩個(gè)接口,一個(gè)供網(wǎng)卡向其中寫數(shù)據(jù)包,另一個(gè)為應(yīng)用層程序提供讀取數(shù)據(jù)包的接口,讀取數(shù)據(jù)包的接口通過 mmap函數(shù)(將一個(gè)文件或其它對象映射進(jìn)內(nèi)存)實(shí)現(xiàn)的。圖2顯示了PF_RING的工作原理。
圖2 PF_RING
2.5.2 PF_RING技術(shù)優(yōu)化
由于 PF_RING需要定制的網(wǎng)卡驅(qū)動(dòng)的支持,并且PF_RING的虛擬網(wǎng)絡(luò)接口目前僅支持 DNA(Direct NIC Access)模式,所以為了適應(yīng)本模型的需要,本文做了以下優(yōu)化:
(1) 修改PF_RING定制的網(wǎng)卡驅(qū)動(dòng),開啟網(wǎng)卡多接收隊(duì)列的功能;
(2) 把PF_RING的DNA模塊的虛擬網(wǎng)絡(luò)接口功能移植到NAPI模式下。
圖3顯示了測試環(huán)境的部署情況。
圖3 測試環(huán)境
測試服務(wù)器,i3 CPU 2.93GHZ,4G內(nèi)存,2塊Intel 82576千兆網(wǎng)卡,Red Hat Enterprise 6.0系統(tǒng)(內(nèi)核已升級為2.6.39),
網(wǎng)絡(luò)流量發(fā)生儀,基于 Intel IXP2400 的網(wǎng)絡(luò)處理器,用于產(chǎn)生測試的流量。
控制端是普通的PC機(jī),用來控制流量的組織、發(fā)送和控制。
3.2.1 捕包性能測試與分析
控制端控制流量發(fā)生儀發(fā)送 1000Mbit,長度分別為128、512 和 1024 字節(jié)的數(shù)據(jù)包,在被測試主機(jī)上分別采用 Libpcap,PF_RING和本文捕包模型接收測試流量。圖4顯示了當(dāng)丟包數(shù)為零時(shí)各個(gè)包捕獲方式可以接收的最大流速率。
圖4 吞吐率對比測試圖
分析圖4的結(jié)果可以得出:在 1024 字節(jié)、512字節(jié)和128字節(jié),1000Mbit 的鏈路環(huán)境下,Multi-PF_RING和PF_RING 接收速率沒有什么區(qū)別。
3.2.2 CPU使用率測試與分析
CPU 空閑率是衡量包捕獲接口的重要指標(biāo),空閑率高的CPU 可以有更多的時(shí)間用來做與應(yīng)用更加相關(guān)的工作,控制端控制流量發(fā)生儀發(fā)送 100Mbit 至 1000Mbit,字節(jié)長度為512字節(jié)的鏈路流量。
圖5 CPU使用率對比圖
分析圖 5結(jié)果可以得出:同等接收速率下,Multi-PF_RING的CPU使用率最低。即使在1000Mbit/s時(shí),CPU仍然有 70%左右的空閑率,可以讓 CPU有足夠的計(jì)算資源對數(shù)據(jù)包進(jìn)行處理。
控制端控制流量發(fā)生儀發(fā)送 IP 包頭地址輪轉(zhuǎn)變化的IP 包,在測試服務(wù)器端觀察 Multi-PF_RING接收數(shù)據(jù)包的情況,發(fā)現(xiàn)測試服務(wù)器接收的 IP 包與流量發(fā)生儀發(fā)送的 IP包內(nèi)容一致,驗(yàn)證了程序的正確性;每個(gè)核心收到的鏈路數(shù)據(jù)是完整的,驗(yàn)證了程序?qū)?shù)據(jù)包的分發(fā)是符合應(yīng)用邏輯的。
本文首先提出了一種基于多核架構(gòu)和多收發(fā)隊(duì)列的包捕獲模型,然后對包捕獲模型中涉及的核心技術(shù)進(jìn)行了詳細(xì)介紹和分析,并結(jié)合本模型捕包的需要對 PF_RING的接口進(jìn)行了優(yōu)化。實(shí)驗(yàn)結(jié)果表明,本文設(shè)計(jì)的 Multi-PF_RING 模型在保持高吞吐量的同時(shí),具有更低的CPU使用率,給CPU留出了足夠的資源進(jìn)行數(shù)據(jù)包的處理,并且保證了同一鏈接的數(shù)據(jù)始終被分發(fā)到一個(gè)CPU核心上。本文的不足之處是沒有考慮負(fù)載均衡的情況,當(dāng)鏈接數(shù)目較少或者同一鏈接數(shù)據(jù)超多的情況下,會造成個(gè)別CPU核心超負(fù)荷運(yùn)轉(zhuǎn)而其它核心閑置的情況,后期會進(jìn)一步研究負(fù)載均衡的問題。
[1]張顯,黎文偉.基于多核平臺的數(shù)據(jù)包捕獲方法性能評估[J].計(jì)算機(jī)應(yīng)用研究.2011.
[2]孫江.基于多核處理器的普適性報(bào)文捕獲技術(shù)研究[D].解放軍信息工程大學(xué).2011.
[3]笱程成.基于多核架構(gòu)的高速 IP包捕獲技術(shù)研究[D].解放軍信息工程大學(xué).2010.
[4]http://www.ntop.org/products/pf_ring.
http://code.google.com/p/kernel/wiki/NetScalingGuide.