摘要:PCffi總線已經成為高帶寬網卡與計算機通信的主流總線。而DMA控制器是實現(xiàn)PCIE總線高帶寬應用的關鍵因素。本文詳細闡述了基于PCIE接口的網卡中DMA引擎的接收和發(fā)送數(shù)據過程,介紹了描述符機制。本文提出了基于PCIE接口的網卡DMA的設計方案,并詳細說明了其中的實現(xiàn)難點和各子模塊的功能。本文還提出了影響DMA性能的主要因素和改進方向。
關鍵詞:網卡;DMA機制;PCIExpress
中圖分類號:TP334.7文獻標識碼:ADOI:10.3969/j.issn.1003-6970.2017.08.041
本文著錄格式:鄭凱.基于PCI+ExpressZO的高速網卡中DMA的設計[J].軟件,2017,38(8):204-209
引言
高性能高可靠性的網絡接口卡是大型數(shù)據中心服務器直連高速網絡的關鍵部件。PCI Express2.0提供的最高單位通道速率已可達5.0Gb/s。使用該總線的網卡能適應更高速度、更高帶寬網絡的需要。高速網卡通過直接內存訪問機制(即DMA機制)來進行主機和網絡直接的數(shù)據交互。在DMA機制中,數(shù)據傳輸無需CPU的介入,大大降低主機的工作負擔。在主流的以PCIE為總線接口的網卡中,如何利用DMA機制來充分利用PC正總線的高帶寬特性,實現(xiàn)網卡和主機間的高速數(shù)據傳輸是目前的一個研究熱點。
DMA控制器是隨著DMA機制在網卡中的應用而出現(xiàn)的,DMA控制器的主要功能是通過硬件數(shù)據通路完成主機和網卡之間的數(shù)據交互。設計一個高效合理的DMA控制器首先需要理解DMA機制下的工作原理和傳輸數(shù)據的關鍵機制。并且需要了解軟件驅動程序和硬件網卡高效傳輸數(shù)據的交互過程。能否實現(xiàn)軟硬件協(xié)同高效工作,也是DMA設計好壞的一個指標。為了更好的應用PCIE總線的特性,要充分了解PCIE總線協(xié)議和數(shù)據傳輸?shù)男问健1疚恼怯梢陨纤悸穪碚归_對論文的闡述。
1DMA的關鍵機制和工作流程在網卡采用的DMA方式下,網卡在發(fā)送和讀寫前必須知道其讀寫的內存地址,DMA控制器中接收和發(fā)送描述符的設計便是為DMA提供讀寫主存的地址和其他控制信息。
1.1 接收和發(fā)送描述符隊列
DMA控制器包含了兩個描述符隊列即接收和發(fā)送描述符隊列。描述符隊列的設計正是為了提高系統(tǒng)的性能和總線帶寬利用率。在主機的主存中也存在著同樣的兩個隊列的映射。
1.2 接收和發(fā)送描述符隊列
DMA控制器包含了兩個描述符隊列即接收和發(fā)送描述符隊列。描述符隊列的設計正是為了提高系統(tǒng)的性能和總線帶寬利用率。在主機的主存中也存在著同樣的兩個隊列的映射。
如圖1為主存中發(fā)送描述符隊列示意圖,隊列中每個描述符中的地址信息被配置為一個待發(fā)送數(shù)據緩存的基地址。其中Base為這個描述符隊列存放在主存中的基地址,Size為隊列長度,Head指針指向此隊列中配好的第一個可用描述符,Tail指針指向此隊列中CPU配好的最后一個可用描述符。
發(fā)送描述符的組成結構如圖2所示。其中,Datalength域為待發(fā)送數(shù)據的長度,由CRJ來配置;RdAddr域為主存中待發(fā)送數(shù)據緩存的基地址。Own位由CPU置為0,表明為此描述可被DMA控制器使用;被硬件置為1,表明此描述符已經被DMA控制器用掉,需要被CPU重新配置。
1.3 高速網卡中DMA數(shù)據發(fā)送流程
(1)CPU在主存中創(chuàng)建了一個發(fā)送描述符隊列,并且把該隊列在主存中的起始位置,隊列長度和頭尾指針(初值都為0)寫到網卡中的相關寄存器中去。
(2)CPU被協(xié)議棧請求發(fā)包,它把包存放在一個緩存區(qū)或多個緩存區(qū)中。
(3)CPU初始化描述符隊列中的描述符,將其指向待發(fā)送的數(shù)據緩存區(qū)。
(4)主機準備好了可用的描述符,并及時更新網卡中的隊列尾指針寄存器。
(5)網卡中的DMA通過查看頭尾指針寄存器的值,知道主存中有可用描述符,進而通過PCIE接口發(fā)起一次為獲取描述符的存儲器讀請求。
(6)描述符以PCffi讀完成報文的形式被網卡接收并且存放到網卡中的專門位置。
(7)DMA讀出描述符中存放的讀主存地址和長度等信息,通過PCIE總線發(fā)起一次為獲取主存中待發(fā)送數(shù)據的存儲器讀請求。如果讀取長度大于PCIE總線的最大讀請求長度,還會分割為幾次讀請求發(fā)出。
(8)主存中的數(shù)據包被以PCIE完成報文的形式傳送到網卡中。
(9)當整個數(shù)據包存放到本地網卡后,DMA會通過PCIE總線向主存發(fā)起一次存儲器寫請求,來回寫主存中被網卡剛用過的描述符。
(10)DMA會發(fā)起一次中斷,通知主機驅動,數(shù)據包已經被讀到網卡中,驅動可以釋放剛才的數(shù)據緩存。
1.3 高速網卡中DMA數(shù)據接收流程
(1)CPU在主存中創(chuàng)建了一個接收描述符隊列,并且把該隊列在主存中的起始位置,隊列長度和頭尾指針(初值都為0)寫到網卡中的相關寄存器中去。
(2)主機將隊列中的描述符指針指向空的緩存,并且更新了網卡中尾指針寄存器的值。
(3)接收DMA通過查看尾指針寄存器,獲知主存中有可用接收描述符,通過PCIE總線發(fā)出存儲器讀請求來獲取主存中的接收描述符。
(4)接收描述符通過PC正總線以讀完成報文形式返回并被存放在網卡中的適當位置。
(5)網絡的數(shù)據包進入接收MAC,并通過過濾模塊后進入接收FIFO中。
(6)當網卡接收到一個完整包時,會發(fā)起數(shù)據傳輸請求。DMA讀取描述符中的寫主存地址并且根據數(shù)據包長度來進行切割請求,發(fā)起若干個存儲器與請求。
(7)等一個完整的數(shù)據包都寫到主存,DMA可以回寫本地描述符中的數(shù)據包長度,并將own位置為1,表示此描述符已經用完。
(8)DMA通過PCIE接口,將回寫后的本地描述符組裝成存儲器寫請求,來回寫剛用掉的對應主存中的描述符。
(9)網卡產生一個中斷通知主機一個新的數(shù)據包已經被接收到主存,等待處理。
(10)主機讀取這個數(shù)據包并把它送到TCP/IP協(xié)議棧進行進一步處理。
(11)主機釋放掉相關的緩存,并通過查看主存中描述符的狀態(tài)位確定哪些描述符已經被用,并重新分配描述符。
2 基于PCIE接口的DMA設計
PCIExpress總線采用了一種類似網絡報文的形式來進行傳輸。在PCIExpress協(xié)議中,隱藏了地址線、數(shù)據線,以及中斷信號等邊緣信號。所有信息以傳輸層報文TLP(Transaction Layer Packet)進行傳輸。TLP與TCP/IP很相似,在報文中同樣也具有報文頭和載荷:報文頭是由代表不同傳輸信息的字段組成,如報文長度、報文傳輸?shù)刂返?;而載荷則由傳輸?shù)臄?shù)據構成。
PCIE的DMA讀/寫操作實現(xiàn)的主要方法是將TLP包頭中的各個字段正確填充,并將數(shù)據按照64bit或者32bit并行放在TLP包頭后,按照64bit或者32bit并行傳輸給PCffi核,由PCE核以PCIE協(xié)議串行傳輸給主機。
2.1 系統(tǒng)設計架構和模塊劃分
結合高速網卡高效的數(shù)據收發(fā)流程,以及對PCIE總線協(xié)議的了解,本文提出了DMA控制器的設計方案。如圖3為基于PCIE總線的高速網卡中,DMA控制器的設計架構圖。其中PCIE接口采用了賽林思的PCIE核。
在DMA接收方向上大概的數(shù)據路徑依次是:網絡中的數(shù)據包通過RxMAC模塊進入網卡,被包過濾模塊過濾后,存放到接收緩存控制模塊的DataFIFO中,通過接收引擎送入PCIE接口,并最終寫入主存中去。
在DMA發(fā)送方向上大概的數(shù)據路徑依次是:主存中的數(shù)據通過PCIE接口傳入網卡,在發(fā)送引擎中被解析后送到發(fā)送緩存控制模塊,并通過數(shù)據成幀模塊形成網絡報文,最終通過TXMAC模塊送到網絡中去。
在數(shù)據接收和傳送過程中,都要用到描述符,它們被存放在各自的FIFO中。
DMA的主要模塊包括接收引擎和發(fā)送引擎,以及描述符和寄存器讀寫模塊。
2.2 接收引擎功能詳述
接收引擎需要向PCIE核發(fā)送存儲器寫/讀請求和完成包,本設計支持以上三種包類型的產生。其中存儲器寫請求是用來向主存寫入網卡接收到的網絡報文。
存儲器讀請求主要上有兩種用途:一是用來讀取主存中待發(fā)送的數(shù)據;二是用來讀取主存中準備好的描述符,包括接收和發(fā)送描述符。
完成報文主要是為了回應主機對網卡中某些寄存器的讀操作。
為了產生這三種報文,接收引擎內部設計了專門的產生三種報文的模塊:即存儲器寫請求(MWr)組包模塊,存儲器讀請求(MRd)組包模塊,完成報文(Comp)組包模塊。
2.2.1 存儲器寫請求(MWr)切片和組包模塊
PCIE總線協(xié)議規(guī)定最大存儲器寫請求的數(shù)據載荷長度是4K字節(jié)。但是在大部分實際系統(tǒng)中,最大存儲器寫請求長度為128字節(jié)或者256字節(jié)。因此傳送長度較長的網絡報文需要分割為幾次存儲器寫請求。
存儲器寫請求(MWr)切片模塊就是根據接收到的報文長度進行切割。當已經接收到一個完整的報文,并且接收描述FIFO不空時,切片模塊讀入描述符FIFO中的寫主存地址,并讀取CtrlFIFO中的報文長度,隨后進行寫請求的分割。分割的原則是一次讀請求不能跨越主存地址的4k邊界,并且一次請求的長度不超過最大請求長度。
存儲器寫請求切片模塊將每次切割的寫請求長度和寫主存地址送入存儲器寫請求包頭組裝模塊,進行包頭的組裝。組裝后的存儲器寫請求包頭會被存放到存儲器寫請求包頭FIFO中去。
2.2.2 存儲器讀請求(MRd)切片和組包模塊
存儲器讀請求切片模塊和存儲器寫請求切片模塊大體相似,但是它需要完成更多的任務。上文中提到存儲器讀請求要完成對主存中描述符的讀取。這需要通過查看網卡中的發(fā)送/接收描述符尾指針寄存器。
當網卡中的尾指針寄存器有變化時,網卡需要計算兩次變化的差值并結合發(fā)送/接收描述符隊列基地址等信息,組成一次存儲器讀請求。如果這次讀取的描述符的數(shù)目很多,使讀取長度大于最大讀請求長度,就會分割為多次存儲器讀請求。每次切割后,將相關信息送入存儲器讀請求組包模塊中,生成多個存儲器讀請求并被存放到讀取發(fā)送/接收描述符請求FIFO中去。
同樣,為了完成對主存中待發(fā)送數(shù)據的讀取,還需要查看發(fā)送描述符FIFO。如果發(fā)送描述FIFO不空,就會將描述符FIFO中的讀主存地址和數(shù)據長度讀入存儲器讀請求切片模塊進行切割。
如果CPU剛剛更新了網卡中發(fā)送描述符的尾指針寄存器,并且這時發(fā)送描述符FIFO也不空,就需要對兩種切割任務的仲裁。當發(fā)送描述符FIFO中的描述符數(shù)目不小于一個最少值時,我們優(yōu)先發(fā)起獲取主存待發(fā)送數(shù)據的讀請求。當發(fā)送描述符FIFO中的描述符小于一個最小值時,我們要首先發(fā)起獲取新的發(fā)送描述符的讀請求丁作。
在存儲器讀請求組包模塊中,我們通過存儲器讀請求中的標簽號(Tag號)來區(qū)分三種不同的讀請求,以便在接收它們對應的完成報文時能分類存放和管理。因此Tag號的管理是一個非常重要的問題。
2.2.3 完成報文(Comp)組包模塊
如果主機想了解網卡中寄存器的相關信息,會發(fā)出存儲器讀請求,這時網卡就要回復一個完成報文。其中完成報文的切片操作是由發(fā)送引擎中解析到存儲器讀請求來觸發(fā)的。其中,完成報文包頭中的完成標號(completeId)等信息需要從PCIE核的配置接口來獲知。
2.2.4 仲裁模塊
當各種請求的包頭FIFO都不空時,我們需要進行對事務層報文(TLP)的接收進行仲裁。在本設計中,我們采用加權輪詢分時的方法對三種TLP報文請求進行調度。加權輪詢(Weighted Round Robin)是為了解決不同任務間的調度平衡問題,而通過為各個任務設置不同權重值,以權重值來組織各個任務的執(zhí)行時間,從而達到調度的合理性。
當傳輸開始時,在傳輸模塊中分別有兩個計數(shù)器負責對讀寫請求計數(shù),當請求次數(shù)達到權重值,則將該請求計數(shù)器清零,跳入另一請求周期,如此反復直到傳輸完畢。采用這種分時方式的好處是,用戶可根據傳輸?shù)妮敵鐾掏碌奶攸c對傳輸進行配置。
2.2.5 接收狀態(tài)機
這個狀態(tài)機負責通過接收傳輸接口把TLP報文送給PCIE核。當要發(fā)起傳輸時,它要從存放各種TLP報文包頭FIFO中讀出包頭信息先存到寄存器中,然后在狀態(tài)機的控制下發(fā)送出去。
這個狀態(tài)機模塊負責產生一次完整的DMA傳輸結束信號,回寫描述符FIFO中相應的信息,并將回寫后的本地描述符組裝成存儲器寫請求送人到PCIE核。
中斷邏輯也是在這個模塊產生的。接收狀態(tài)機負責產生中斷通知CPU刷新已使用的主存中相應描述符。
這個狀態(tài)機主要部分是傳輸狀態(tài)的產生邏輯和每種傳輸狀態(tài)下要分類傳送數(shù)據的邏輯。當包頭組裝模塊中某種存儲包頭的fifo不空時,狀態(tài)機狀態(tài)開始調轉,進入傳送某種TLP包的狀態(tài)。
2.3 發(fā)送引擎功能詳述
2.3.1 發(fā)送狀態(tài)機
發(fā)送狀態(tài)機用來解析主機發(fā)送到網卡的TLP報文類型,把收到的不同類型的數(shù)據送到各自對應的FIFO緩存。當有存儲器讀請求時,要向接收引擎?zhèn)魉桶l(fā)起完成包的請求。
2.3.2 發(fā)送檢測模塊
發(fā)送檢測模塊的功能主要有:
(1)檢測一次讀請求發(fā)起的完成包的結束,以釋放Tag資源。
(2)檢測完整的一次DMA讀請求是否完成。
(3)檢測收到的完成包是否正確。
(4)產生中斷,通知CPU刷新已使用的主存中相應描述符,并通知接收引擎發(fā)起回寫主存描述符的存儲器寫請求。
2.3.3 數(shù)據緩存狀態(tài)機
PCIE協(xié)議規(guī)定一次讀請求的完成包是按序收來的,但是后一次的讀請求對應的完成可能比一次讀請求對應的完成來的早。因此接收到的完成包的順序不一定是對應發(fā)出的讀請求的順序,所以當存到SRAM里時要有一個存放排序的問題,根據完成包的tag標簽來分配存放地址。
數(shù)據緩存狀態(tài)機就是要計算每個完成包要存放的起始地址和存放順序。
2.4接收和發(fā)送描述符FIFO和寄存器模塊從主存中獲取的發(fā)送和接收描述符被分別存放在網卡中的發(fā)送和接收描述符FIFO。描述符的獲取和正確存放是實現(xiàn)DMA高效工作的必要條件。CPU通過PCIE總線將一些DMA相關寄存器信息寫到本地網卡中的DMA寄存器模塊。
3 實現(xiàn)難點和性能改進方向
3.1 DMA讀寫對界問題
PCIE接口的TLP報文的數(shù)據載荷長度是以雙字為單位因此需要要求PCIE存儲器讀寫請求的地址都以雙字對齊。而網絡報文的長度不一定能被雙字整除,因此在報文的包頭填寫時需要做細致的處理,以實現(xiàn)數(shù)據對界的要求。
為此我們采用了向前X字節(jié)對界和向后X字節(jié)對界的方法操作來處理對界問題。
3.2 對存儲器讀完成TLP的亂序處理
在PQE總線中,一個存儲器讀請求可以對應幾個完成報文。設備發(fā)出的存儲器讀請求可以超越之前發(fā)出的存儲器讀請求。而且當存儲器完成報文使用的Transaction ID不同時,存儲器讀完成TLP也可能超越之前的存儲器讀完成TLP,這將造成存儲器讀完成TLP亂序到達網卡。
但是我們要充分利用存儲器讀請求和其對應的完成報文的Tag號相同的特點,以及同一個存儲器讀請求對應的完成報文是按地址順序依次到達的。
為了實現(xiàn)對亂序存儲器讀完成報文的接收,我們在DMA中采用了一塊SRAM對完成報文進行存儲。并且用一個小的RAM來對完成報文的存放順序做管理。我們以Tag號對這塊RAM進行編址,每個Tag號對應的entry中填入這個讀請求對應完成報文存到SRAM的起始存放地址。這個起始地址是以每個Tag號對應的發(fā)送讀請求的先后順序來安排的。
當這個讀請求對應的一個完成報文到達后,要及時根據這個完成報文的長度,對這個RAM對應的entry進行更新,遞增其目的存放地址,以便接收此存儲器讀請求對應的下一個完成報文。當確認這個存儲器讀請求對應的完成報文都已接收完成后,這個存儲器讀請求的Tag號對應的Entry會被標記。并且這個Tag號會被其他存儲器讀請求再次使用,否則其它存儲器讀請求不能使用這個Tag號。
當SRAM中的一個數(shù)據報文發(fā)送到網絡中后,已發(fā)送報文的存儲起始地址和報文長度會送到報文管理模塊,以便讓下一次存儲器讀請求返回的完成報文來使用。
3.2 DMA性能改進的方向
本文中的DMA是每當往主存寫好一個完整包后,就會向主機發(fā)出一次中斷。當網絡上的小報文集中大量涌入網卡時,會使網卡產生的接收中斷過于頻繁,導致CPU在沒有完成一次接收中斷處理的時候又有需要處理的接收中斷,CPU就會疲于處理接收中斷而沒有時間對接收數(shù)據做進一步處理。
這需要我們可以不再以接收一個包來發(fā)出中斷。而是等一定量的數(shù)據塊(例如1K字節(jié)的包)寫到主存后,再發(fā)出中斷。但是這會大大增加DMA控制器硬件的復雜度。因為需要很多邏輯去解析這次接收的定量數(shù)據塊中含有數(shù)據報文的數(shù)目。因為CPU是以一個數(shù)據報文為單位來進行處理。
另外描述符的設計上,多隊列描述符會比單隊列描述更能提高DMA控制器的性能。目前,市場上大多數(shù)采取描述符機制的網卡使用的是傳統(tǒng)的單隊列接收描述符。雖然服務器[11-12]的內存可以配置到1GB以上,但對于越來越復雜的應用程序來說服務器內存仍然是緊缺資源。所以在描述符機制中分配給接收描述符的接收數(shù)據的緩沖區(qū)空間總量不會太大,而為了提高高速網卡的性能,接收描述符的數(shù)量當然是越多越好。這就需要在固定容量的緩沖區(qū)空間條件下開發(fā)更多個數(shù)的接收描述符。多對列描述符機制在同樣緩沖空間大小下能夠獲得更多的接收描述符,從而提高了網卡的性能。