Devlink 端口¶
devlink-port
是设备上存在的端口。它具有设备逻辑上独立的入口/出口点。一个 devlink 端口可以是多种类型中的任何一种。devlink 端口类型以及端口属性描述了一个端口代表什么。
打算发布 devlink 端口的设备驱动程序设置 devlink 端口属性并注册 devlink 端口。
Devlink 端口类型描述如下。
类型 |
描述 |
|
任何类型的物理端口。这可以是 eswitch 物理端口或设备上的任何其他物理端口。 |
|
这表示 DSA 互连端口。 |
|
这表示仅适用于 DSA 的 CPU 端口。 |
|
这表示一个 eswitch 端口,代表 PCI 物理功能 (PF) 的端口。 |
|
这表示一个 eswitch 端口,代表 PCI 虚拟功能 (VF) 的端口。 |
|
这表示一个 eswitch 端口,代表 PCI 子功能 (SF) 的端口。 |
|
这表示 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 创建的网络设备和 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 驱动程序时,用户可以将具有此 VF 的 VM 从一个 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 状态和策略加密操作(加密/解密)以及 IPsec 封装卸载到此 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_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)。例如,网络设备通道的数量和 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 操作),并要求它创建一个子功能 devlink 端口。然后,驱动程序实例化子功能端口和任何关联的对象,例如运行状况报告器和代表网络设备。
(2) 配置¶
创建了子功能 devlink 端口,但它尚未激活。这意味着实体是在 devlink 端创建的,创建了电子交换机端口代表器,但子功能设备本身尚未创建。用户可以使用电子交换机端口代表器来执行设置,将其放入网桥、添加 TC 规则等。用户也可以在子功能处于非活动状态时配置子功能的硬件地址(例如 MAC 地址)。
(3) 部署¶
配置子功能后,用户必须激活它才能使用它。激活后,子功能管理驱动程序会要求子功能管理设备在特定的 PCI 功能上实例化子功能设备。子功能设备是在 Documentation/driver-api/auxiliary_bus.rst 上创建的。此时,匹配的子功能驱动程序将绑定到子功能的辅助设备。
速率对象管理¶
Devlink 提供 API 来管理单个 devlink 端口或组的 tx 速率。这是通过速率对象完成的,速率对象可以是以下两种类型之一
叶子
表示单个 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
允许在同级之间使用加权公平队列仲裁方案。此仲裁方案可以与严格优先级同时使用。当节点配置了更高的速率时,它会获得相对于其同级更多的带宽。这些值是相对的,类似于百分比点,它们基本上表示节点相对于其同级应占用多少带宽。
parent
父节点名称。父节点速率限制被视为所有子节点限制的额外限制。
tx_max
是子节点的上限。tx_share
是在子节点之间分配的总带宽。
tx_priority
和 tx_weight
可以同时使用。在这种情况下,具有相同优先级的节点在同级组中形成一个 WFQ 子组,并且它们之间的仲裁基于分配的权重。
高级仲裁流程
选择优先级最高且在带宽限制内且未被阻塞的节点或节点组。使用
tx_priority
作为此仲裁的参数。如果节点组具有相同的优先级,则在该子组上执行 WFQ 仲裁。使用
tx_weight
作为此仲裁的参数。选择获胜的节点,并在其子节点之间继续仲裁流程,直到到达叶节点并确定获胜者。
如果来自最高优先级子组的所有节点都已满足或超出了其分配的带宽,则移动到较低优先级的节点。
驱动程序实现允许支持两种或其中一种速率对象类型及其参数的设置方法。此外,驱动程序实现可以导出节点/叶及其父子关系。
术语和定义¶
术语 |
定义 |
|
具有一个或多个 PCI 总线的物理 PCI 设备由一个或多个 PCI 控制器组成。 |
|
控制器由可能多个物理功能、虚拟功能和子功能组成。 |
|
用于管理端口功能的对象。 |
|
在其上部署了父 PCI 功能的轻量级功能。 |
|
子功能的总线设备,通常在辅助总线上。 |
|
用于子功能辅助设备的设备驱动程序。 |
|
支持子功能管理的 PCI 物理功能。 |
|
使用 devlink 端口接口支持子功能管理的 PCI 物理功能的设备驱动程序。 |
|
用于承载子功能设备的 PCI 物理功能的设备驱动程序。在大多数情况下,它与子功能管理驱动程序相同。当子功能在外部控制器上使用时,子功能管理和主机驱动程序是不同的。 |