王雷淘,喬廬峰,續(xù) 欣
(陸軍工程大學 通信工程學院,江蘇 南京 210001)
網(wǎng)絡技術(shù)的飛速發(fā)展帶來了網(wǎng)絡流量的爆炸式增長,衛(wèi)星通信以其廣闊的覆蓋范圍、穩(wěn)定可靠的性能、靈活機動的接入、大容量寬頻帶、成本對距離不敏感等優(yōu)點,在全球互聯(lián)網(wǎng)中扮演著愈加重要的角色[1-3]。星載路由器的一大特點在于其帶寬和存儲資源十分珍貴。DDR3 以其存儲容量大、讀寫速度快等特點,越來越多的被應用于路由器中隊列管理器的設計當中[4]。常見的基于DDR3 的隊列管理器中,都采取將數(shù)據(jù)實際存入DDR3 中,將地址指針送入隊列控制器中的鏈表建立虛擬出口隊列的方式[5]。然而,當需要讀出數(shù)據(jù)時,輸出電路僅能從隊列中獲取待輸出數(shù)據(jù)包存儲位置的起始地址指針,而無法獲取數(shù)據(jù)包的實際長度,在實際操作時,需要暫停DDR3 的讀操作以獲取數(shù)據(jù)包長度信息,這無疑降低了DDR3 的讀寫效率,影響了整個路由器的傳輸性能。一種解決方法是利用長度信息SRAM,將每一個數(shù)據(jù)包的長度信息存儲其中,在獲取待讀出數(shù)據(jù)包的起始地址指針時,從該SRAM中讀出數(shù)據(jù)包的長度信息,將其同起始地址指針一起送往DDR3 控制器,從而實現(xiàn)數(shù)據(jù)包的連續(xù)讀出。但是,針對于星載路由器存儲資源十分珍貴這一特點,這種解決方式明顯并不適合。
本文在上述分析的基礎上,基于FPGA 硬件平臺,設計了一種基于DDR3 的星載路由器的隊列管理器。隊列管理器通過調(diào)用片外DDR3 作為數(shù)據(jù)存儲區(qū),增大了緩沖區(qū)容量,并設置共享存儲區(qū),可以有效應對突發(fā),提高了抗流量波動的能力。在本電路中,本文采取了一種可以連續(xù)對多個讀出請求進行操作的設計方案,保證了DDR3 的連續(xù)讀寫。同時,為了減少存儲地址指針時的資源消耗,本電路采用了基于大數(shù)據(jù)塊的存儲區(qū)分配方式,將存儲區(qū)分為了16 384 塊大小相同的存儲塊,使用塊指針加上塊內(nèi)信元指針的方式對數(shù)據(jù)包進行尋址,并設置了基于sram 的指針緩沖區(qū)[6]。本文將進一步詳細介紹其具體的設計與實現(xiàn)方式。
系統(tǒng)的硬件架構(gòu)包括前級的預處理電路、查找引擎,后級的輸出調(diào)度器和輸出合路電路等,如圖1 所示。
圖1 系統(tǒng)邏輯架構(gòu)
在圖1 中,輸入至該系統(tǒng)的數(shù)據(jù)流首先經(jīng)過合路電路和查找引擎進行預處理,而后送入隊列管理器。在預處理過程中,電路會對數(shù)據(jù)流進行分類,傳統(tǒng)的流分類策略主要是依據(jù)數(shù)據(jù)包報文頭中的五元組(源IP 地址、目的IP 地址、源MAC 地址、目的MAC 地址和協(xié)議種類),這種分類方式實現(xiàn)簡單、判定速度快,適于硬件實現(xiàn)。
經(jīng)過分類的數(shù)據(jù)流,會在數(shù)據(jù)包報文頭頭前面增加一個本地頭,其中包含了包長、輸入輸出端口號、所屬隊列號(FLOW_ID)等信息。
在網(wǎng)絡流量管理中,主要存在兩個關(guān)鍵機制:一個是對不同應用或協(xié)議對應的業(yè)務流進行區(qū)分的流量分類機制;另一個則是用于實現(xiàn)對數(shù)據(jù)包的緩沖管理、基于流的排隊管理、輸出調(diào)度和輸出速度控制的隊列管理機制。
本電路使用的隊列管理器邏輯模型如圖2 所示。
圖2 隊列管理器邏輯模型
其主體結(jié)構(gòu)為多個相互獨立的鏈表隊列,不同的隊列分別對應于特定的協(xié)議或應用,隊列之間使用在預處理電路中生成并放置于本地頭中的隊列好(FLOW_ID)進行區(qū)分。FLOW_ID 的數(shù)值范圍可以根據(jù)業(yè)務的實際需求進行動態(tài)調(diào)整,最大可同時對數(shù)千個隊列進行管理??紤]到星載路由器存儲資源十分珍貴的特點,本電路采用DDR3 作為隊列管理器的數(shù)據(jù)緩沖區(qū),從而在盡量降低片內(nèi)資源消耗的同時,保證了數(shù)據(jù)緩沖空間的大小,實現(xiàn)對大量隊列的精確管理。
針對于隊列管理器,具體的電路細節(jié)如圖3 所示,其中包括寫入預處理電路、自由指針管理電路、隊列控制電路、DDR3 控制器。
圖3 隊列管理器的電路結(jié)構(gòu)
其中,需要特別說明的是,針對自由指針管理電路,其主要負責維護系統(tǒng)當前所有可以使用的地址指針,同時執(zhí)行地址指針的分發(fā)和回收功能。
本電路中采用基于塊的存儲區(qū)分配,使用塊指針和塊內(nèi)指針聯(lián)合尋址的方式存儲數(shù)據(jù)包。數(shù)據(jù)存儲在DDR3 中,鏈表隊列中實際排隊的是使用的是數(shù)據(jù)包對應的塊指針,因此自由指針管理電路中僅需使用128 k 大小的sram 即可存儲全部的塊指針,大大降低了自由指針管理電路存儲地址指針時的存儲資源消耗。
本文所設計的隊列管理器具有以下幾個特點:
(1)對于每一隊列,都預先保留了一定大小的緩沖區(qū)。同時設立共享緩存區(qū),可供個別隊列在私有存儲區(qū)耗盡時申請使用,避免丟包;
(2)使用片外存儲器DDR3 作為數(shù)據(jù)緩存區(qū),極大的并提高了存儲容量。同時以塊為單位對DDR3 進行劃分并分配指針,使用塊所對應的指針以鏈表的形式構(gòu)建邏輯隊列,降低存儲地址指針時的存儲資源消耗,并降低了讀寫數(shù)據(jù)包時,打開不同bank、行時的額外時間消耗;
(3)在DDR3 控制器中,將讀數(shù)據(jù)和分析本地頭的工作分開進行,使得DDR3 控制器可以連續(xù)處理多個讀請求,實現(xiàn)了DDR3 的連續(xù)讀寫,進而提高了路由器的傳輸性能。
隊列管理器的設計往往要求具備一定的抗流量抖動能力。假設在某一時刻,某一個或某幾個隊列對應的數(shù)據(jù)流連續(xù)突發(fā),而隊列管理器又無法及時輸出時,則需要為這些隊列分配額外更多的存儲資源,這對緩沖空間的大小提出了更高的要求。同時,在隊列管理器中,數(shù)據(jù)實際存儲在緩沖區(qū)中,緩沖區(qū)的讀寫速度也就決定了隊列管理器的吞吐率上限。
由于DDR3 存儲容量大、讀寫速度快等優(yōu)點,本電路采用DDR3 作為片外存儲區(qū)。DDR3 為了提高讀寫的效率,采取了突發(fā)操作,在突發(fā)長度為8,位寬為64 bits 的情況下,一次突發(fā)操作可以寫入或者讀出64 字節(jié)的數(shù)據(jù)。在寫預處理電路中完成了將經(jīng)過的數(shù)據(jù)包包長填充為64 字節(jié)的整數(shù)倍,并將一個數(shù)據(jù)包劃分為了多個長度為64 字節(jié)的信元的操作,這樣,一次突發(fā)即可完成一個信元的寫入或者讀出操作。本電路采用的基于塊的存儲區(qū)分配,即將存儲區(qū)劃分為16 384 個大小相同的存儲塊,每個存儲塊對應一個塊指針,在塊內(nèi)使用塊內(nèi)指針進行尋址,當數(shù)據(jù)包輸入時,實際存儲在DDR3 中,然后將其對應的塊指針送入鏈表中建立虛擬輸出隊列。如圖4 所示。
圖4 基于塊的存儲區(qū)分配
在寫入預處理電路中設置了兩塊sram 存儲各隊列的詳細信息,包括首尾塊指針、首尾塊內(nèi)指針等。由于在存儲塊內(nèi),信元總是按順序存儲,因此每次寫入或讀出數(shù)據(jù)包時,只需要根據(jù)該隊列的隊列編號,從寄存器中獲取對應的首尾塊指針和塊內(nèi)指針,即可迅速定位到該隊列的首尾位置,進行讀寫操作。而每個數(shù)據(jù)包本地頭中都包含有該包長度,在每次讀寫操作完成后,可以很方便的對首尾指針進行更新。
同時,由于DDR3 的讀寫特性,每次讀寫時需要按照順序打開存儲數(shù)據(jù)的所在bank、行、列,消耗一定的時鐘周期,按照通常的存儲方式,即有可能出現(xiàn)同一個數(shù)據(jù)包存儲在不同行、不同bank 的情況,在讀寫時消耗額外大量的時鐘周期。通過劃分大塊存儲區(qū)的方式,基本可以保證同一個數(shù)據(jù)包的數(shù)據(jù)存儲在相同bank 的相同行內(nèi),避免了讀寫時在不同bank 和行之間切換,有利于提高DDR3的讀寫效率,進而提高系統(tǒng)的吞吐率。
系統(tǒng)上電之后,DDR3 控制器首先需要對DDR3進行初始化操作。初始化完成后,即可按照圖5 所示的工作流程開始數(shù)據(jù)包的輸入操作。
圖5 寫入工作流程
數(shù)據(jù)包經(jīng)過預處理電路后到達隊列管理器時,包頭前加裝了本地頭,其中包含了隊列編號、出端口位圖、包長等信息。寫入預處理電路根據(jù)數(shù)據(jù)流的隊列編號(Flow ID),從存儲隊列信息的sram中獲取該隊列的首指針地址、尾指針地址、隊列深度等詳細信息,如果當前隊列長度(已使用存儲區(qū))沒有超過私有存儲區(qū),則直接進行指針獲取、數(shù)據(jù)寫入、隊列信息更新的流程。若已經(jīng)超過私有存儲區(qū),則轉(zhuǎn)而向共享緩存區(qū)域申請存儲資源,申請成功后,才能繼續(xù)進行后續(xù)的操作。
讀出操作與寫入操作類似,如圖6 所示。
圖6 輸出工作流程
當有鏈表隊列中有完整數(shù)據(jù)包可以輸出時,調(diào)度器根據(jù)其隊列編號從隊列信息寄存器中獲取首尾指針等信息,并判斷,若當前存儲塊已經(jīng)讀空,則向鏈表隊列申請新的塊指針,歸還當前塊地址給自由指針電路,并更新鏈表信息,將新的塊指針和塊內(nèi)指針送入DDR3 控制器,若當前存儲塊尚未讀空,則將當前塊指針和塊內(nèi)指針送入DDR3 控制器。DDR3 控制器根據(jù)讀請求和地址指針,將數(shù)據(jù)包從DDR3 中讀出,最后更新隊列信息。
在DDR3 控制器根據(jù)讀請求從DDR3 中讀數(shù)據(jù)時存在一個問題,即跟隨讀請求一同送入的地址指針僅指示了等待讀取的數(shù)據(jù)包在DDR3 中的起始地址,并不攜帶數(shù)據(jù)包的長度信息,控制器也就無法確定要從DDR3 中讀取多少數(shù)據(jù)。因此,控制器在從DDR3 中讀出第一個信元后,需要暫停讀出操作,從首信元中分離出本地頭,進而獲取數(shù)據(jù)包的長度信息,然后再繼續(xù)執(zhí)行讀操作,將數(shù)據(jù)包的剩余信元完全讀出。在分離本地頭、獲取長度信息的這個過程中,DDR3 的讀操作處于停滯狀態(tài),降低了其讀寫效率,對于路由器的吞吐率造成了一定的影響。一種解決方案是利用sram 將各數(shù)據(jù)包的長度信息都存儲起來,當發(fā)出讀信號時,將數(shù)據(jù)包對應的長度信息同地址指針一同送入DDR3 控制器中,這樣雖然解決了DDR3 連續(xù)讀寫的問題,但當存儲的數(shù)據(jù)包較多時,存儲各數(shù)據(jù)包的長度信息需要消耗額外大量的存儲資源。
對于調(diào)用DDR3 作為片外存儲區(qū)的電路而言,DDR3 的帶寬決定了本電路吞吐率的上限,因此,保證DDR3 的連續(xù)讀寫是提高電路性能的關(guān)鍵。在數(shù)據(jù)包讀出時,DDR3 控制器依據(jù)從隊列中讀出的塊指針和塊內(nèi)指針對數(shù)據(jù)包進行讀出操作,由于隊列和隊列信息sram 中不包含數(shù)據(jù)包長度的實際情況,DDR3 控制器需要在讀出數(shù)據(jù)包首信元后暫停對DDR3 的讀請求,從首信元的本地頭中分析出數(shù)據(jù)包總長度,然后再繼續(xù)從DDR3 中讀出數(shù)據(jù)包的剩余信元,在分析首信元這一過程中,DDR3 讀操作一度處于停滯狀態(tài),大大降低了DDR3 的讀寫效率。本文提出并實現(xiàn)了一種將讀出信元和分析首信元的工作分開,可以連續(xù)處理多個讀信號的DDR3控制器設計方案,保證當有讀寫請求時,DDR3 可以連續(xù)讀寫,不存在停滯,同時避免了消耗額外的資源去存儲各數(shù)據(jù)包的長度信息。
經(jīng)過分析發(fā)現(xiàn),在對首信元進行分析獲取包長的這段時間內(nèi),DDR3 并不是無法進行讀操作,而是無法繼續(xù)進行當前數(shù)據(jù)包后續(xù)信元的讀操作。因此,我們可以考慮讓DDR3 控制器在對某數(shù)據(jù)包的首信元進行分析的過程中,暫時擱置對該數(shù)據(jù)包的讀操作,先對后續(xù)的讀請求進行應答,讀出相應的信元,等到有首信元分析完畢時,再來繼續(xù)讀出該數(shù)據(jù)包的剩余信元。DDR3 控制器其結(jié)構(gòu)圖如圖7所示。
圖7 DDR3 控制器結(jié)構(gòu)
本電路中將DDR3 控制器主要分為讀請求處理模塊和信元處理模塊兩部分。讀請求處理模塊負責根據(jù)調(diào)度器發(fā)來的讀請求和信元處理模塊發(fā)來的后續(xù)信元讀請求,從DDR3 中讀出數(shù)據(jù),信元處理模塊則負責對從DDR3 中讀出的信元進行判斷,若是首信元,則先存入首信元緩沖中,分析獲取包頭等信息,形成后續(xù)信元讀請求,送入讀請求處理模塊,若不是首信元,則送入輸出緩沖中等待輸出。具體的工作流程如圖8 所示。
圖8 DDR3 工作流程
讀請求處理處理模塊對調(diào)度器發(fā)出的讀請求和信元處理模塊發(fā)出的讀請求進行輪詢監(jiān)測。對于調(diào)度器發(fā)出的讀請求,讀請求處理模塊根據(jù)地址指針,從DDR3 中讀出數(shù)據(jù)包首信元,而后暫時擱置該數(shù)據(jù)包的讀操作,繼續(xù)處理其他讀請求;對于信元處理模塊發(fā)出的讀請求,讀請求處理模塊根據(jù)地址指針和包長信息,可以從DDR3 中讀出數(shù)據(jù)包的全部剩余信元,完成數(shù)據(jù)包的讀操作。
信元處理模塊則時刻對DDR3 緩沖進行監(jiān)測,當其中有數(shù)據(jù)時進行判斷,若是首信元,且不是單信元數(shù)據(jù)包,則開始進行分離本地頭、獲取包長信息、生成后續(xù)信元讀請求的操作;若是首信元且是單信元數(shù)據(jù)包,表示該數(shù)據(jù)包已經(jīng)輸出完畢,可以直接將其送入輸出緩沖中等待輸出;若不是首信元,表示讀請求處理模塊正在完成某數(shù)據(jù)包剩余信元的讀出工作,則將該數(shù)據(jù)包的首信元和后續(xù)信元一起送入輸出緩沖中,等待輸出。
本設計通過將處理讀信號和分析首信元的工作分入兩個模塊進行,使得控制器可以連續(xù)處理多個讀請求,避免DDR3 讀操作進入停滯狀態(tài),保障了DDR3 的讀寫效率,提高了電路的傳輸性能。
本設計中,隊列管理器的電路核心模塊采用Verilog HDL 編程實現(xiàn),開發(fā)環(huán)境采用的是Xilinx集成開發(fā)環(huán)境VIVADO 2018.3,使用仿真軟件Modelsim SE-64 2019.2對整個系統(tǒng)進行行為級仿真。
如圖9 所示,前級有數(shù)據(jù)包可以輸入時(i_frame_ptr_fifo_ft_empty),從指針中獲取該包所屬的流編號(wr_flowid),進而從存儲隊列信息的sram中獲取首尾地址指針等隊列信息(如圖中①)。當需要申請新的存儲塊時,向自由指針電路發(fā)送請求(ll_wr_req),并附帶流編號(ll_wr_flowid)(如圖中②),自由指針電路收到請求后,首先獲取該流當前隊列長度和門限值,若隊列長度小于門限值,表示為該流預留的存儲區(qū)還有剩余,將新申請的塊指針返回寫入電路(如圖中③)。收到塊指針后,將數(shù)據(jù)包送入輸出緩沖fifo(i_frame_data_fifo_ft_dout),準備送入DDR3 控制器中(o_cell_data_fifo_ft_din)(如圖中④)。寫入完成后,該隊列的長度、首尾指針等都有變化,對隊列信息進行更新(depth_flag_refresh),DDR3 控制器收到寫入請求后,將數(shù)據(jù)包寫入DDR3 中(如圖中⑤)。
圖9 數(shù)據(jù)包輸入仿真
如圖10 所示,當某隊列中有完整數(shù)據(jù)包時,向調(diào)度器發(fā)出一個可讀信號(q_rdy),若正好此時端口空閑(port_rdy),則向隊列管理器發(fā)出讀信號(q_status_rd_req),申請要讀出數(shù)據(jù)包的地址指針(如圖①)。調(diào)度器收到地址指針后(rd_addr),將其寫入面向DDR3 控制器的讀信號緩沖中(sdram_req_fifo_ft_din),等待從DDR3 中輸出(如圖②)。等到數(shù)據(jù)包輸出完畢后,DDR3 控制器將已經(jīng)剛讀出的數(shù)據(jù)包的相關(guān)信息送回調(diào)度器當中(sdram_rtn_fifo_ft_din)(如圖③),調(diào)度器從中獲取該包所屬的流編號(q_status_ref_flowid)、包長度(q__status_ref_len)后送到隊列管理器當中,隊列管理器根據(jù)收到的信息對隊列信息寄存器進行更新,若該數(shù)據(jù)包是數(shù)據(jù)塊中的最后一個包,則此時該數(shù)據(jù)塊為空,隊列控制器想自由指針控制電路發(fā)出請求歸還指針(rtn_ptr_req)(如圖④)。
如圖11 所示,讀信號處理電路當收到前級發(fā)來的讀請求(sdram_req_fifo_ft_empty)時,首先從中讀信息(sdram_req_fifo_ft_dout)中獲取數(shù)據(jù)包起始地址(read_start_addr)送往DDR3 中(app_addr),請求讀出數(shù)據(jù),隨后交由信元處理電路分析該數(shù)據(jù)包的首信元,暫時擱置該讀請求,繼續(xù)處理其他讀請求(如圖中①)。
當收到來自信元處理電路的讀請求時(sdram_secreq_fifo_empty),讀信號處理電路根據(jù)包長度,將數(shù)據(jù)包剩余信元全部讀出(如圖中②)。
圖10 數(shù)據(jù)包輸出仿真
圖11 DDR3 控制器工作仿真
DDR3 輸出的信元(app_rd_data)存儲在一個DDR3 輸出緩沖當中,等待進一步處理(w512_ddr_rd_data_fifo_ft_din)(如圖中③)。信元處理器檢測到緩沖區(qū)有信元時,首先檢測是否首信元(cell_first),若是,則將后續(xù)信元起始地址和包長作為新的讀信號,發(fā)送給讀信號處理電路(sdram_sec_req_fifo_din)(如圖中④)。等到數(shù)據(jù)包完全讀出后,將其存入輸出緩沖中,等待輸出(如圖中⑤)。
星載路由器對資源消耗、吞吐率等都有嚴格的要求,在資源消耗較低的前提下仍能保證一定的吞吐量。電路基于Xilinx Virtex-7 XC7V690T 設計實現(xiàn),圖12 所示為該設計的硬件資源消耗情況。從圖中可以看到,在調(diào)用外部DDR3 作為數(shù)據(jù)存儲區(qū)時,雖然訪問片外存儲區(qū)的時間會增加,但對應的片內(nèi)硬件資源消耗也較低,實際占用的BRAM 資源僅為18%。
圖13 為本設計的功耗評估報告,電路中大量采用了狀態(tài)機結(jié)構(gòu),其與流水線結(jié)構(gòu)相比,狀態(tài)機結(jié)構(gòu)能耗相對較低,可以看到整個隊列管理器動態(tài)功耗4.391 W,存儲部分的功耗只占了20%。
圖12 FPGA 內(nèi)部硬件資源消耗
圖13 功耗評估報告
本文提出了一種基于FPGA 硬件平臺的網(wǎng)絡流量管理系統(tǒng)架構(gòu),基于流建立隊列并進行資源預留,同時,為了減少片內(nèi)資源消耗,提供更大的數(shù)據(jù)緩存功能,本系統(tǒng)使用了片外DDR3 作為數(shù)據(jù)緩沖區(qū)。在此基礎上,針對其中的核心關(guān)鍵模塊,隊列管理器和DDR3 控制器,進行了設計與實現(xiàn)。
仿真結(jié)果表明,該電路能夠?qū)Σ煌臄?shù)據(jù)流實現(xiàn)有效管理,實現(xiàn)資源預留,正確地完成了數(shù)據(jù)流的寫入與讀取操作,能夠?qū)Σ煌臉I(yè)務提供絕對服務保證,減少了關(guān)鍵業(yè)務的時延。