跳至內容

聊一聊Linux網絡性能王者——XDP技術

更新時間
快连VPN:速度和安全性最佳的VPN服务
快连VPN:速度和安全性最佳的VPN服务

大家好,今天我們通過幾張圖來聊一聊XDP技術。

許多Linux開發人員可能對XDP技術感到陌生,尤其是那些從事網絡相關開發工作的人。如果你是一名Linux開發人員且對XDP技術不瞭解,那可能會錯失許多機會。

我曾應用XDP技術對一個項目進行優化,成功提升了其網絡處理性能3-4倍。也許有人會認爲該項目原本性能較差,纔有如此顯著的提升空間。

我認爲,在當前的軟件架構下,即使進行進一步優化,性能瓶頸也不容易消除。必須採取更高效的架構,以更全面的視角來解決這個問題。

後續我的項目魔法盒子也會用上XDP技術,採用XDP技術後,魔法盒子的網絡性能估計能夠提高3倍左右。

1.XDP技術簡介

1.1 XDP技術背景

隨着超高帶寬網絡技術10G,40G,100G網絡的出現,Linux內核協議棧越來越不能適應新的網絡技術的發展,Linux內核協議棧似乎成爲了網絡性能的瓶頸和雞肋,爲了解決這個尷尬的處境,Linux內核引入了一個新的技術內核旁路(Kernel Bypass)技術,內核旁路技術的核心思想是網絡數據包跳過內核協議棧,直接由用戶程序處理,這樣可以避免內核協議棧的開銷,大大提高網絡性能。

XDP是Linux特有的內核旁路技術,與之相對應的是DPDK技術。DPDK在性能方面表現出色,然而並不完全適用於Linux系統。

1.2 XDP是什麼?

XDP是一種Linux內核技術,通過使用eBPF機制,在內核空間中實現高性能的數據包處理和轉發。

XDP可以顯著提升網絡性能,並提供靈活的編程接口,讓用戶能夠實現各種自定義的網絡功能。相較於傳統的用戶空間數據包處理,XDP能夠有效降低數據包處理的延遲和CPU佔用。

XDP技術工作模式:

 原生模式(性能高,需要網卡支持)驅動模式,將XDP程序運行在網卡驅動中,從網卡驅動中將網絡數據包重定向,該模式支持的網卡較多且性能也很高,如果網卡支持的話,儘量使用該模式。

卸載模式(性能最高,支持的網卡最少)將XDP程序直接卸載到網卡,該模式支持的網卡少,暫不做討論。

通用模式(性能良好,Linux內核支持最好)XDP程序運行在Linux內核協議棧入口,無需驅動支持,性能低於XDP其他的兩種模式,但是即使XDP通用模式,也會給你的系統性能帶來一定的提升。

後續會有專門的專題來講XDP技術,這裏不展開討論。

2.AF_XDP工作原理

2.1 整體架構

很多同學容易將XDP和AF_XDP技術給弄混淆。

  • XDP技術是基於BPF技術的一種新的網絡技術。
  • AF_XDP是XDP技術的一種應用場景,AF_XDP是一種高性能Linux socket。

AF_XDP需要通過socket函數創建。

socket(AF_XDP, SOCK_RAW, 0);
登錄後複製

AF_XDP技術會涉及到一些比較重要的知識點:

圖片

  • AF_XDP想要XDP程序配合,才能完成網絡數據包收發。
  • XDP程序主要工作是根據以太網幀的相關信息如:MAC地址,五元組信息等,進行數據包的過濾和重定向。
  • AF_XDP處理的是以太網數據幀,所以用戶程序發送和接收的是以太網數據幀。
  • 用戶程序,AF_XDP,XDP會操作一個共享的內存區域,稱之爲UMEM。
  • 網絡數據包的接收和發送需要用到4個無鎖環形隊列。

2.2 UMEM共享內存

UMEM共享內存通過setsockopt函數進行申請。

setsockopt(umem->fd, SOL_XDP, XDP_UMEM_REG, &mr, sizeof(mr));
登錄後複製

UMEM共享內存通常以4K爲一個單元,每個單元可以存儲一個數據包,UMEM共享內存通常爲4096個單元。

接收和發送的數據包都是存儲在UMEM內存單元。

用戶程序和內核都可以直接操作這塊內存區域,所以發送和接收數據包時,只是簡單的內存拷貝,不需要進行系統調用。

用戶程序需要維護一個UMEM內存使用記錄,記錄每一個UMEM單元是否已被使用,每個記錄都會有一個相對地址,用於定位UMEM內存單元地址。

2.2 無鎖環形隊列

