用於彈性網路介面卡 (ENA) 系列的 Linux 核心驅動程式

概述

ENA 是一種網路介面,旨在充分利用現代 CPU 功能和系統架構。

ENA 裝置透過管理佇列公開了一個輕量級管理介面,該介面具有最少的記憶體對映暫存器,並且可以透過 Admin Queue 擴充套件命令集。

該驅動程式支援一系列 ENA 裝置,與鏈路速度無關(即,相同的驅動程式用於 10GbE、25GbE、40GbE 等),並且具有協商和可擴充套件的功能集。

某些 ENA 裝置支援 SR-IOV。該驅動程式用於 SR-IOV 物理功能 (PF) 和虛擬功能 (VF) 裝置。

ENA 裝置透過提供多個 Tx/Rx 佇列對(最大數量由裝置透過 Admin Queue 公佈)、每個 Tx/Rx 佇列對的專用 MSI-X 中斷向量、自適應中斷調節和 CPU 快取行最佳化的資料放置,從而實現高速和低開銷的網路流量處理。

ENA 驅動程式支援行業標準的 TCP/IP 解除安裝功能,例如校驗和解除安裝。接收端縮放 (RSS) 支援多核縮放。

ENA 驅動程式及其對應的裝置實現了健康監控機制,例如看門狗,使裝置和驅動程式能夠以對應用程式透明的方式恢復,以及除錯日誌。

某些 ENA 裝置支援一種稱為低延遲佇列 (LLQ) 的工作模式,該模式可以節省更多微秒。

ENA 原始碼目錄結構

ena_com.[ch]

管理通訊層。該層負責處理裝置和驅動程式之間的所有管理(admin)通訊。

ena_eth_com.[ch]

Tx/Rx 資料路徑。

ena_admin_defs.h

ENA 管理介面的定義。

ena_eth_io_defs.h

ENA 資料路徑介面的定義。

ena_common_defs.h

ena_com 層的通用定義。

ena_regs_defs.h

ENA PCI 記憶體對映 (MMIO) 暫存器的定義。

ena_netdev.[ch]

主 Linux 核心驅動程式。

ena_ethtool.c

ethtool 回撥。

ena_xdp.[ch]

XDP 檔案

ena_pci_id_tbl.h

支援的裝置 ID。

管理介面:

ENA 管理介面透過以下方式公開

  • PCIe 配置空間

  • 裝置暫存器

  • Admin Queue (AQ) 和 Admin Completion Queue (ACQ)

  • 非同步事件通知佇列 (AENQ)

ENA 裝置 MMIO 暫存器僅在驅動程式初始化期間訪問,並且在進一步的正常裝置操作期間不使用。

AQ 用於提交管理命令,結果/響應透過 ACQ 非同步報告。

ENA 引入了一小部分管理命令,併為特定於供應商的擴充套件留有空間。大多數管理操作都以通用的 Get/Set 功能命令進行構建。

支援以下 admin 佇列命令

  • 建立 I/O 提交佇列

  • 建立 I/O 完成佇列

  • 銷燬 I/O 提交佇列

  • 銷燬 I/O 完成佇列

  • 獲取功能

  • 設定功能

  • 配置 AENQ

  • 獲取統計資訊

有關支援的 Get/Set 功能屬性的列表,請參閱 ena_admin_defs.h。

非同步事件通知佇列 (AENQ) 是 ENA 裝置用於向驅動程式傳送無法使用 ACQ 報告的事件的單向佇列。 AENQ 事件分為多個組。 每個組可能有多個綜合徵,如下所示

事件是

綜合徵

連結狀態更改

X

致命錯誤

X

通知

暫停流量

通知

恢復流量

保持活動

X

ACQ 和 AENQ 共享同一個 MSI-X 向量。

保持活動是一種特殊機制,允許監視裝置的健康狀況。 裝置每秒傳遞一個保持活動事件。 驅動程式維護一個看門狗 (WD) 處理程式,該處理程式記錄當前狀態和統計資訊。 如果未按預期傳遞保持活動事件,則 WD 會重置裝置和驅動程式。

資料路徑介面

I/O 操作基於 Tx 和 Rx 提交佇列(分別對應 Tx SQ 和 Rx SQ)。 每個 SQ 都有一個與之關聯的完成佇列 (CQ)。

SQ 和 CQ 在連續物理記憶體中實現為描述符環。

