Devlink 端口¶
devlink-port
是设备上存在的端口。它具有设备逻辑上独立的入口/出口点。devlink 端口可以有多种类型。devlink 端口类型以及端口属性描述了端口的代表意义。
设备驱动程序如果想发布 devlink 端口,需要设置 devlink 端口属性并注册 devlink 端口。
Devlink 端口类型如下所述。
类型 |
描述 |
|
任何类型的物理端口。这可以是 eswitch 物理端口或设备上的任何其他物理端口。 |
|
表示 DSA 互连端口。 |
|
表示仅适用于 DSA 的 CPU 端口。 |
|
表示代表 PCI 物理功能 (PF) 端口的 eswitch 端口。 |
|
表示代表 PCI 虚拟功能 (VF) 端口的 eswitch 端口。 |
|
表示代表 PCI 子功能 (SF) 端口的 eswitch 端口。 |
|
表示 PCI 虚拟功能的虚拟端口。 |
Devlink 端口可以根据下面描述的链路层具有不同的类型。
类型 |
描述 |
|
当端口的链路层是以太网时,驱动程序应设置此端口类型。 |
|
当端口的链路层是 InfiniBand 时,驱动程序应设置此端口类型。 |
|
当驱动程序应自动检测端口类型时,用户会指示此类型。 |
PCI 控制器¶
在大多数情况下,PCI 设备只有一个控制器。一个控制器由潜在的多个物理功能、虚拟功能和子功能组成。一个功能由一个或多个端口组成。该端口由 devlink eswitch 端口表示。
但是,连接到多个 CPU 或多个 PCI 根复合体或 SmartNIC 的 PCI 设备可能具有多个控制器。对于具有多个控制器的设备,每个控制器都由唯一的控制器编号区分。eswitch 位于支持多个控制器端口的 PCI 设备上。
具有两个控制器的系统的示例视图
---------------------------------------------------------
| |
| --------- --------- ------- ------- |
----------- | | vf(s) | | sf(s) | |vf(s)| |sf(s)| |
| server | | ------- ----/---- ---/----- ------- ---/--- ---/--- |
| pci rc |=== | pf0 |______/________/ | pf1 |___/_______/ |
| connect | | ------- ------- |
----------- | | controller_num=1 (no eswitch) |
------|--------------------------------------------------
(internal wire)
|
---------------------------------------------------------
| devlink eswitch ports and reps |
| ----------------------------------------------------- |
| |ctrl-0 | ctrl-0 | ctrl-0 | ctrl-0 | ctrl-0 |ctrl-0 | |
| |pf0 | pf0vfN | pf0sfN | pf1 | pf1vfN |pf1sfN | |
| ----------------------------------------------------- |
| |ctrl-1 | ctrl-1 | ctrl-1 | ctrl-1 | ctrl-1 |ctrl-1 | |
| |pf0 | pf0vfN | pf0sfN | pf1 | pf1vfN |pf1sfN | |
| ----------------------------------------------------- |
| |
| |
----------- | --------- --------- ------- ------- |
| smartNIC| | | vf(s) | | sf(s) | |vf(s)| |sf(s)| |
| pci rc |==| ------- ----/---- ---/----- ------- ---/--- ---/--- |
| connect | | | pf0 |______/________/ | pf1 |___/_______/ |
----------- | ------- ------- |
| |
| local controller_num=0 (eswitch) |
---------------------------------------------------------
在上面的示例中,外部控制器(由控制器编号 = 1 标识)没有 eswitch。本地控制器(由控制器编号 = 0 标识)具有 eswitch。本地控制器上的 Devlink 实例具有两个控制器的 eswitch devlink 端口。
功能配置¶
用户可以在枚举 PCI 功能之前配置一个或多个功能属性。通常,这意味着用户应在为该功能创建特定于总线的设备之前配置功能属性。但是,启用 SRIOV 后,将在 PCI 总线上创建虚拟功能设备。因此,应在将虚拟功能设备绑定到驱动程序之前配置功能属性。对于子功能,这意味着用户应在激活端口功能之前配置端口功能属性。
用户可以使用 devlink port function set hw_addr 命令设置功能的硬件地址。对于以太网端口功能,这意味着 MAC 地址。
用户还可以使用 devlink port function set roce 命令设置功能的 RoCE 功能。
用户还可以使用 devlink port function set migratable 命令将功能设置为可迁移。
用户还可以使用 devlink port function set ipsec_crypto 命令设置功能的 IPsec 加密功能。
用户还可以使用 devlink port function set ipsec_packet 命令设置功能的 IPsec 数据包功能。
用户还可以使用 devlink port function set max_io_eqs 命令设置功能的最大 IO 事件队列数。
功能属性¶
MAC 地址设置¶
PCI VF/SF 的已配置 MAC 地址将由为 PCI VF/SF 创建的 netdevice 和 rdma 设备使用。
获取由其唯一 devlink 端口索引标识的 VF 的 MAC 地址
$ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00
设置由其唯一 devlink 端口索引标识的 VF 的 MAC 地址
$ devlink port function set pci/0000:06:00.0/2 hw_addr 00:11:22:33:44:55 $ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:11:22:33:44:55
获取由其唯一 devlink 端口索引标识的 SF 的 MAC 地址
$ devlink port show pci/0000:06:00.0/32768 pci/0000:06:00.0/32768: type eth netdev enp6s0pf0sf88 flavour pcisf pfnum 0 sfnum 88 function: hw_addr 00:00:00:00:00:00
设置由其唯一 devlink 端口索引标识的 SF 的 MAC 地址
$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 $ devlink port show pci/0000:06:00.0/32768 pci/0000:06:00.0/32768: type eth netdev enp6s0pf0sf88 flavour pcisf pfnum 0 sfnum 88 function: hw_addr 00:00:00:00:88:88
RoCE 功能设置¶
并非所有 PCI VF/SF 都需要 RoCE 功能。
当禁用 RoCE 功能时,可以节省每个 PCI VF/SF 的系统内存。
当用户禁用 VF/SF 的 RoCE 功能时,用户应用程序无法通过此 VF/SF 发送或接收任何 RoCE 数据包,并且此 PCI 的 RoCE GID 表将为空。
当使用端口功能属性在设备中禁用 RoCE 功能时,VF/SF 驱动程序无法覆盖它。
获取 VF 设备的 RoCE 功能
$ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 roce enable
设置 VF 设备的 RoCE 功能
$ devlink port function set pci/0000:06:00.0/2 roce disable $ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 roce disable
可迁移功能设置¶
实时迁移是将实时虚拟机从一台物理主机传输到另一台物理主机,而不会中断其正常操作的过程。
希望 PCI VF 能够执行实时迁移的用户需要显式启用 VF 可迁移功能。
当用户启用 VF 的可迁移功能,并且 HV 将 VF 绑定到具有迁移支持的 VFIO 驱动程序时,用户可以将 VM 与此 VF 从一个 HV 迁移到另一个 HV。
但是,当启用可迁移功能时,设备将禁用无法迁移的功能。因此,可迁移功能可能会对 VF 施加限制,因此让用户决定。
具有可迁移功能配置的 LM 示例:- 获取 VF 设备的可迁移功能
$ devlink port show pci/0000:06:00.0/2
pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1
function:
hw_addr 00:00:00:00:00:00 migratable disable
设置 VF 设备的可迁移功能
$ devlink port function set pci/0000:06:00.0/2 migratable enable $ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 migratable enable
将 VF 绑定到具有迁移支持的 VFIO 驱动程序
$ echo <pci_id> > /sys/bus/pci/devices/0000:08:00.0/driver/unbind $ echo mlx5_vfio_pci > /sys/bus/pci/devices/0000:08:00.0/driver_override $ echo <pci_id> > /sys/bus/pci/devices/0000:08:00.0/driver/bind
将 VF 附加到 VM。启动 VM。执行实时迁移。
IPsec 加密功能设置¶
当用户为 VF 启用 IPsec 加密功能时,用户应用程序可以将 XFRM 状态加密操作(加密/解密)卸载到此 VF。
当禁用 VF 的 IPsec 加密功能(默认)时,XFRM 状态由内核中的软件处理。
获取 VF 设备的 IPsec 加密功能
$ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 ipsec_crypto disabled
设置 VF 设备的 IPsec 加密功能
$ devlink port function set pci/0000:06:00.0/2 ipsec_crypto enable $ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 ipsec_crypto enabled
IPsec 数据包功能设置¶
当用户为 VF 启用 IPsec 数据包功能时,用户应用程序可以将 XFRM 状态和策略加密操作(加密/解密)卸载到此 VF,以及 IPsec 封装。
当禁用 VF 的 IPsec 数据包功能(默认)时,XFRM 状态和策略由内核中的软件处理。
获取 VF 设备的 IPsec 数据包功能
$ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 ipsec_packet disabled
设置 VF 设备的 IPsec 数据包功能
$ devlink port function set pci/0000:06:00.0/2 ipsec_packet enable $ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 ipsec_packet enabled
最大 IO 事件队列设置¶
当用户为 SF 或 VF 设置最大 IO 事件队列数时,此类功能驱动程序仅限于使用强制数量的 IO 事件队列。
IO 事件队列传递与 IO 队列相关的事件,包括网络设备发送和接收队列(txq 和 rxq)和 RDMA 队列对 (QP)。例如,netdevice 通道和 RDMA 设备完成向量的数量是从功能的 IO 事件队列派生的。通常,驱动程序使用的中断向量数量受到每个设备的 IO 事件队列数量的限制,因为每个 IO 事件队列都连接到一个中断向量。
获取 VF 设备的最大 IO 事件队列数
$ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 ipsec_packet disabled max_io_eqs 10
设置 VF 设备的最大 IO 事件队列数
$ devlink port function set pci/0000:06:00.0/2 max_io_eqs 32 $ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 ipsec_packet disabled max_io_eqs 32
子功能¶
子功能是一种轻量级功能,它具有在其上部署的父 PCI 功能。子功能以 1 为单位创建和部署。与 SRIOV VF 不同,子功能不需要自己的 PCI 虚拟功能。子功能通过父 PCI 功能与硬件通信。
要使用子功能,请按照 3 个步骤的设置顺序进行
创建 - 创建子功能;
配置 - 配置子功能属性;
部署 - 部署子功能;
子功能管理是使用 devlink 端口用户界面完成的。用户在子功能管理设备上执行设置。
(1) 创建¶
使用 devlink 端口接口创建子功能。用户通过添加子功能类型的 devlink 端口来添加子功能。devlink 内核代码向下调用子功能管理驱动程序(devlink ops)并要求它创建子功能 devlink 端口。然后,驱动程序实例化子功能端口和任何关联的对象,例如运行状况报告程序和表示网络设备。
(2) 配置¶
子功能 devlink 端口已创建,但尚未激活。这意味着实体是在 devlink 端创建的,e-switch 端口表示已创建,但子功能设备本身尚未创建。用户可以使用 e-switch 端口表示进行设置,将其放入网桥,添加 TC 规则等。用户也可以在子功能处于非活动状态时配置子功能的硬件地址(例如 MAC 地址)。
(3) 部署¶
配置子功能后,用户必须激活它才能使用它。激活后,子功能管理驱动程序会要求子功能管理设备在特定的 PCI 功能上实例化子功能设备。子功能设备是在 Documentation/driver-api/auxiliary_bus.rst 上创建的。此时,匹配的子功能驱动程序将绑定到子功能的辅助设备。
速率对象管理¶
Devlink 提供了管理单个 devlink 端口或组的 tx 速率的 API。这是通过速率对象完成的,速率对象可以是以下两种类型之一
叶
表示单个 devlink 端口;由驱动程序创建/销毁。由于叶与其 devlink 端口具有 1 对 1 映射,因此在用户空间中将其称为
pci/<bus_addr>/<port_index>
;节点
表示一组速率对象(叶和/或节点);由来自用户空间的请求创建/删除;最初为空(未添加速率对象)。在用户空间中,它被称为
pci/<bus_addr>/<node_name>
,其中node_name
可以是任何标识符,十进制数字除外,以避免与叶发生冲突。
API 允许配置以下速率对象的参数
tx_share
所有其他速率对象之间共享的最小 TX 速率值,或者速率对象如果是父组的一部分,则与其他组的一部分共享。
tx_max
最大 TX 速率值。
tx_priority
允许在兄弟节点之间使用严格的优先级仲裁器。此仲裁方案尝试根据节点的优先级来调度节点,只要节点保持在其带宽限制内。优先级越高,节点被选择进行调度的可能性就越高。
tx_weight
允许在兄弟节点之间使用加权公平队列仲裁方案。此仲裁方案可以与严格优先级同时使用。当节点配置更高的速率时,它会获得相对于其兄弟节点更多的 BW。这些值是相对的,就像百分比点一样,它们基本上告诉节点应该获得相对于其兄弟节点的多少 BW。
父
父节点名称。父节点速率限制被视为所有节点子节点限制的附加限制。
tx_max
是子节点的上限。tx_share
是在子节点之间分配的总带宽。
tx_priority
和 tx_weight
可以同时使用。在这种情况下,具有相同优先级的节点在兄弟节点组中形成一个 WFQ 子组,并且它们之间的仲裁基于分配的权重。
从高级别仲裁流程
选择优先级最高且保持在 BW 限制内且未被阻止的节点或节点组。使用
tx_priority
作为此仲裁的参数。如果节点组具有相同的优先级,则对该子组执行 WFQ 仲裁。使用
tx_weight
作为此仲裁的参数。选择获胜节点,并继续在其子节点之间进行仲裁流程,直到到达叶节点并建立获胜者。
如果最高优先级子组中的所有节点都已满足或过度使用其分配的 BW,请移动到较低优先级的节点。
驱动程序实现允许支持两种或任一速率对象类型及其参数的设置方法。此外,驱动程序实现可以导出节点/叶及其父子关系。
术语和定义¶
术语 |
定义 |
|
具有一个或多个 PCI 总线的物理 PCI 设备由一个或多个 PCI 控制器组成。 |
|
控制器由潜在的多个物理功能、虚拟功能和子功能组成。 |
|
管理端口功能的实体。 |
|
一种轻量级功能,它具有在其上部署的父 PCI 功能。 |
|
子功能的总线设备,通常位于辅助总线上。 |
|
子功能辅助设备的设备驱动程序。 |
|
支持子功能管理的 PCI 物理功能。 |
|
支持使用 devlink 端口接口进行子功能管理的 PCI 物理功能的设备驱动程序。 |
|
托管子功能设备的 PCI 物理功能的设备驱动程序。在大多数情况下,它与子功能管理驱动程序相同。当子功能在外部控制器上使用时,子功能管理驱动程序和主机驱动程序是不同的。 |