AF_XDP socket總共有4個無鎖環形隊列,分別爲:

  • 填充隊列(FILL RING)
  • 已完成隊列(COMPLETION RING)
  • 發送隊列(TX RING)
  • 接收隊列(RX RING)

圖片

環形隊列創建方式:

//創建FILL RINGsetsockopt(fd, SOL_XDP, XDP_UMEM_FILL_RING,&umem->config.fill_size, sizeof(umem->config.fill_size)); //創建COMPLETION RINGsetsockopt(fd, SOL_XDP, XDP_UMEM_COMPLETION_RING,&umem->config.comp_size, sizeof(umem->config.comp_size));//創建RX RING setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING,&xsk->config.rx_size, sizeof(xsk->config.rx_size));//創建TX RINGsetsockopt(xsk->fd, SOL_XDP, XDP_TX_RING, &xsk->config.tx_size, sizeof(xsk->config.tx_size));
登錄後複製

4個環形隊列實現方式基本相同,環形隊列是對數組進行封裝的數據結構,環形隊列由5個重要部分組成:

  • 生產者序號(producer)

    生產者序號用於指示數組當前可生產的元素位置,如果隊列已滿,將不能再生產。

  • 消費者序號(consumer)

    消費者序號用於指示當前可消費的元素位置,如果隊列已空,將不能再消費。

  • 隊列長度(len)

    隊列長度即數組長度。

  • 隊列掩碼(mask)

    mask=len-1,生產者和消費者序號不能直接使用,需要配合掩碼使用,producer,consumer和mask進行與運算,可以獲取到數組的索引值。

  • 固定長度數組

數組的每一個元素記錄了UMEM單元的相對地址,如果UMEM單元有發送和接收的數據包,還會記錄數據包的長度。

環形隊列的無鎖化通過原子變量來實現,原子變量和原子操作在高性能編程中經常會用到。

2.3 AF_XDP接收數據包

 AF_XDP接收數據包需要FILL RING,RX RING兩個環形隊列配合工作。

第一步:XDP程序獲取可用UMEM單元。

FILL RING記錄了可以用來接收數據包的UMEM單元數量,用戶程序根據UMEM使用記錄,定期的往FILL RING生產可用UMEM單元。

 第二步:XDP填充新的接收數據包

XDP程序消費FILL RING中UMEM單元用於存放網絡數據包,接收完數據包後,將UMEM單元和數據包長度重新打包,填充至RX RING隊列,生產一個待接收的數據包。

 第三步:用戶程序接收網絡數據包

用戶程序檢測到RX RING有待接的收數據包,消費RX RING中數據包,將數據包信息從UMEM單元中拷貝至用戶程序緩衝區,同時用戶程序需要再次填充FILL RING隊列推動XDP繼續接收數據。

圖片

2.4 AF_XDP發送數據包

AF_XDP發送數據包需要COMP RING,TX RING兩個環形隊列配合工作。

第一步:用戶程序確保有足夠的UMEM發送單元

COMP RING記錄了已完成發送的數據包(UMEM單元)數量,用戶程序需要回收這部分UMEM單元,確保有足夠的UMEM發送單元。

第二步:用戶程序發送數據包

用戶程序申請一個可用的UMEM單元,將數據包拷貝至該UMEM單元,然後生產一個待發送數據包填充值TX RING。

第三步:XDP發送數據包

XDP程序檢測到TX RING中有待發送數據包,從TX RING消費一個數據包進行發送,發送完成後,將UMEM單元填充至COMP RING,生產一個已完成發送數據包,用戶程序將對該數據包UMEM單元進行回收。

圖片

3. AF_XDP高效的祕密

AF_XDP之所以高效,主要有三大原因:

  • 內核旁路技術

內核旁路技術在處理網絡數據包的時候,可以跳過Linux內核協議棧,相當於走了捷徑,這樣可以降低鏈路開銷。

  • 內存映射

用戶程序和內核共享UMEM內存和無鎖環形隊列,採用mmap技術將內存進行映射,用戶操作UMEM內存不需要進行系統調用,減少了系統調用上下文切換成本。

  • 無鎖環形隊列

無鎖環形隊列採用原子變量實現,可以減少線程切換和上下文切換成本。

基於以上幾點,AF_XDP必然是一個高性能的網絡技術,由於目前沒有一個能夠測試XDP極限性能的測試環境,大家如果對AF_XDP技術感興趣,可以自行上網搜索相關資料。

以上就是聊一聊Linux網絡性能王者——XDP技術的詳細內容,更多請關注本站其它相關文章!

更新時間

發表留言

請注意,留言須先通過審核才能發佈。