ENA 驅動程式支援 Tx SQ 的兩種佇列操作模式

  • 常規模式: 在此模式下,Tx SQ 駐留在主機的記憶體中。 ENA 裝置從主機記憶體中獲取 ENA Tx 描述符和資料包資料。

  • 低延遲佇列 (LLQ) 模式或“推送模式”: 在此模式下,驅動程式將傳輸描述符和資料包的前 96 個位元組直接推送到 ENA 裝置記憶體空間。 資料包有效負載的其餘部分由裝置獲取。 對於此操作模式,驅動程式使用專用的 PCI 裝置記憶體 BAR,該 BAR 對映有寫組合功能。

    請注意,並非所有 ENA 裝置都支援 LLQ,並且此功能在初始化時與裝置協商。 如果 ENA 裝置不支援 LLQ 模式,則驅動程式會回退到常規模式。

Rx SQ 僅支援常規模式。

該驅動程式支援 Tx 和 Rx 的多佇列。 這有多種好處

  • 減少給定乙太網介面上的 CPU/執行緒/程序爭用。

  • 完成時的快取未命中率降低,特別是對於儲存 sk_buff 結構的資料快取行。

  • 處理收到的資料包時,程序級並行性增加。

  • 透過將資料包的核心處理引導到使用該資料包的應用程式執行緒正在執行的 CPU,從而提高資料快取命中率。

  • 硬體中斷重定向。

中斷模式

驅動程式為每個佇列對分配一個 MSI-X 向量(對於 Tx 和 Rx 方向)。 驅動程式為管理分配額外的專用 MSI-X 向量(對於 ACQ 和 AENQ)。

管理中斷註冊在 Linux 核心探測介面卡時執行,並在刪除介面卡時取消註冊。 I/O 佇列中斷註冊在開啟介面卡的 Linux 介面時執行,並在關閉介面時取消註冊。

管理中斷命名為

ena-mgmnt@pci:<PCI domain:bus:slot.function>

對於每個佇列對,中斷命名為

<interface name>-Tx-Rx-<queue index>

ENA 裝置以自動遮蔽和自動清除中斷模式執行。 也就是說,一旦 MSI-X 傳遞到主機,其 Cause 位將自動清除,並且中斷將被遮蔽。 中斷在 NAPI 處理完成後由驅動程式取消遮蔽。

中斷調節

ENA 驅動程式和裝置可以在傳統或自適應中斷調節模式下執行。

在傳統模式下,驅動程式指示裝置根據靜態中斷延遲值推遲中斷髮布。 中斷延遲值可以透過 ethtool(8) 配置。 驅動程式支援以下 ethtool 引數:tx-usecsrx-usecs

在自適應中斷調節模式下,中斷延遲值由驅動程式動態更新,並根據流量性質在每個 NAPI 週期進行調整。

可以透過 ethtool(8)adaptive_rx on|off 引數開啟/關閉自適應合併。

有關自適應中斷調節 (DIM) 的更多資訊,請參見 Net DIM - 通用網路動態中斷調節

RX copybreak

rx_copybreak 預設初始化為 ENA_DEFAULT_RX_COPYBREAK,可以透過 SIOCETHTOOL ioctl 的 ETHTOOL_STUNABLE 命令進行配置。

此選項控制接收資料包的 RX 描述符將被回收的最大資料包長度。 當收到小於 RX copybreak 位元組的資料包時,它將被複制到新的記憶體緩衝區中,並且 RX 描述符將返回到 HW。

統計資訊

使用者可以使用 ethtool 獲取 ENA 裝置和驅動程式統計資訊。 驅動程式可以從裝置收集常規或擴充套件統計資訊(包括每個佇列的統計資訊)。

此外,驅動程式會在裝置重置時將統計資訊記錄到 syslog。

在支援的例項型別上,統計資訊還將包括 ENA Express 資料(帶有 ena_srd 字首的欄位)。 有關 ENA Express 資料的完整文件,請參閱 https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ena-express.html#ena-express-monitor

MTU

該驅動程式支援任意大的 MTU,最大值與裝置協商。 驅動程式使用 SetFeature 命令(ENA_ADMIN_MTU 屬性)配置 MTU。 使用者可以透過 ip(8) 和類似的舊工具更改 MTU。

無狀態解除安裝

ENA 驅動程式支援

  • IPv4 標頭校驗和解除安裝

  • TCP/UDP over IPv4/IPv6 校驗和解除安裝

