丁 帥,喬廬峰,陳慶華,劉 熹,鄒仕祥
(中國人民解放軍陸軍工程大學,江蘇 南京 210001)
計算機系統中,傳輸控制協議(Transmission Control Protocol,TCP)通常集成在操作系統中,以軟件方式實現。研究表明,這種軟件實現的方式在協議處理、數據拷貝和中斷處理中給系統帶來了龐大的開銷[1]。隨著網絡帶寬不斷增大,對服務器能力的要求不斷增加,協議處理已經成為服務器的主要負荷之一。為了提高服務器的處理能力,目前通常采用增大單一服務器CPU 數量和多服務器并行處理等方式。為了進一步提高服務器同時服務的用戶數量、提高處理的數據吞吐率,采用專用的TCP協議處理電路,以全硬件方式實現TCP 協議處理的功能成為研究的熱點,由此推動了TCP 協議卸載引擎(TCP Offload Engine,TOE)技術的發展。
TOE 技術的基本思想是采用專用硬件,如TOE網卡,實現原來由CPU 承擔的TCP 協議處理功能[2]。如圖1 所示,傳統網卡主要實現網絡的物理層和數據鏈路層處理功能,網絡層和TCP 層功能由軟件實現。TOE 網卡除實現傳統網卡的處理功能外,還需要實現TCP 層和網絡層協議處理功能。CPU 重點完成應用層及以上處理功能,從而可以大大降低CPU 負荷。TOE 可以采用專用集成電路(Application Specific Integrated Circuit,ASIC)、嵌入式處理器和現場可編程門陣列(Field Programmable Gate Array,FPGA)實現。利用ASIC 實現時,TOE 處理能力強,但靈活性較差;采用嵌入式處理器實現時,處理靈活,可拓展性強,但是其本質上還是以軟件方式實現協議處理,性能提升有限;采用FPGA 實現時,可以在保證處理能力的前提下,保持足夠的靈活性,且開發周期短,實現風險小[3]。本文采用的是基于FPGA 的實現方案。

圖1 傳統網卡與TOE 網卡
本文設計的TCP 協議處理電路總體結構如圖2所示,由TCP 發送控制電路、封裝電路、校驗和生成電路、窗口管理電路、定時器管理電路、哈希查找電路、TCP 接收控制電路、包重排序電路、發送和接收緩存組成。

圖2 TCP 協議處理電路總體結構
TCP 發送控制電路包含TCP 發送電路和重傳電路。TCP 發送電路負責根據上層應用提供的套接字(Socket)與目的主機實現建立連接、數據傳輸和釋放連接的控制功能,產生TCP 頭部信息并交給下級電路。TCP 封裝電路根據TCP 發送電路在數據傳輸階段提供的TCP 頭和用戶數據,組建完整的TCP報文段,并通過校驗和生成電路計算位于TCP 頭部的校驗和字段,從而生成完整的TCP 報文段并通過發送緩存交給IP 層處理電路。重傳電路利用定時器超時控制報文段重傳,同時可根據返回的確認信息進行發送窗口管理,實現TCP 流量控制的功能。TCP 接收控制電路負責接收TCP 報文段,根據報文段類別,產生攜帶確認序號和接收窗口確認分組,發送給對端。接收分組排序電路可以對非按序到達的報文段進行本地緩沖,確保向上層按序交付數據。TCP 接收控制電路還可以利用哈希查找電路進行業務流區分,從而以時分復用方式同時支持多個連接。
TCP 協議有復雜的狀態變遷流程,圖3 是在正常情況下,服務器和客戶機狀態的變遷,不包含同時打開、關閉連接的服務[4]。TCP 協議處理電路需要采用全硬件方式實現TCP 協議處理功能。

圖3 TCP 狀態變遷
TCP 協議處理電路中的緩沖區分布和實現控制功能的狀態機分布如圖4 所示。發送狀態機通過與前級電路的發送隊列接口,讀取待發送TCP 分段凈荷,并讀取與TCP 頭部生成有關的控制信息,然后按照給定目的IP 地址和目的端口號完成與對端服務器建立連接、發送數據和釋放連接的操作并接收對端確認(Acknowledgment,ACK)。定時器管理電路對發送分段進行定時,當一個分段出現超時后,它會觸發該分段的重傳操作。重傳電路包含兩個狀態機,一個用于接收對端ACK,根據窗口大小字段,調節發送窗口大小實現流量和擁塞控制功能,并能給發送狀態機提供必要的狀態字段;另一個狀態機用于數據段的超時重傳。在發送數據時,發送狀態機首先判斷與應用層的接口數據隊列和與重傳電路的接口隊列中是否有待發送數據指針,其次優先發送待重傳數據。接收控制電路從與前級電路的接口隊列中讀取數據包,提取TCP 頭部信息,按照給定源IP 地址和源端口號完成與客戶機建立連接、接收數據和釋放連接的操作。在數據包的接收過程中,通過應答發送狀態機向對端發送相應的ACK 應答。包重排序狀態機根據序號對數據包進行排序,再按序交付給應用層。當同時支持多個TCP 流時,哈希查找電路用于識別不同的TCP 連接,在時分復用狀態下讀取不同TCP 流的狀態信息,對不同的流進行管理。

