Compute Engine 虚拟以太网 (gve) 的 Linux 内核驱动程序:

支持的硬件

GVE 驱动程序绑定到某些 Compute Engine VM 中发现的虚拟以太网设备使用的单个 PCI 设备 ID。

字段

注释

供应商 ID

0x1AE0

谷歌

设备 ID

0x0042

子供应商 ID

0x1AE0

谷歌

子设备 ID

0x0058

修订 ID

0x0

设备类别

0x200

以太网

PCI Bar

gVNIC PCI 设备公开了三个 32 位内存 BAR:- Bar0 - 设备配置和状态寄存器。- Bar1 - MSI-X 向量表 - Bar2 - IRQ、RX 和 TX 门铃

设备交互

驱动程序通过以下方式与设备交互
  • 寄存器
    • MMIO 寄存器块

    • 有关更多详细信息,请参见 gve_register.h

  • 管理队列
    • 参见下面的描述

  • 重置
    • 设备可以随时重置

  • 中断
    • 请参见下面支持的中断

  • 发送和接收队列
    • 参见下面的描述

描述符格式

GVE 支持两种描述符格式:GQI 和 DQO。这两种格式具有完全不同的描述符,将在下面进行描述。

寻址模式

GVE 支持两种寻址模式:QPL 和 RDA。QPL(“队列页列表”)模式通过一组预先注册的页面来传递数据。

对于 RDA(“原始 DMA 寻址”)模式,页面集是动态的。因此,数据包缓冲区可以位于访客内存中的任何位置。

寄存器

所有寄存器都是 MMIO。

这些寄存器用于初始化和配置设备,以及查询设备状态以响应管理中断。

字节序

  • 管理队列消息和寄存器均为大端字节序。

  • GQI 描述符和数据路径寄存器均为大端字节序。

  • DQO 描述符和数据路径寄存器均为小端字节序。

管理队列 (AQ)

管理队列是一个 PAGE_SIZE 大小的内存块,被视为 AQ 命令数组,驱动程序使用它向设备发出命令并设置资源。驱动程序和设备会维护已提交和执行的命令计数。要发出 AQ 命令,驱动程序必须执行以下操作(具有适当的锁定)

  1. 将新命令复制到 AQ 数组中下一个可用的槽中

  2. 将其计数器增加新命令的数量

  3. 将计数器写入 GVE_ADMIN_QUEUE_DOORBELL 寄存器

  4. 轮询 ADMIN_QUEUE_EVENT_COUNTER 寄存器,直到其等于写入门铃的值,或直到超时。

设备将更新通过 ADMIN_QUEUE_EVENT_COUNTER 寄存器报告为已执行的每个 AQ 命令中的状态字段。

设备重置

通过将 0x0 写入 AQ PFN 寄存器来触发设备重置。这会导致设备释放驱动程序分配的所有资源,包括 AQ 本身。

中断

驱动程序支持以下中断

管理中断

设备使用管理中断来告知驱动程序查看 GVE_DEVICE_STATUS 寄存器。

管理 irq 的处理程序仅将服务任务排队到工作队列中,以检查寄存器并确认 irq。

通知块中断

通知块中断用于告知驱动程序轮询与该中断关联的队列。

这些 irq 的处理程序会调度该块的 napi 以运行并轮询队列。

GQI 流量队列

GQI 队列由一个描述符环和一个缓冲区组成,并分配给一个通知块。

描述符环是大小为 2 的幂的环形缓冲区,由固定大小的描述符组成。它们使用位于 Bar2 中的 __be32 门铃来移动其头指针。尾指针通过按顺序使用描述符并更新 __be32 计数器来移动。门铃和计数器都溢出到零。

每个队列的缓冲区必须事先在设备中注册为队列页列表,并且数据包数据只能放在这些页面中。

发送

gve 将发送环的缓冲区映射到 FIFO 中,并将数据包复制到 FIFO 中,然后再将其发送到网卡。

接收

接收环的缓冲区被放入一个与描述符环长度相同的数据环中,头指针和尾指针一起在环上移动。

DQO 流量队列

  • 每个 TX 和 RX 队列都分配有一个通知块。

  • 向设备发送描述符的 TX 和 RX 缓冲区队列使用 MMIO 门铃通知设备有新的描述符。

  • 接收来自设备的描述符的 RX 和 TX 完成队列使用“生成位”来了解设备何时填充了描述符。驱动程序使用“当前生成”初始化所有位。设备将使用与当前生成相反的“下一个生成”填充收到的描述符。当环绕时,会交换当前/下一个生成。

  • 驱动程序有责任确保 RX 和 TX 完成队列不会溢出。这可以通过限制发布到硬件的描述符数量来实现。

  • TX 数据包具有 16 位 completion_tag,RX 缓冲区具有 16 位 buffer_id。这些将在 TX 完成和 RX 队列上分别返回,以让驱动程序知道哪个数据包/缓冲区已完成。

发送

数据包的缓冲区被 DMA 映射以供设备在传输之前访问。成功发送数据包后,将取消映射缓冲区。

接收

驱动程序在 RX 缓冲区队列上将固定大小的缓冲区发布到硬件。在关联的 RX 队列上接收的数据包可能跨越多个描述符。