RSS

  • ENA 裝置支援 RSS,允許靈活的 Rx 流量引導。

  • 支援 Toeplitz 和 CRC32 雜湊函式。

  • L2/L3/L4 欄位的不同組合可以配置為雜湊函式的輸入。

  • 驅動程式使用 AQ SetFeature 命令(ENA_ADMIN_RSS_HASH_FUNCTION、ENA_ADMIN_RSS_HASH_INPUT 和 ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG 屬性)配置 RSS 設定。

  • 如果設定了 NETIF_F_RXHASH 標誌,則在收到的 SKB 中設定 Rx CQ 描述符中傳遞的雜湊函式的 32 位結果。

  • 使用者可以透過 ethtool(8) 提供雜湊金鑰、雜湊函式並配置間接表。

資料路徑

Tx

堆疊呼叫 ena_start_xmit()。 此函式執行以下操作

  • 對映資料緩衝區(skb->data 和 frags)。

  • 為推送緩衝區填充 ena_buf(如果驅動程式和裝置處於推送模式)。

  • 為其餘 frags 準備 ENA bufs。

  • 從空 req_id 環中分配新的請求 ID。 請求 ID 是 Tx 資訊中資料包的索引。 這用於亂序 Tx 完成。

  • 將資料包新增到 Tx 環中的正確位置。

  • 呼叫 ena_com_prepare_tx(),這是一個 ENA 通訊層,它將 ena_bufs 轉換為 ENA 描述符(並根據需要新增元 ENA 描述符)。

    • 此函式還會將 ENA 描述符和推送緩衝區複製到裝置記憶體空間(如果在推送模式下)。

  • 向 ENA 裝置寫入門鈴。

  • 當 ENA 裝置完成傳送資料包時,會引發完成中斷。

  • 中斷處理程式計劃 NAPI。

  • 呼叫 ena_clean_tx_irq() 函式。 此函式處理 ENA 生成的完成描述符,每個已完成的資料包都有一個完成描述符。

    • 從完成描述符中檢索 req_id。 資料包的 tx_info 透過 req_id 檢索。 資料緩衝區被取消對映,並且 req_id 返回到空 req_id 環。

    • 當完成描述符完成或達到預算時,該函式停止。

Rx

  • 當從 ENA 裝置收到資料包時。

  • 中斷處理程式計劃 NAPI。

  • 呼叫 ena_clean_rx_irq() 函式。 此函式呼叫 ena_com_rx_pkt(),這是一個 ENA 通訊層函式,它返回用於新資料包的描述符數量,如果未找到新資料包,則返回零。

  • ena_rx_skb() 檢查資料包長度

    • 如果資料包較小 (len < rx_copybreak),則驅動程式會為新資料包分配一個 SKB,並將資料包有效負載複製到 SKB 資料緩衝區中。

      • 這樣,原始資料緩衝區不會傳遞到堆疊,而是被重用於將來的 Rx 資料包。

    • 否則,該函式將取消對映 Rx 緩衝區,將第一個描述符設定為 skb 的線性部分,並將其他描述符設定為 skb 的 frags。

  • 使用必要的資訊(協議、校驗和硬體驗證結果等)更新新的 SKB,然後使用 NAPI 介面函式 napi_gro_receive() 將其傳遞到網路堆疊。

動態 RX 緩衝區 (DRB)

RX 環中的每個 RX 描述符都是單個記憶體頁面(長度為 4KB 或 16KB,具體取決於系統的配置)。 為了減少處理小資料包的高速率時所需的記憶體分配,如果此頁面的剩餘空間超過 2KB 未使用,則驅動程式會嘗試重用剩餘的 RX 描述符空間。

此機制的一個簡單示例是以下事件序列

1. Driver allocates page-sized RX buffer and passes it to hardware
        +----------------------+
        |4KB RX Buffer         |
        +----------------------+

2. A 300Bytes packet is received on this buffer

3. The driver increases the ref count on this page and returns it back to
   HW as an RX buffer of size 4KB - 300Bytes = 3796 Bytes
       +----+--------------------+
       |****|3796 Bytes RX Buffer|
       +----+--------------------+

當載入 XDP 程式時,或者當 RX 資料包小於 rx_copybreak 位元組時,不使用此機制(在這種情況下,資料包將從 RX 緩衝區複製到為其分配的新 skb 的線性部分,並且 RX 緩衝區保持相同的大小,請參見 RX copybreak)。