圖4 TCP 協議處理電路中的緩沖區和狀態機
面向多業務流的連接管理需要采用哈希查找電路進行業務流識別,該電路位于接收控制電路端,用于識別上千條TCP 連接,并對各個連接的參數進行維護管理。哈希查找電路的工作原理是利用哈希函數建立關鍵字到哈希表地址空間的映射,即將關鍵字進行哈希散列運算,得到哈希值(Hash)。這種映射是一種壓縮映射,不同的關鍵字可能會產生相同的Hash,從而導致哈希沖突。為了減少哈希沖突,可以使用多桶哈希的技術,本方案采用雙桶哈希表結構。
雙桶哈希技術通過增大哈希表的位寬,使得一個Hash 對應的存儲空間中可以同時存儲2 個關鍵字及其對應的結果信息來減少哈希沖突。本設計中哈希查找電路的關鍵字是當前連接的源IP 地址、目的IP 地址、源端口號和目的端口號,標識為一個Socket。輸出的結果信息是每個業務流對應唯一的連接號(Connection_id)。
哈希查找電路實現的功能有業務流添加操作,業務流識別操作和業務流刪除操作。
業務流添加操作是在Hash 對應的存儲中寫入當前Socket、Connection_id 表項。發送電路完成建立連接的操作后,哈希查找電路會進行業務流添加操作,利用哈希函數計算Socket 得到Hash,以Hash 為地址將Socket 和對應的Connection_id 寫入,完成業務流添加操作。
在連接上到達報文段時,為了簡單標識連接進行數據傳輸,哈希查找電路根據Socket 得到Hash讀取兩個哈希桶中對應的表項,表項匹配成功,得到Connection_id 進行連接參數維護。
在發送電路完成釋放連接的操作后,查找電路會進行業務流刪除操作,它將根據Socket 得到Hash 讀取兩個哈希桶中對應的表項,將該表項(包括有效指示位)全部清零,完成業務流刪除操作。
TCP 發送電路的工作流程如圖5 所示。發送狀態機的初始狀態為CLOSED 狀態,在此狀態下,所有寄存器的值都為初始設定值,發送狀態機會不停地檢測上層應用是否有執行建立連接的操作,若上層應用要建立連接,則發送狀態機會發送一個同步序號編號(Synchronize Sequence Numbers,SYN)置1 的連接數據幀到對端,建立連接定時器就會被啟動,發送狀態機會隨即跳轉至SYN_SENT 狀態。在SYN_SENT 狀態下,發送狀態機會等待對端ACK 的到來。若在建立連接定時器超時前收到對端的確認,則發送狀態機跳轉到ESTABLISH 狀態,否則重發SYN。若在3 次發送SYN 都沒有收到對端ACK,則建立連接失敗[5]。

圖5 TCP 發送電路工作流程
若上層應用有數據待發送,則發送狀態機開始進行數據加載操作,數據加載完成后,發送狀態機跳轉至發送數據狀態。在發送數據狀態下,封裝好的報文段被發送出去,同時啟動超時定時器,之后進入超時檢查狀態。在檢查超時時間時,發送方會等待對端ACK 的到來,若收到了對端的應答,且沒有超時,則按照應答包接收窗口大小字段進入下一批數據發送操作;否則應進行數據重傳,收到重傳數據的確認后,繼續進行下一批數據的傳輸操作。
完成數據的傳輸后,發送狀態機可根據上級電路的要求發送一個結束幀(FIN 位置1)到對端,同時啟動超時定時器,跳轉至FIN_WAIT_1 狀態。若在超時定時器超時前收到對端的確認,會進入FIN_WAIT_2 狀態,同時啟動fin_wait 定時器,否則會向對端重發FIN。若在fin_wait 定時器超時前,發送狀態機收到對端FIN,得知對端請求關閉數據傳輸連接,便會發送一個應答包,隨后跳轉到TIME_WAIT狀態。兩倍的最大段生存時間(Maximum Segment Lifetime,MSL)后回到CLOSED 狀態,否則直接關閉連接。
如圖6 所示為重傳電路存儲結構,重傳電路的存儲管理方式為自由指針隊列(Free Pointer Queue,FQ)、待發送指針隊列(Pending Pointer Queue,PQ)、數據存儲區SRAM 和重傳接口隊列的組合。上層應用有數據塊要發送時,發送控制電路在將數據寫入發送隊列的同時也將數據寫入緩沖區隊列。重傳電路開始工作時,首先將FQ 初始化,若檢測到緩沖區隊列中有指針,寫入狀態機先從自由指針隊列中讀取一個自由指針;其次根據這個指針將數據塊寫入數據存儲區中,其中自由指針作為數據存儲區的基地址;最后以自由指針值為地址,將自由指針值、數據長度、起始字節編號(本地頭)和時間戳等信息寫入PQ 中。

