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

支持的硬件

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

字段

注释

供应商 ID

0x1AE0

Google

设备 ID

0x0042

子供应商 ID

0x1AE0

Google

子设备 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 寄存器,直到它等于写入门铃的值,或直到超时。

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

设备重置

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

中断

驱动程序支持以下中断

管理中断

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

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

通知块中断

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

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

GQI 流量队列

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

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

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

发送

gve 将用于传输环的缓冲区映射到 FIFO 中,并在将数据包发送到 NIC 之前将数据包复制到 FIFO 中。

接收

用于接收环的缓冲区被放入数据环中,该数据环的长度与描述符环相同,并且头指针和尾指针一起在环上前进。

DQO 流量队列

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

  • TX 和 RX 缓冲区队列(将描述符发送到设备)使用 MMIO 门铃来通知设备有关新描述符。

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

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

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

发送

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

接收

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