圖6 重傳電路存儲結構
接收狀態機在檢測ACK 接收隊列指針是否非空的同時,在間隙中掃描PQ 中的時間戳。接收狀態機如果收到對端ACK,則對ACK 包進行解析,依次讀取PQ 隊列并與PQ 中各表項的本地頭比較,確定是哪一個數據包的ACK 并記錄下接收窗口大小字段,然后從PQ 隊列中讀出自由指針。以該指針為基地址將數據塊從存儲區內釋放,將自由指針歸還給自由指針隊列,同時在PQ 中將此表項的有效位置0,表示該表項對應的報文段被對端成功接收。如果發生超時,重傳狀態機邊開始工作,將PQ 中自由指針值讀出,以該指針為基地址將存儲區內數據寫入重傳接口隊列中,同時將時間戳值更新。這樣便完成了ACK的接收與數據包的重傳功能。由于一個TCP 的最大報文段是1.5 KB,所以對數據包進行存儲時可以將一個32 KB RAM 的緩存區分塊,每塊2 KB,這樣一塊RAM 可以分為16 個數據塊,每個數據塊對應一個指針,這樣對應一個深度為16 的自由指針隊列0~15。在初始化時,將0~15 寫入FQ 中。假設RAM 的位寬為32 位,這樣512 個32 位的存儲單元可以存儲一個2 KB 完整的數據塊。RAM 的地址除自由指針值外,還應該加上低9 位的計數值,加在一起才是真正使用的RAM地址。
本文以Xilinx ZYNQ-7020 開發板為硬件平臺搭建TCP 處理電路,其關鍵電路的仿真波形如圖7、圖8 和圖9 所示。圖7 展示的是多連接查找電路的仿真結果,圖中標“1”處是4 個連接的添加操作,由于電路采用雙桶Hash 技術,所以對于前3 個相同Hash 的Socket 連接添加時,第3 個連接添加失敗。標“2”處是連接查找操作,根據Socket 得到Hash 利用哈希查找電路進行查找,第3 個連接查找失敗,其余3 個均查找成功。標“3”處是第4 個連接的刪除操作,根據Socket 得到Hash 利用哈希電路進行表項刪除,第4 個連接刪除成功;標“4”處是連接查找操作,由于經過第3 步的連接刪除操作,第3 和第4 個連接均查找失敗。圖8 和圖9 展示了建立連接和釋放連接仿真結果,圖中標“1”處是第1 次建立連接操作,由于發送3 個SYN,均沒有收到對端的同步應答幀,所以建立連接失敗。標“2”處是第2 次建立連接操作,在發送第3 個SYN 的超時時間內收到對端的同步應答幀,建立連接成功。標“3”處是拆除連接過程中發送FIN 的操作,在第2 次FIN 的超時時間內收到對端ACK,且在一定時間內收到對端FIN,所以發送完ACK,再等待2MSL 時間后釋放連接。標“4”處是拆除連接過程中接收對端FIN 超時的情況,在第2 次FIN的超時時間內收到對端ACK,但在一定時間內沒有收到對端FIN,所以直接釋放連接。

圖7 連接查找電路仿真結果

圖8 TCP 建立連接仿真結果

圖9 TCP 釋放連接仿真結果
本文給出了多端口TCP 協議處理電路設計方案,由TCP 發送控制電路、哈希查找電路、重傳電路、定時器管理電路組成。TCP 協議處理關鍵電路在Xilinx ZYNQ-7020 開發板上進行了設計與仿真分析,結果表明,TCP 處理電路可以以全硬件方式實現連接建立、數據傳輸、連接釋放和連接存儲管理,符合TCP 協議規范要求。