DOCA 流
本指南介绍如何部署 DOCA Flow 库、DOCA Flow API 的理念以及如何使用它。本指南适用于编写专注于数据包处理(例如网关)的网络功能应用程序的开发人员。它假设您熟悉网络堆栈和 DPDK。
DOCA Flow 是用于在硬件中构建通用数据包处理管道的最基本 API。DOCA Flow 库提供了一个 API,用于构建一组管道,其中每个管道都包含匹配标准、监控和一组操作。管道可以链接在一起,以便在执行管道定义的操作后,数据包可以继续进入另一个管道。
使用 DOCA Flow API,可以轻松开发硬件加速应用程序,这些应用程序可以匹配多达两层的数据包(隧道化)。
MAC/VLAN/ETHERTYPE
IPv4/IPv6
TCP/UDP/ICMP
GRE/VXLAN/GTP-U/ESP/PSP
元数据
执行管道可以包括数据包修改操作,例如以下操作
修改 MAC 地址
修改 IP 地址
修改 L4(端口)
剥离隧道
添加隧道
设置元数据
加密/解密
执行管道还可以具有监控操作,例如以下操作
计数
策略器
管道还具有转发目标,可以是以下任何一项
软件(RSS 到队列子集)
端口
另一个管道
丢弃数据包
基于 DOCA Flow 的应用程序可以在主机或 NVIDIA® BlueField® DPU 目标上运行。基于流的程序需要分配巨页,因此需要以下命令
$ echo '1024' | sudo tee -a /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
$ sudo mkdir /mnt/huge
$ sudo mount -t hugetlbfs -o pagesize=2M nodev /mnt/huge
下图显示了 DOCA Flow 库如何定义管道模板、接收要处理的数据包、创建管道条目以及在 NIC 硬件中卸载流规则。

DOCA Flow 的特性
用户定义的匹配解析器和操作集
DOCA Flow 管道可以动态创建或销毁
数据包处理完全由硬件加速,在流管道中具有特定条目
与硬件中任何管道条目都不匹配的数据包可以发送到 Arm 内核进行异常处理,然后再重新注入回硬件
DOCA Flow 管道由以下组件组成
监视器(图中的 MON)- 计数、计量器或镜像
修改器(图中的 MDF)- 修改字段
转发器(图中的 FWD)- 转发到数据包处理的下一阶段
DOCA Flow 将管道组织成名为域的高级容器,以满足底层架构的特定需求。
定义域的关键要素是数据包方向和一组允许的操作。
域是管道属性(也与共享对象相关)
域限制了允许的操作集
域之间的转换是明确定义的(数据包不能任意跨域)
域可能会限制数据包方向之间对象的共享
数据包方向可以限制域之间的移动
Steering 域列表
DOCA Flow 提供了以下预定义的 steering 域集
域 | 描述 |
|
|
| |
|
|
|
|
VNF 模式下的域

交换机模式下的域

在交换机模式下,允许从具有默认域的管道转发到出口域根管道,但不允许从出口域转发到默认域。
来自软件 Tx 的流量转发到出口根管道。
具有 RSS 转发的管道遵循上述规则。
建议从出口完成封装。
初始化流
在使用任何 DOCA Flow 函数之前,必须调用 DOCA Flow 初始化函数 doca_flow_init()
,该函数初始化 DOCA Flow 所需的所有资源。
管道模式
此模式 ( mode_args
) 定义了 DOCA 中的基本流量。它在 DOCA 端口初始化时创建一些未命中规则。目前,DOCA 支持 3 种模式
vnf
从设备端口之一到达的数据包将被处理,并且可以发送到另一个端口。默认情况下,未命中数据包会转到 RSS。
下图显示了
vnf
模式下的基本流量流。数据包 1 首先未命中并转发到主机 RSS。应用程序捕获此数据包并决定如何处理它,然后创建管道条目。数据包 2 将命中此管道条目并执行操作,例如,对于 VXLAN,将执行解封装、修改和封装,然后从 P1 发送出去。switch
用于内部交换,仅允许表示器端口,例如,上行链路表示器和 SF/VF 表示器。数据包从一个端口转发到另一个端口。如果数据包从上行链路到达并且未命中用户管道定义的规则,则该数据包将在上行链路表示器的所有 RSS 队列上接收。
下图显示了
switch
模式下的基本流量流。数据包 1 首先未命中到主机 RSS 队列。应用程序捕获此数据包并决定数据包要发送到哪个表示器,然后设置规则。数据包命中此规则并转到 representor0。doca_dev
字段在doca_flow_port_cfg
中是必需的(使用doca_flow_port_cfg_set_dev()
),并且应指定隔离模式。注意应用程序必须避免在 DPDK API 中初始化 VF/SF 表示器端口(即,以下函数
rte_eth_dev_configure()
、rte_eth_rx_queue_setup()
、rte_eth_dev_start()
不得为 VF/SF 表示器端口调用)。DOCA Flow 交换机模式将所有端口统一到交换机管理器端口以进行流量管理。这意味着所有流量都由交换机管理器端口处理。用户只需在交换机管理器端口上创建一个 RSS 管道即可获取未命中的流量,并且他们应该只管理交换机管理器端口上的管道。交换机模式可以使用两种不同的
mode_args
配置工作:带或不带expert
。检索未命中流量源的port_id
的方式取决于此配置注意在交换机模式下,管道的默认
fwd_miss
(一旦用户未配置fwd_miss
)如下:在
isolated
模式下转发到内核在
non-isolated
模式下转发到端口 RSS
如果未设置
expert
,则未命中到软件的流量将在 mbuf CQE 字段中标记port_id
信息,以允许用户推断源port_id
。同时,用户可以将目标port_id
设置为 mbuf 元数据,并且数据包将基于元数据信息直接发送到目标端口。信息请参阅“流交换机到线缆”示例,以获取有关使用未命中流量 mbuf 进行
port_id
管理的更多信息。如果设置了
expert
,则port_id
不会添加到数据包中。用户可以自由配置管道以实现他们自己的解决方案。注意由于固件限制,从 VF 克隆到 RSS 管道的流量会丢失其
port_id
信息。
remote-vnf
远程模式是仅 BlueField 模式,具有两个物理端口(上行链路)。用户必须使用
doca_flow_port_pair
将一个物理端口与其表示器之一配对。来自此上行链路的数据包,如果未命中用户的任何规则,则首先在此表示器上接收。用户还必须使用doca_flow_port_pair
将两个物理上行链路配对。如果从一个上行链路接收到数据包,并且命中了 FWD 操作是另一个上行链路的规则,则数据包将从该上行链路发送出去。下图显示了远程 vnf 模式下的基本流量流。来自 BlueField 上行链路 P0 的数据包 1 首先未命中到主机 VF0。应用程序捕获此数据包并决定是丢弃它还是将其转发到另一个上行链路 (P1)。然后,使用 gRPC 在 P0 上设置规则,数据包 2 命中该规则,然后被丢弃或从 P1 发送出去。
起始点
DOCA Flow API 用作网络加速的抽象层 API。网络内功能中的数据包处理从入口到出口进行描述,因此,管道必须附加到源端口。一旦数据包到达入口端口,它就会按照 DOCA API 的定义启动硬件执行。
doca_flow_port
是一个不透明对象,因为 DOCA Flow API 不绑定到特定的数据包传递 API,例如 DPDK。第一步是通过调用 doca_flow_port_start()
来启动 DOCA Flow 端口。此步骤的目的是将用户应用程序端口附加到 DOCA Flow 端口。
当使用 DPDK 时,必须提供以下配置
enum doca_flow_port_type type = DOCA_FLOW_PORT_DPDK_BY_ID;
const char *devargs = "1";
devargs
参数指向一个字符串,该字符串具有 DPDK port_id
的十进制格式数值。端口必须在调用此 API 之前配置并启动。将 DPDK 端口映射到 DOCA 端口是同步应用程序端口与硬件端口所必需的。
端口操作状态
DOCA Flow 端口可以从不同的实例多次初始化。每个实例都准备其管道,但一次只有一个实例主动接收端口流量。主动处理端口流量的实例取决于 doca_flow_port_cfg_set_operation_state()
函数设置的操作状态
DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
– 该实例主动处理传入和传出流量DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE_READY_TO_SWAP
– 当没有其他活动实例可用时,该实例主动处理流量DOCA_FLOW_PORT_OPERATION_STATE_STANDBY
– 仅当没有活动或active_ready_to_swap
实例可用时,该实例才处理流量DOCA_FLOW_PORT_OPERATION_STATE_UNCONNECTED
– 无论其他实例的状态如何,该实例都不处理流量
如果未调用 doca_flow_port_cfg_set_operation_state()
函数,则应用默认状态 DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
。
当端口配置为期望处理流量的状态时,只有在该端口创建根管道后,该状态才会生效。
当活动端口关闭时(无论是正常关闭还是由于崩溃),备用实例都会自动变为活动状态,而无需任何操作。
端口操作状态可以在端口启动后使用 doca_flow_port_operation_state_modify()
函数进行修改。
用例示例
热升级
此操作状态机制允许升级 DOCA Flow 程序,而不会丢失任何流量。
要升级在 DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
状态(实例 A)下启动端口的现有 DOCA Flow 程序:
打开一个新的实例 B,并以
DOCA_FLOW_PORT_OPERATION_STATE_STANDBY
状态启动其端口。将实例 A 的端口从
DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
修改为DOCA_FLOW_PORT_OPERATION_STATE_UNCONNECTED
状态。此时,实例 B 开始接收流量。关闭实例 A。
打开一个新的实例 C,其状态为
DOCA_FLOW_PORT_OPERATION_STATE_UNCONNECTED
。实例 C 是实例 A 的升级版本。为实例 C 创建整个管道。
将实例 C 的状态从
DOCA_FLOW_PORT_OPERATION_STATE_UNCONNECTED
更改为DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
。此时,实例 B 停止接收流量,实例 C 开始接收流量。实例 B 可以关闭,也可以保留作为实例 C 崩溃时的备份。
交换现有实例
此机制还便于在两个不同的 DOCA Flow 程序之间进行交换,而不会丢失任何流量。
要在以 DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
和 DOCA_FLOW_PORT_OPERATION_STATE_STANDBY
状态(分别为实例 A 和实例 B)启动端口的两个现有 DOCA Flow 程序之间进行交换:
将实例 A 的端口从
DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
修改为DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE_READY_TO_SWAP
。将实例 B 的端口从
DOCA_FLOW_PORT_OPERATION_STATE_STANDBY
修改为DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
。此时,实例 B 开始接收流量。将实例 A 的端口从
DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE_READY_TO_SWAP
修改为DOCA_FLOW_PORT_OPERATION_STATE_STANDBY
。
局限性
仅在交换机模式下受支持 –
mode_args
字符串必须包含"switch"
。只有交换机端口支持状态;其表示器受其状态影响。启动表示器端口或使用非活动操作状态调用修改函数应失败。
两个实例不能同时处于相同的操作状态,除了
DOCA_FLOW_PORT_OPERATION_STATE_UNCONNECTED
。如果新实例初始化端口,而另一个具有相同操作状态的实例已存在,则在端口启动或根管道创建期间会返回DOCA_ERROR_ALREADY_EXIST
错误。
创建管道和管道条目
管道是一个模板,它定义了数据包处理,而无需添加任何特定的硬件规则。管道由一个模板组成,该模板包括以下元素
匹配
监视器
操作
转发
下图说明了管道结构。

创建阶段允许硬件有效地构建执行管道。创建管道后,可以添加特定条目。可以使用管道的子集(例如,完全跳过监视器,仅使用计数器等)。
管道匹配或操作应用
DOCA Flow 允许定义用于匹配数据包或对匹配的数据包执行操作(通过修改数据包)的标准。定义这些标准的信息通过以下指针提供
匹配或操作指针 – 在管道或条目创建时给出
掩码指针 – 可选择在管道创建时给出
可以在管道级别定义用于匹配或操作数据包的标准,它适用于管道的所有数据包,或者在每个条目的基础上指定,其中每个条目定义对匹配、操作或两者都进行的操作。
在 DOCA Flow 术语中,当字段在管道创建时被标识为 CHANGEABLE 时,这意味着字段的实际标准被推迟到条目创建。不同的条目可以为 CHANGEABLE 字段提供不同的标准。
匹配或操作字段可以在管道创建期间分类为以下之一
IGNORED – 在匹配或操作过程中被忽略
CHANGEABLE – 当实际行为被推迟到条目创建阶段时
SPECIFIC – 值按原样用于匹配或操作过程
可以提供掩码字段,在这种情况下,它被称为显式匹配或操作应用。如果掩码指针为 NULL,我们称之为隐式匹配或操作应用。以下小节提供了控制匹配和操作应用的逻辑。
当字段值指定为 0xffff
时,表示该字段的所有位都已设置(例如,对于 TTL,表示 0xff
,对于 IPv4 地址,表示 0xffffffff
)。
匹配
匹配是根据数据包字段的值选择数据包并将其 steering 以进行进一步处理的过程。处理可以是进一步匹配或操作应用。
数据包进入绿色过滤器,该过滤器通过使用值 A 对其进行掩码来修改它。然后将输出值 P&A 与值 B 进行比较,如果它们相等,则表示匹配。
A 和 B 的值根据管道配置和条目配置字段的值进行评估,根据“隐式匹配”和“显式匹配”部分中的表。
隐式匹配
匹配类型 | 管道匹配值 (V) | 管道匹配掩码 (M) | 条目匹配值 (E) | 过滤器 (A) | 规则 (B) |
忽略 | 0 | NULL | 不适用 | 0 | 0 |
常量 | 0<V<0xffff | NULL | 不适用 | 0xffff | V |
可更改(每个条目) | 0xffff | NULL | 0≤E≤0xffff | 0xffff | E |
显式匹配
匹配类型 | 管道匹配值 (V) | 管道匹配掩码 (M) | 条目匹配值 (E) | 过滤器 (A) | 规则 (B) |
常量 | V!=0xffff | 0<M≤0xffff | 0≤E≤0xffff | M | M&V |
可更改 | V==0xffff | 0<M≤0xffff | 0≤E≤0xffff | M | M&E |
忽略 | 0≤V<0xffff | M==0 | 0≤E≤0xffff | 0 | 0 |
操作应用
隐式操作应用
操作类型 | 管道操作值 (V) | 管道操作掩码 (M) | 条目操作值 (E) | 字段上的操作 |
忽略 | 0 | NULL | 不适用 | 无 |
常量 | 0 < V < 0xffff | NULL | 不适用 | 设置为 V |
可更改 | 0xffff | NULL | E | 设置为 E |
隐式操作应用示例
目标 IPv4 地址为 255.255.255.255
未提供掩码
条目值为 192.168.0.1
结果 – 操作字段是可更改的。因此,该值由条目提供。如果数据包上发生匹配,则数据包目标 IPv4 地址将更改为 192.168.0.1。
显式操作应用
假设 P 是数据包的字段值。
操作类型 | 管道操作值 (V) | 管道操作掩码 (M) | 条目操作值 (E) | 字段上的操作 |
常量 | V!=0xffff | 0≤M≤0xffff | 0≤E≤0xffff | 设置为 (~M & P) | (M & V) 换句话说:仅将掩码上设置的位修改为 V 中的值 |
可更改 | V==0xffff | 0<M≤0xffff | 0≤E≤0xffff | 设置为 (~M & P) | (M & E) |
忽略 | 0≤V<0xffff | M==0 | 0≤E≤0xffff | 无 |
显式操作应用示例
目标 IPv4 地址为 192.168.10.1
提供的掩码等于 255.255.0.0
条目值被忽略
结果 – 如果数据包上发生匹配,则数据包目标 IPv4 值更改为 192.168.0.0。
设置管道匹配或操作
匹配是创建管道时的强制性参数。使用 doca_flow_match
结构,用户必须定义管道要匹配的数据包字段。
对于每个 doca_flow_match
字段,用户选择字段类型是
忽略(匹配任何)– 数据包中忽略该字段的值。换句话说,匹配字段的任何值。
常量(特定)– 管道中的所有条目对于此字段都具有相同的值。用户不应为每个条目放置一个值。
可更改 – 字段的值是按条目定义的。用户必须在添加条目时提供它。
注意L4 类型、L3 类型和隧道类型不能是可更改的。
注意gtp_next_ext_hdr_type
仅支持psc
类型 (0x85)。
可以使用 doca_flow_pipe_cfg_set_match(struct doca_flow_pipe_cfg *cfg, const doca_flow_match *match, const doca_flow_match *match_mask)
函数隐式或显式地定义匹配字段类型。如果 match_mask == NULL
,则它是隐式完成的。否则,它是显式的。
在以下小节的表格中,使用了一个 16 位字段(例如第 4 层目标端口)的示例,其中
相同的概念将适用于任何其他字段(例如占用 32 位的 IP 地址)。
P 代表数据包字段值
V 代表管道匹配字段值
M 代表管道掩码字段值
E 代表匹配条目字段值
隐式匹配
匹配类型 | 管道匹配值 (V) | 管道匹配掩码 (M) | 条目匹配值 (E) | 过滤器 (A) | 规则 (B) |
忽略 | 0 | NULL | 不适用 | 0 | 0 |
常量 | 0<V<0xffff | NULL | 不适用 | 0xffff | V |
可更改(每个条目) | 0xffff | NULL | 0≤E≤0xffff | 0xffff | E |
要隐式匹配,应考虑以下事项。
忽略的字段
字段为零
管道对该字段没有比较
常量字段 – 这些是在所有条目中都具有常量值的字段。例如,如下所示,隧道类型为 VXLAN
match.tun.type = DOCA_FLOW_TUN_VXLAN;
这些字段必须仅在管道构建阶段配置一次,而不是每个新管道条目配置一次。
可更改字段 – 这些是每个条目的值可能更改的字段。例如,以下显示了匹配每个条目可变值的目标 IPv4 地址(外部 5 元组)
match.outer.ip4.dst_ip =
0xffffffff
;以下是一个匹配示例,其中
外部 5 元组
L3 类型为 IPv4 – 根据设计在条目之间是常量
L4 类型为 UDP – 根据设计在条目之间是常量
隧道类型为
DOCA_FLOW_TUN_VXLAN
– 根据设计在条目之间是常量IPv4 目标地址因条目而异
UDP 目标端口始终为
DOCA_VXLAN_DEFAULT_PORT
VXLAN 隧道 ID 因条目而异
数据包的其余字段将被忽略
内部 5 元组
L3 类型为 IPv4 – 根据设计在条目之间是常量
L4 类型为 TCP – 根据设计在条目之间是常量
IPv4 源地址和目标地址因条目而异
TCP 源端口和目标端口因条目而异
数据包的其余字段将被忽略
// filter creation
static void build_underlay_overlay_match(struct doca_flow_match *match)
{
//outer
match->outer.l3_type = DOCA_FLOW_L3_TYPE_IP4;
match->outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP;
match->tun.type = DOCA_FLOW_TUN_VXLAN;
match->outer.ip4.dst_ip = 0xffffffff;
match->outer.udp.l4_port.dst_port = DOCA_VXLAN_DEFAULT_PORT;
match->tun.vxlan_tun_id = 0xffffffff;
//inner
match->inner.l3_type = DOCA_FLOW_L3_TYPE_IP4;
match->inner.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_TCP;
match->inner.ip4.dst_ip = 0xffffffff;
match->inner.ip4.src_ip = 0xffffffff;
match->inner.tcp.l4_port.src_port = 0xffff;
match->inner.tcp.l4_port.dst_port = 0xffff;
}
// create entry specifying specific values to match upon
doca_error_t add_entry(struct doca_flow_pipe *pipe, struct doca_flow_port *port,
struct doca_flow_pipe_entry **entry)
{
struct doca_flow_match match = {};
struct entries_status status = {};
doca_error_t result;
match.outer.ip4.dst_ip = BE_IPV4_ADDR(7, 7, 7, 1);
match.tun.vxlan_tun_id = RTE_BE32(9876);
match.inner.ip4.src_ip = BE_IPV4_ADDR(8, 8, 8, 1);
match.inner.ip4.dst_ip = BE_IPV4_ADDR(9, 9, 9, 1);
match.inner.tcp.l4_port.src_port = rte_cpu_to_be_16(5678);
match.inner.tcp.l4_port.dst_port = rte_cpu_to_be_16(1234);
result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, &status, entry);
}
匹配内部的 doca_flow_meta
结构的字段不受隐式匹配规则的约束,并且必须与显式掩码值配对。
显式匹配
匹配类型 | 管道匹配值 (V) | 管道匹配掩码 (M) | 条目匹配值 (E) | 过滤器 (A) | 规则 (B) |
常量 | V!=0xffff | 0<M≤0xffff | 0≤E≤0xffff | M | M&V |
可更改 | V==0xffff | 0<M≤0xffff | 0≤E≤0xffff | M | M&E |
忽略 | 0≤V<0xffff | M==0 | 0≤E≤0xffff | 0 | 0 |
在这种情况下,有两个 doca_flow_match
项,应考虑以下事项
忽略的字段
M 等于零。这可以从规则等于 0 的表中看出。由于掩码也为 0,因此过滤后的结果数据包为 0。因此,比较始终成功。
match_mask.inner.ip4.dst_ip = 0;
常量字段
这些是具有常量值的字段。例如,如下所示,内部 5 元组匹配属于
0.0.0.0/24
子网的 IPv4 目标地址,并且此匹配在所有条目中都是常量// BE_IPV4_ADDR converts 4 numbers A,B,C,D to a big endian representation of IP address A.B.C.D match.inner.ip4.dst_ip = 0; match_mask.inner.ip4.dst_ip = BE_IPV4_ADDR(255, 255, 255, 0);
例如,如下所示,内部 5 元组匹配属于
1.2.0.0/16
子网的 IPv4 目标地址,并且此匹配在所有条目中都是常量。match.inner.ip4.dst_ip
的最后两个八位字节被忽略,因为应用了255.255.0.0
的match_mask
// BE_IPV4_ADDR converts 4 numbers A,B,C,D to a big endian representation of IP address A.B.C.D match.inner.ip4.dst_ip = BE_IPV4_ADDR(1, 2, 3, 4); match_mask.inner.ip4.dst_ip = BE_IPV4_ADDR(255, 255, 0, 0);
一旦字段定义为常量,就不能按条目更改字段的值。
提示用户应在添加条目时将常量字段设置为零,以提高代码可读性。
可以按如下方式实现更复杂的常量匹配示例
match_mask.outer.tcp.l4_port.dst_port = rte_cpu_to_be_16(0xf0f0); match.outer.tcp.l4_port.dst_port = rte_cpu_to_be_16(0x5020)
以下端口将被匹配
0x5020 - 0x502f
0x5120 - 0x512f
...
0x5f20 - 0x5f2f
可更改字段
以下示例匹配 FTP 或 TELNET 众所周知的端口号,并在修改目标 IP 地址和目标端口号后将数据包转发到服务器。在该示例中,FTP 或 TELNET 都转发到同一服务器。FTP 转发到端口 8000,TELNET 转发到端口 9000。
// at Pipe creation
doca_flow_pipe_cfg_set_name(pipe_cfg, "PORT_MAPPER");
doca_flow_pipe_cfg_set_type(pipe_cfg, DOCA_FLOW_PIPE_BASIC);
match.outer.tcp.l4_port.dst_port = rte_cpu_to_be_16(0xffff); // v
match_mask.outer.tcp.l4_port.dst_port = rte_cpu_to_be_16(0xffff); // M
doca_flow_pipe_cfg_set_match(pipe_cfg, &match, &match_mask);
actions_arr[0] = &actions;
doca_flow_pipe_cfg_set_actions(pipe_cfg, action_arr, NULL, NULL, 1);
doca_flow_pipe_cfg_set_is_root(pipe_cfg, true);
// Adding entries
// FTP
match.outer.tcp.l4_port.dst_port = rte_cpu_to_be_16(20); // E
actions.outer.ip4.src_ip = server_addr;
actions.outer.tcp.l4_port.dst_port = rte_cpu_to_be_16(8000);
result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, &status, entry);
// TELNET
match.outer.tcp.l4_port.dst_port = rte_cpu_to_be_16(23); // E
actions.outer.ip4.src_ip = server_addr;
actions.outer.tcp.l4_port.dst_port = rte_cpu_to_be_16(9000);
result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, &status, entry);
宽松匹配
宽松匹配是 DOCA Flow 中的默认工作模式。宽松模式授予用户对匹配字段的完全控制权,并保证 DOCA Flow 不会隐式添加任何字段。
虽然可以使用管道属性 enable_strict_matching
禁用每个管道的宽松匹配,但请注意,此属性将在未来某个时候被弃用。
宽松匹配和管道设计注意事项
宽松匹配模式为 DOCA 应用程序开发人员提供了对匹配设计的完全控制,而无需 DOCA Flow 库添加隐式匹配逻辑。 这种方法增加了用户的责任,以防止由于数据包布局相似性(例如,UDP 和 TCP 源/目标端口之间)或在匹配报头字段之前跳过报头类型验证而导致的意外副作用。 例如,仅匹配 UDP 目标端口并不会验证 L4 报头的存在或确认 L4 报头是否为 UDP 类型。
为了确保有效的设计,早期管道应分类数据包类型以滤除不需要的数据包。 随着管道的进行,后期阶段可以基于先前的匹配专注于更具体的数据包类型。 示例包括
匹配 VXLAN VNI
对于早期管道,请确保数据包包含 VXLAN 报头(这可以在单个管道中实现)
第一个管道通过将 L4 数据包类型匹配到 UDP 或 L3
next_proto
字段匹配到 UDP 来验证数据包是否具有 UDP 报头第二个管道将 UDP 目标端口匹配到常用的 VXLAN 值 (4789)
对于后期管道,匹配 VXLAN VNI 字段
匹配 UDP 目标端口
对于早期管道,通过将 L4 数据包类型匹配到 UDP 或 L3
next_proto
字段匹配到 UDP 来验证数据包是否包含 UDP 报头对于后期管道,匹配 UDP 目标端口字段
宽松匹配内存占用和性能影响
考虑以下严格匹配模式示例。 有三个管道
基本管道
A
,具有match.outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_TCP
和match.outer.tcp.flags = 1
基本管道
B
,具有match.outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP
和match.outer.udp.l4_port.src_port = 8080
控制管道
C
,具有两个条目,用于将 TCP 流量定向到管道A
,将 UDP 流量定向到管道B
。 第一个条目具有match.outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_TCP
,而第二个条目具有match.outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP
。
因此,硬件对 L4 报头类型进行了两次匹配
当数据包进入控制管道
C
中的过滤器以决定下一个管道时当数据包进入管道
A
或B
的过滤器以匹配 L4 报头字段时
对于特别大的管道,这种双重匹配会降低性能并增加硬件中的内存占用。 宽松匹配模式使用户可以更好地控制匹配逻辑,从而消除隐式添加的匹配,从而减少硬件内存占用并提高性能。
解析器元数据与宽松匹配的用法
当需要匹配特定数据包类型时,解析器元数据匹配特别有用。 在宽松模式下,doca_flow_match
结构体的 outer
、inner
和 tun
部分中的类型选择器仅用于底层联合的类型转换。 报头类型(数据包类型)匹配可以使用 parser_meta
API。
例如,可以通过更改控制管道 C
的匹配(使用相同的 A
和 B
管道)来覆盖上一节中的场景
基本管道
A
,具有match.outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_TCP
和match.outer.tcp.flags = 1
基本管道
B
,具有match.outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP
和match.outer.udp.l4_port.src_port = 8080
控制管道
C
,具有两个条目,用于将 TCP 流量定向到管道A
,将 UDP 流量定向到管道B
。 第一个条目具有match.parser_meta.outer_l4_type = DOCA_FLOW_L4_META_TCP
,而第二个条目具有match.parser_meta.outer_l4_type = DOCA_FLOW_L4_META_UDP
。
因此,硬件仅在数据包进入控制管道的过滤器时执行一次 L4 报头类型匹配。 基本管道的 match.outer.l4_type_ext
仅用于在检查匹配结构时选择 match.outer.tcp
或 match.outer.udp
结构。
示例
以下代码片段用于演示使用宽松匹配重新设计非隧道匹配用例的管道。
以下是重新设计之前的代码
static
void
pipe_match_build(struct
doca_flow_match *match)
{
match->outer.l3_type = DOCA_FLOW_L3_TYPE_IP4;
match->outer.ip4.dst_ip = 0xffffffff;
match->outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP;
match->outer.udp.l4_port.src_port = 22;
}
在禁用宽松匹配(即,enable_strict_matching 属性显式设置为 true
)的情况下,将为上面的代码片段执行以下硬件匹配
L3 报头类型为 IPv4 – 设计中条目之间恒定
L4 报头类型为 UDP – 设计中条目之间恒定
IPv4 目标地址因条目而异
UDP 源端口在条目之间恒定
数据包的其余字段将被忽略
在启用宽松匹配(即,默认模式)的情况下,应考虑以下管道阶段(其中 pipe1
将数据包转发到 pipe2
),以实现与上述类似的匹配
static
void
pipe1_match_build(struct
doca_flow_match *match)
{
// Classifier logic. Only IPv4, UDP packets are to be forwarded to pipe2
match.parser_meta.outer_l3_type = DOCA_FLOW_L3_META_IPV4;
match.parser_meta.outer_l4_type = DOCA_FLOW_L4_META_UDP;
}
static
void
pipe2_match_build(struct
doca_flow_match *match)
{
// Main logic. Match on the specific packet fields
match->outer.l3_type = DOCA_FLOW_L3_TYPE_IP4;
match->outer.ip4.dst_ip = 0xffffffff;
match->outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP;
match->outer.udp.l4_port.src_port = 22;
}
以下代码片段演示了使用宽松匹配重新设计隧道匹配用例的管道
static
void
pipe1_match_build(struct
doca_flow_match *match)
{
match->outer.l3_type = DOCA_FLOW_L3_TYPE_IP4;
match->outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP;
match->tun.type = DOCA_FLOW_TUN_VXLAN;
match->outer.ip4.dst_ip = 0xffffffff;
match->outer.udp.l4_port.src_port = 0x22;
match->tun.vxlan_tun_id = 0xffffffff;
}
在禁用宽松匹配(即,enable_strict_matching 属性设置为 true
)的情况下,将为上面的代码片段执行以下硬件匹配
L3 类型为 IPv4 – 根据设计在条目之间是常量
L4 类型为 UDP – 根据设计在条目之间是常量
隧道类型为
DOCA_FLOW_TUN_VXLAN
– 根据设计在条目之间是常量IPv4 目标地址因条目而异
UDP 源端口始终为 22
VXLAN 隧道 ID 因条目而异
数据包的其余字段将被忽略
在启用宽松匹配(即,默认模式)的情况下,应考虑以下管道阶段(其中 pipe1
将数据包转发到 pipe2
),以实现与上述类似的匹配
static
void
pipe1_match_build(struct
doca_flow_match *match)
{
// Classifier logic. Only IPv4, UDP packets are to be forwarded to pipe2
match.parser_meta.outer_l3_type = DOCA_FLOW_L3_META_IPV4;
match.parser_meta.outer_l4_type = DOCA_FLOW_L4_META_UDP;
}
static
void
pipe2_match_build(struct
doca_flow_match *match)
{
// Main logic. Match on the specific packet fields
match->outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP;
match->outer.udp.l4_port.src_port = 22;
match->outer.udp.l4_port.dst_port = DOCA_VXLAN_DEFAULT_PORT;
match->outer.l3_type = DOCA_FLOW_L3_TYPE_IP4;
match->outer.ip4.dst_ip = 0xffffffff;
match->tun.type = DOCA_FLOW_TUN_VXLAN;
match->tun.vxlan_tun_id = 0xffffffff;
}
宽松匹配注意事项
使用宽松匹配时,outer
、inner
或 tun
结构中的报头类型字段不再指示对特定协议的匹配。 它们仅用作相关报头字段的选择器。 例如,要匹配 outer.ip4.dst_ip
,用户必须设置 outer.l3_type = DOCA_FLOW_L3_TYPE_IP4
。 通过此匹配,将检查 L3 报头的 IPv4 目标地址,但是不检查 L3 报头是否为 IPv4 类型。 用户有责任确保到达此类过滤器的数据包确实具有 IPv4 类型的 L3 报头。
要匹配特定协议/隧道类型,请考虑以下事项
要匹配内部/外部 L3/L4 协议类型,用户可以使用相关的
doca_flow_parser_meta
字段,如上所述。 例如,对于外部协议,可以使用parser_meta.outer_l[3,4]_type
字段。要匹配特定的隧道类型,用户应根据其规范匹配隧道。 例如,对于 VXLAN 隧道,可以使用 UDP 目标端口 4789 上的匹配。 另一种选择是使用 L3 下一个协议字段。 例如,对于下一个报头为 GRE 的 IPv4,可以匹配 IPv4 报头的下一个协议字段值以匹配 GRE IP 协议号 47。
有关更宽松的匹配设计最佳实践,请参阅 Flow Drop、Flow VXLAN Encap 和 LPM with Exact Match Logic 示例。
使用宽松匹配,要实现全匹配功能,可以在管道创建期间使用以下方法之一
将
match_mask
结构设置为 NULL,并将匹配结构设置为全零将
match_mask
结构设置为全零,同时匹配结构具有任何设置
使用宽松匹配,如果任何选择器在使用时未设置相关字段,则管道/条目创建将失败,并显示以下错误消息
failed building active opcode - active opcode <opcode number> is protocol only
设置管道操作
管道执行顺序
设置操作时,它们按以下顺序执行
加密(解密)
解封装
弹出
元数据
外部
隧道
推送
封装
加密(加密)
应避免在同时将一个字段用作其他修改的源时修改该字段,因为无法保证修改操作的顺序。
自动修改
与设置管道匹配类似,操作也具有模板定义。
与创建阶段的 doca_flow_match
类似,仅定义应为每个数据包执行的操作子集。 这以类似于匹配的方式完成,即通过将 doca_flow_match
的字段分类为以下之一
忽略字段 – 字段归零,不使用修改。
常量字段 – 当必须为每个数据包修改字段时,但所有数据包的值都相同时,可以使用操作定义的一次性值
可变字段 – 可能有多个可能值的字段,确切值由用户为每个条目设置
actions.outer.ip4.dst_ip = 0xffffffff
注意如果用户想要将此字段配置为 0,则应将
action_mask
设置为0xffffffff
,将 action 设置为 0。
显式修改类型
可以使用操作掩码强制常量修改或每个条目的修改。 例如
static
void
create_constant_modify_actions(struct doca_flow_actions *actions,
struct doca_flow_actions *actions_mask,
struct doca_flow_action_descs *descs)
{
actions->outer.l4_type_ext = DOCA_FLOW_L4_TYPE_EXT_UDP;
actions->outer.udp.src_port = 0x1234
;
actions_mask->outer.udp.src_port = 0xffff
;
}
复制字段
操作描述符可用于在数据包字段和元数据之间复制。 例如
#define META_U32_BIT_OFFSET(idx) (offsetof(struct doca_flow_meta, u32[(idx)]) << 3
)
static
void
create_copy_packet_to_meta_actions(struct doca_flow_match *match,
struct doca_flow_action_desc *desc)
{
desc->type = DOCA_FLOW_ACTION_COPY;
desc->field_op.src.field_string = "outer.ipv4.src_ip"
;
desc->field_op.src.bit_offset = 0
;
desc->field_op.dst.field_string = "meta.data"
;
desc->field_op.dst.bit_offset = META_U32_BIT_OFFSET(1
); /* Bit offset of meta.u32[1] */
;
}
多个操作列表
可以使用多个操作列表创建管道。 例如
static
void
create_multi_actions_for_pipe_cfg()
{
struct doca_flow_actions *actions_arr[2
];
struct doca_flow_actions actions_0 = {0
}, actions_1 = {0
};
struct doca_flow_pipe_cfg *pipe_cfg;
/* input configurations for actions_0 and actions_1 */
actions_arr[0
] = &actions_0;
actions_arr[1
] = &actions_1;
doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, 2
);
}
操作类型摘要
管道创建 | 条目创建 | 行为 | |||
action_desc | 管道操作 | 管道操作掩码 | 条目操作 | ||
doca_flow_action_type | 配置 | ||||
| 无特定配置 |
|
| 不适用 | 字段被忽略,无修改 |
|
| 不适用 | 将 | ||
|
| 不适用 | 将 | ||
|
| 不适用 | 将 | ||
|
| 为每个条目定义 | 应用条目的 | ||
添加字段值或来自 | 仅定义 |
| 不适用 | 不适用 | 将此 |
| 不适用 | 为每个条目定义 | 应用条目的 | ||
定义 | 定义源字段和目标字段。
| 不适用 | 不适用 | 将来自 | |
将字段复制到另一个字段 | 不适用 | 定义源字段和目标字段。
| 不适用 | 不适用 | 在所有条目的字段之间复制数据 |
设置管道监控
如果应使用计量策略器,则可以对管道上的所有策略器使用相同的配置,也可以对每个条目使用特定的配置。 计量策略器由 FWD 操作确定。 如果条目具有 NULL FWD 操作,则策略器 FWD 操作取自管道。
如果应使用镜像,则镜像可以在管道上共享,或者配置为每个条目具有特定值。
监视器还包括老化配置,如果设置了老化时间,则如果超时过去而没有任何条目匹配,则此条目将老化。
例如
static void build_entry_monitor(struct doca_flow_monitor *monitor, void *user_ctx)
{
monitor->aging_sec = 10;
}
有关更多信息,请参阅 管道条目老化查询。
设置管道转发
FWD(转发)操作是管道中的最后一个操作,它指示数据包的下一个去向。 用户可以配置以下目标之一
发送到软件 (representor)
发送到线缆
跳转到下一个管道
丢弃数据包
FORWARDING 操作可以在管道创建时设置,但也可以是每个条目唯一的。
管道转发可以在创建时设置,也可以延迟到条目添加时设置
如果
fwd.type
类型不是DOCA_FLOW_FWD_CHANGEABLE
,则管道上任何条目上的任何匹配项都将转发到指定的目标如果
fwd.type
类型是DOCA_FLOW_FWD_CHANGEABLE
,则目标将匹配特定条目的fwd.type
字段中定义的内容
将此逻辑放在表格中如下所示
管道 Fwd.type | 条目 Fwd.type | 实际转发 | 注释 |
等于 | X | X | X 不得等于 |
X != | 不在乎 | X |
当管道包含计量监视器 <cir, cbs>
时,它必须同时定义 fwd
和策略器。
如果使用专用常量镜像和 FWD 创建管道,则管道 FWD 可以来自镜像 FWD 或管道 FWD,并且两个 FWD 是互斥的。 不允许将具有 FWD 的镜像指定给也具有 FWD 的管道。
如果未配置镜像 FWD,则 FWD 来自管道配置。 带有镜像的管道的 FWD 不能是直接 RSS,仅允许来自 NULL FWD 的共享 RSS。
以下是 RSS 转发示例
fwd.type = DOCA_FLOW_FWD_RSS;
fwd.rss_type = DOCA_FLOW_RESOURCE_TYPE_NON_SHARED;
fwd.rss.queues_array = queues;
fwd.rss.outer_flags = DOCA_FLOW_RSS_IPV4 | DOCA_FLOW_RSS_UDP;
fwd.rss.nr_queues = 4;
队列指向包含队列号的 uint16_t
数组。 当端口启动时,定义队列的数量,从零开始到队列数量减 1。 RSS 队列号可以包含这些预定义队列号的任何子集。 对于特定的匹配,可以通过具有单个队列的 RSS 转发将数据包定向到单个队列。
支持可变 RSS 转发。 创建管道时,num_of_queues
必须设置为 0xffffffff
,然后在添加每个条目时可以设置不同的转发 RSS 信息。
fwd->num_of_queues = 0xffffffff;
数据包被定向到端口。 在许多情况下,整个管道都在硬件中执行,包括将数据包转发回线缆。 数据包永远不会到达软件。
转发到端口的示例代码
struct doca_flow_fwd *fwd = malloc(sizeof(struct doca_flow_fwd));
memset(fwd, 0, sizeof(struct doca_flow_fwd));
fwd->type = DOCA_FLOW_FWD_PORT;
fwd->port_id = port_id; // this should the same port_id that was set in doca_flow_port_cfg_set_devargs()
转发类型为 DOCA_FLOW_FWD_PORT
,唯一需要的数据是在 DOCA_FLOW_PORT
中定义的 port_id
。
也支持可变端口转发。 创建管道时,port_id
必须设置为 0xffff
,然后在添加每个条目时可以设置不同的转发 port_id
值。
fwd->port_id = 0xffff;
共享资源
DOCA Flow 支持多种可以共享的资源类型。 支持的资源类型可以是
计量器
计数器
RSS 队列
镜像
PSP
封装
解封装
IPsec SA
共享资源可以被多个管道使用,并且可以节省设备和内存资源,同时提高性能。
要创建和配置共享资源,用户应执行以下小节中详述的步骤。
创建共享资源配置对象
调用 doca_flow_cfg_create(&flow_cfg)
,传递指向 struct doca_flow_cfg
的指针,用于填充共享资源所需的参数。
struct doca_flow_cfg
对象用于配置除上述共享资源之外的其他资源,但本节仅指共享资源的配置。
设置每种共享资源类型的共享资源数量
可以通过调用 doca_flow_cfg_set_nr_shared_resource()
来完成。 有关配置过程的详细信息,请参阅 API 文档。
通过调用 doca_flow_init()
完成配置。
配置共享资源
分配共享资源后,将为其分配从 0 开始并递增的标识符。 例如,如果用户配置了两个共享计数器,则它们将带有标识符 0 和 1。
请注意,每个资源都有自己的标识符空间。 因此,如果用户有两个共享计数器和三个计量器,则它们将分别带有标识符 0..1 和 0..2。
配置共享资源需要用户调用 doca_flow_shared_resource_set_cfg()
。
绑定共享资源
必须通过调用 doca_flow_shared_resources_bind()
来绑定共享资源,这会将资源绑定到指针。 资源绑定到的对象通常是 struct doca_flow_port
指针。
使用共享资源
配置资源后,可以通过引用其 ID 来使用它。
对于计量器、计数器和镜像,在管道创建或条目添加期间,它们通过 struct doca_flow_monitor
引用。
查询共享资源
可以通过调用 doca_flow_shared_resources_query()
来完成查询共享资源。 该函数接受资源类型和资源编号数组,并返回一个 struct doca_flow_shared_resource_result
数组,其中包含结果。
共享计量器资源
共享计量器可用于多个管道条目(仅支持硬件控制模式)。
共享计量器操作使用三种颜色之一标记数据包:绿色、黄色和红色。 然后可以在下一个管道中匹配数据包颜色,并可以采取适当的操作。 例如,标记为红色的数据包通常会被丢弃。 因此,计量器操作的下一个管道可能具有匹配红色并具有 fwd 类型 DOCA_FLOW_FWD_DROP
的条目。
DOCA Flow 支持基于 RFC 的三种标记算法:2697、2698 和 4115。
RFC 2697 – 单速率三色标记器 (srTCM)

CBS(承诺突发大小)是以 CIR(承诺信息速率)授予凭据的存储桶大小。 如果发生 CBS 溢出,凭据将传递到 EBS(超额突发大小)存储桶。 通过计量器的数据包会消耗凭据。 如果数据包未超过 CBS,则标记为绿色;如果数据包超过 CBS 但未超过 EBS,则标记为黄色;否则标记为红色。 数据包在进入计量器时可以具有初始颜色。 预着色的黄色数据包将开始从 EBS 消耗凭据。
RFC 2698 – 双速率三色标记器 (trTCM)

CBS 和 CIR 的定义与 RFC 2697 中相同。 PBS(峰值突发大小)是以 PIR(峰值信息速率)授予凭据的第二个存储桶。 凭据不会从 CBS 存储桶溢出到 PBS 存储桶。 PIR 必须等于或大于 CIR。 消耗 CBS 凭据的数据包也会消耗 PBS 凭据。 如果数据包超过 PIR,则标记为红色。 否则,根据它是否超过 CIR 来标记为黄色或绿色。 数据包在进入计量器时可以具有初始颜色。 预着色的黄色数据包开始从 PBS 消耗凭据。
RFC 4115 – 不依赖峰值速率的 trTCM
EBS 是第二个存储桶,它以 EIR(超额信息速率)授予凭据,并从 CBS 获取溢出的凭据。 有关数据包标记算法,请参阅 RFC 4115。
以下部分介绍了配置和使用共享计量器标记数据包的步骤。
共享 IPsec SA 资源
IPsec 安全关联 (SA) 共享资源用于 IPsec ESP 加密协议。 该资源应从 doca_flow_actions
内的 doca_flow_crypto_actions
结构体中指向。
默认情况下,该资源管理序列号 (SN) 的状态,在加密端递增每个数据包,并在解密端执行防重放保护。 防重放综合征存储在 meta.u32[0]
中。
要在软件中控制 SN,应在 doca_flow_port_start
的配置中为每个端口禁用 sn_offload
(有关详细信息,请参阅 DOCA API 文档)。 禁用 sn_offload
后,将忽略以下字段:sn_offload_type
、win_size
、sn_initial
和 lifetime_threshold
。
当为 IPsec SA 资源调用共享资源查询时,将检索加密资源的当前 SN,并检索解密资源的防重放窗口的下限。 仅当启用 sn_offload
时才能调用查询 IPsec SA。
为了在使用期间保持资源的有效状态,应定期调用 doca_flow_crypto_ipsec_resource_handle
。
共享镜像资源
镜像共享资源用于将数据包克隆到其他管道、vport(仅限交换机模式)、RSS 队列(仅限 VNF 模式)或丢弃。
最大支持的镜像数为 4K。
最大支持的镜像克隆目标为 254。
镜像克隆目标作为 next_pipe
不能与 port
或 rss
类型混合使用。 仅支持克隆目标和原始目标都作为 next_pipe
。
不保存镜像后数据包的寄存器副本。
对于交换机模式,应注意以下几个镜像限制
镜像应克隆到
DOCA_FLOW_DIRECTION_BIDIRECTIONAL
管道不保存镜像后 pkt 的寄存器副本
镜像不应直接克隆到 RSS 管道
仅当将数据包克隆到线缆端口时才支持封装
镜像不得在可调整大小的管道上配置
如果镜像创建失败,用户应检查结果综合征以了解失败详情。
镜像和数据包顺序
为了保持镜像数据包相对于非镜像数据包的顺序,请将第一个镜像目标转发目标设置为等效于非镜像数据包,如下图所示
在 NVIDIA® BlueField®-3、NVIDIA® ConnectX®-7 及更低版本中,当在出口域中使用镜像操作时,由于镜像操作的高延迟,镜像数据包无法保持与非镜像数据包的顺序 。 为了保持顺序,请使用 DOCA_FLOW_FWD_DROP
作为目标转发,如下图所示

共享封装资源
封装共享资源用于封装。 共享封装 ID 表示一种封装配置,可以在多个管道和条目中使用(仅支持硬件控制模式)。
共享封装操作使用配置的隧道信息封装数据包。
共享解封装资源
解封装共享资源用于解封装。 共享解封装 ID 表示一种解封装配置,可以在多个管道和条目中使用(仅支持硬件控制模式)。
共享解封装操作解封装数据包。 当 is_l2 为 false 时,应提供以太网信息。
共享 PSP 资源
PSP 共享资源用于 PSP 加密。 该资源应从 doca_flow_actions
中的 doca_flow_crypto_actions
结构体中指向。
应使用密钥配置资源以加密数据包。 有关解密端密钥处理的参考,请参阅 NVIDIA DOCA 库 API 文档中有关 PSP 密钥生成的信息。
基本管道创建
定义所有参数后,用户应调用 doca_flow_pipe_create
以创建管道。
该函数的返回值是管道的句柄。 向管道添加条目时,应提供此句柄。 如果发生故障,该函数将返回 NULL
,并且如果用户提供,则错误原因和消息将放入错误参数中。
有关哪些字段是可选的并且可以跳过的信息,请参阅 DOCA 库 API。 通常建议在不使用时将可选字段设置为 0。 有关更多信息,请参阅 Miss Pipe 和控制管道。
创建管道后,可以向其中添加新条目。 这些条目绑定到管道,因此当管道被销毁时,管道中的所有条目都将被删除。 有关更多信息,请参阅 管道条目 部分。
管道或条目之间没有优先级。 可以实现优先级的方式是首先匹配最高优先级,如果发生未命中,则跳转到下一个 PIPE。 根上可以有多个 PIPE,只要管道不重叠即可。 如果条目重叠,则根据添加条目的顺序设置优先级。 因此,如果两个管道具有重叠匹配,并且 PIPE1 的优先级高于 PIPE2,则用户应在将所有条目添加到 PIPE2 后再向 PIPE1 添加条目。
管道条目 (doca_flow_pipe_add_entry)
条目是管道内的特定实例。 定义管道时,用户定义匹配标准(要匹配的字段子集)、对匹配的数据包执行的操作类型、监视器以及可选的 FWD 操作。
当用户调用 doca_flow_pipe_add_entry()
以添加条目时,他们应定义在管道的所有条目中不恒定的值。 如果未定义 FWD,则 FWD 也是强制性的。
DOCA Flow 旨在以高效的方式支持并发。 由于预期速率将达到每秒数百万个新条目,因此必须使用与数据路径类似的架构。 每个核心具有唯一的队列 ID 可以使 DOCA 引擎免于锁定数据结构,并支持在使用硬件时使用多个队列。

当调用 doca_flow_pipe_entry
时,每个核心都应使用其自己的专用 pipe_queue
编号。 从不同的核心使用相同的 pipe_queue
会导致竞争条件并产生意外的结果。
应用程序应避免在 doca_flow_entry_process_cb
中添加、删除或更新管道条目。
失败路径
条目插入可能在两个位置失败,add_entry
和 add_entry_cb
。
当
add_entry
失败时,不需要清理。当
add_entry
成功时,将向用户返回句柄。 如果后续的add_entry_cb
失败,则用户有责任通过rm_entry
调用释放句柄。 此rm_entry
调用应返回DOCA_SUCCESS
,并且应使用成功的返回代码调用doca_rm_entry_cb
。
管道条目计数
默认情况下,不添加计数器。 如果在监视器中定义,则为每个条目添加唯一的计数器。
每个条目都具有计数器会影响性能,如果应用程序不需要,则应避免使用。
检索到的统计信息存储在结构体 doca_flow_query
中。
计数器的粒度为 1 秒。
管道条目老化查询
当用户调用 doca_flow_aging_handle()
时,此查询用于获取按微秒时间配额老化的条目。 用户回调由此 API 调用,并带有老化的条目。
由于流的数量可能非常大,因此老化流的查询受到微秒配额的限制。 这意味着它可能会在没有所有流的情况下返回,并且需要用户再次调用它。 当查询遍历所有流时,将完成一个完整周期。
具有多项操作的管道
用户可以为每个管道定义多个操作。 这为用户提供了通过在 struct doca_flow_actions
中提供 action_idx
来指定管道中每个条目的不同操作的选项。 请注意,即使为管道定义了多个操作,处理的任何数据包仍然最多只会执行一个操作。
例如,要创建具有相同匹配字段但不同操作的多个流,用户可以在管道创建期间定义两个操作:Action_0
和 Action_1
。 这些操作分别在管道配置的操作数组中分配了索引 0 和 1。Action_0
包括 modify_mac
,而 Action_1
包括 modify_ip
。 然后,用户可以向管道添加两种类型的条目:第一个条目通过将 struct doca_flow_actions
中的 action_idx
字段设置为 0 来使用 Action_0
,第二个条目通过将 action_idx
设置为 1 来使用 Action_1
。
Miss Pipe 和控制管道
仅允许一个根管道。 如果需要多个,请创建控制管道作为根,并将数据包转发到相关的非根管道。
要在管道之间设置优先级,用户必须使用 miss-pipe。 Miss pipe 允许查找与管道 X 关联的条目,如果找不到匹配项,则跳转到管道 X+1 并对与管道 X+1 关联的条目执行查找。
下图说明了硬件表结构

第一个查找在优先级为 0 的表上执行。 如果未找到任何命中,则跳转到下一个表并执行另一次查找。
在 DOCA Flow 中实现 miss pipe 的方法是在 FWD 中使用 miss pipe。 在结构体 doca_flow_fwd
中,字段 next_pipe
表示在创建管道时,如果配置了 fwd_miss
,则如果数据包与特定管道不匹配,则转向应跳转到 fwd_miss
中的 next_pipe
。
fwd_miss
的类型为 struct doca_flow_fwd
,但它只实现了此结构的两种转发类型
DOCA_FLOW_FWD_PIPE
– 将数据包转发到另一个管道DOCA_FLOW_FWD_DROP
– 丢弃数据包
不支持其他转发类型(例如,转发到端口或发送到 RSS 队列)。
next_pipe
定义为 doca_flow_pipe
,并通过 doca_flow_pipe_create
创建。为了区分 miss_pipe
和通用管道,在 struct doca_flow_pipe_cfg
中引入了 is_root
。如果 is_root
为 true,则表示该管道是数据包到达时执行的根管道。否则,该管道是 next_pipe
。
当 fwd_miss
不为空时,与标准不匹配的数据包将由 next_pipe
处理,该管道在 fwd_miss
中定义。
在 doca_flow_pipe_create
的内部实现中,如果 fwd_miss
不为空且 miss_pipe
的转发操作类型为 DOCA_FLOW_FWD_PIPE
,则会创建一个优先级最低的流,该流始终跳转到 fwd_miss
的 next_pipe
的组。然后,next_pipe
的流可以处理数据包,或者如果 miss_pipe
的转发操作类型为 DOCA_FLOW_FWD_DROP
,则丢弃数据包。
例如,VXLAN 数据包作为 RSS 转发,其他数据包则进行环回。miss_pipe
用于其他数据包(非 VXLAN 数据包),匹配项用于通用以太网数据包。fwd_miss
由 miss_pipe
定义,类型为 DOCA_FLOW_FWD_PIPE
。对于 VXLAN 管道,它通过 doca_flow_create()
创建,并引入了 fwd_miss
。
由于在该示例中,跳转流用于通用以太网数据包,因此某些 VXLAN 数据包可能与之匹配并导致冲突。例如,为 ipA
创建了 VXLAN 流条目。一个带有 ipB
的 VXLAN 数据包进入,没有为 ipB
添加流条目,因此它命中 miss_pipe
并被环回。
引入控制管道来处理冲突。创建控制管道后,用户可以在发生冲突时添加具有不同匹配项、转发和优先级的控制条目。
用户可以通过调用 doca_flow_control_pipe_add_entry()
来添加控制条目。
priority
必须定义为高于最低优先级 (3) 且低于最高优先级 (0)。
其他参数表示 doca_flow_pipe_create
中参数的相同含义。在上面的示例中,为 VXLAN 创建了一个控制条目。带有 ipB
的 VLXAN 数据包命中了控制条目。
doca_flow_pipe_lpm
此 DOCA 版本不支持此功能。它将在 DOCA 3.0 版本中重新启用。
doca_flow_pipe_lpm
使用最长前缀匹配 (LPM) 匹配。LPM 匹配仅限于管道创建时用户提供的 match
的单个字段(例如,外部目标 IP)。每个条目由一个值和一个掩码组成(例如,10.0.0.0/8、10.10.0.0/16 等)。LPM 匹配定义为具有最大匹配位的条目。例如,使用两个条目 10.7.0.0/16 和 10.0.0.0/8,IP 10.1.9.2 匹配 10.0.0.0/8,而 IP 10.7.9.2 匹配 10.7.0.0/16,因为 16 位是最长匹配前缀。
除了最长前缀匹配逻辑外,LPM 还支持 meta.u32
、内部目标 MAC 和 VNI 上的精确匹配 (EM) 逻辑。meta.u32
仅支持索引 1
。可以为 EM 选择这三个字段的任意组合。但是,如果为 LPM 选择内部目标 MAC,则也不应为 EM 选择它。如果为 EM 选择多个字段,则应用逻辑与。对元数据的 EM 支持允许通过在 LPM 之前的管道上将其值复制到 meta.u32[1]
来处理任何单个字段。EM 与 LPM 匹配同时执行(即,逻辑与应用于两种逻辑)。例如,如果 LPM 逻辑存在匹配,但为 EM 选择的字段中的值不完全匹配,则构成 LPM 管道未命中。
要在 LPM 管道中启用 EM 逻辑,需要两个步骤
为 LPM 管道创建提供
match_mask
,其中meta.u32[1]
被完全屏蔽和/或inner.eth.dst_mac
和/或tun.vxlan_tun_id
,同时将match_mask.tun.type
设置为DOCA_FLOW_TUN_VXLAN
。因此,match
参数负责选择 LPM 逻辑的字段,而match_mask
参数负责启用 EM 逻辑。分为两个参数是为了区分哪个字段用于 LPM 逻辑,哪个字段用于 EM 逻辑,当两个字段都可以用于 LPM 时(例如,目标 IP 地址和源 MAC 地址)。对于每个条目,使用
match
结构提供值以执行精确匹配。match_mask
仅用于 LPM 相关掩码,不参与 EM 逻辑。
EM 逻辑允许为同一对 LPM 相关数据插入具有不同元数据的多个条目。关于启用精确匹配的基于 IPv4 的 LPM 逻辑:LPM 管道可以具有 1.1.1.1/32,元数据为 42、555 和 1020。如果具有 1.1.1.1/32 的数据包通过这样的 LPM 管道,则其 meta
值将与 42、555 和 1020 进行比较。
DOCA Flow LPM 管道的操作和 FWD 与基本 DOCA Flow 管道的工作方式相同。
监视器仅支持 LPM 管道中的非共享计数器。
doca_flow_pipe_lpm
插入最大延迟在某些情况下可以以毫秒为单位进行测量,因此最好从控制路径插入。为了获得最佳插入性能,应大批量添加条目。
LPM 管道不能是根管道。您必须创建一个管道作为根管道,并将数据包转发到 LPM 管道。
LPM 管道只能对内部和外部 IP 和 MAC 地址执行 LPM 匹配。
对于监视,LPM 管道仅支持非共享计数器,不支持 doca_flow_monitor
的其他功能。
doca_flow_pipe_acl
此 DOCA 版本不支持此功能。它将在 DOCA 3.0 版本中重新启用。
doca_flow_pipe_acl
使用访问控制列表 (ACL) 匹配。ACL 匹配是 doca_flow_match
的五元组。每个条目都包含一个值和一个掩码(例如,10.0.0.0/8、10.10.0.0/16 等),用于 IP 地址字段、端口范围或端口字段中的特定端口、协议和条目的优先级。
ACL 条目端口配置
掩码端口为 0 ==> 任何端口
掩码端口等于匹配端口 ==> 精确端口。掩码为 0xffff 的端口。
掩码端口 > 匹配端口 ==> 匹配端口用作起始端口,掩码端口用作结束端口
ACL 中不支持监视器操作。DOCA Flow ACL 管道的 FWD 与基本 DOCA Flow 管道的工作方式相同。
ACL 支持以下类型的 FWD
DOCA_FLOW_FWD_PORT
DOCA_FLOW_FWD_PIPE
DOCA_FLOW_FWD_DROP
doca_flow_pipe_lpm
插入最大延迟在某些情况下可以以毫秒为单位进行测量,因此最好从控制路径插入。为了获得最佳插入性能,应大批量添加条目。
ACL 管道可以是根管道。
ACL 管道可以在入口和出口域中。
必须在单个队列上访问 ACL 管道。可以在不同的队列上访问不同的 ACL 管道。
不支持在使用标志 DOCA_FLOW_NO_WAIT
发送条目后向 ACL 管道添加条目。
不支持从 ACL 管道中删除条目。
doca_flow_pipe_ordered_list
此 DOCA 版本不支持此功能。它将在 DOCA 3.0 版本中重新启用。”
doca_flow_pipe_ordered_list
允许用户定义操作的特定顺序并倍增相同类型的操作(即,计数器/计量器和封装/解封装之间的特定排序)。
有序列表管道由一系列操作(即,操作序列)定义。每个条目可以是这些序列之一的实例。一个有序列表管道最多可以包含 8 个不同操作的数组。每个操作数组的最大大小为 4 个元素。将多个操作数组组合在一个有序列表管道中时,可以优化资源分配。
doca_flow_pipe_hash
doca_flow_pipe_hash
允许用户按索引插入条目。索引表示数据包哈希计算。
哈希管道仅在管道创建时获取 doca_flow_match
和掩码。掩码提供用于哈希计算的所有字段。
DOCA Flow 哈希管道的 monitor
、actions
、actions_descs
和 FWD
与基本 DOCA Flow 管道的工作方式相同。
doca_flow_pipe_attr
中的 nb_flows
应为 2 的幂。
硬件 Steering 模式
用户可以通过将 devarg dv_flow_en
设置为 2
来启用硬件 steering 模式。
以下是以硬件 steering 模式运行 DOCA 的示例
.... –a 03:00.0, dv_flow_en=2 –a 03:00.1, dv_flow_en=2....
以下是以软件 steering 模式运行 DOCA 的示例
.... –a 03:00.0 –a 03:00.1 ....
dv_flow_en=2
表示已启用硬件 steering 模式。
在 struct doca_flow_cfg
中,使用 doca_flow_cfg_set_mode_args()
设置 mode_args
表示 DOCA 应用程序。如果设置为 hws
(例如,"vnf,hws"
、"switch,hws"
、"remmote_vnf,hws"
),则启用硬件 steering 模式。
在交换机模式下,应将 fdb_def_rule_en=0,vport_match=1,repr_matching_en=0,dv_xmeta_en=4
添加到 DPDK PMD devargs,这使得 DOCA Flow 交换机模块接管所有流量。
要通过调用 doca_flow_pipe_add_entry
创建条目,可以将参数标志设置为 DOCA_FLOW_WAIT_FOR_BATCH
或 DOCA_FLOW_NO_WAIT
DOCA_FLOW_WAIT_FOR_BATCH
表示此流条目等待推送到硬件。然后可以一次性推送批处理流。这减少了推送次数并提高了插入速率。DOCA_FLOW_NO_WAIT
表示流条目立即推送到硬件。
参数 usr_ctx
在 struct doca_flow_cfg
中设置的回调中处理。
doca_flow_entries_process
处理此队列中的所有流。在处理完流并返回状态后,将使用状态和 usr_ctx
执行回调。
如果用户未在 doca_flow_cfg
中设置回调,则用户可以使用 doca_flow_entry_get_status
获取状态,以检查流是否已完成卸载。
隔离模式
在非隔离模式(默认)下,任何接收到的数据包(例如,在 RSS 转发之后)都可以由 DOCA 应用程序处理,绕过内核。同样,DOCA 应用程序可以将数据包发送到 NIC,而无需内核了解。这就是为什么默认情况下,当使用正在运行的 DOCA 应用程序 ping 主机时,不会收到任何回复。如果只有特定的数据包类型(例如,DNS 数据包)应由 DOCA 应用程序处理,而其他数据包(例如,ICMP ping)应由内核直接处理,则隔离模式变得相关。
在隔离模式下,与根管道条目匹配的数据包将 steering 到 DOCA 应用程序(与往常一样),而其他数据包则由内核直接接收/发送。
如果您计划创建具有匹配项的管道,然后执行操作/监视器/转发操作,则出于功能/性能考虑,建议根管道条目包括匹配项,然后是下一个管道转发操作。在下一个管道中,可以指定所有计划的匹配项操作/监视器/转发操作。未匹配的数据包由内核接收和发送。
在交换机模式下,DPDK 必须处于 isolated
模式。DOCA Flow 可以处于 isolated
或 non-isolated
模式。
要激活隔离模式,需要两个配置
DOCA 配置:使用
doca_flow_cfg_set_mode_args()
更新字符串成员mode_args
(struct doca_flow_cfg
),它表示 DOCA 应用程序模式,并将“isolated”(以逗号分隔)添加到其他模式参数。例如:doca_flow_cfg_set_mode_args(cfg, "vnf,hws,isolated")
doca_flow_cfg_set_mode_args(cfg, "switch,isolated")
DPDK 配置:将
isolated_mode
设置为 1 (struct application_port_config
)。例如,如果 DPDK 由 API 初始化:dpdk_queues_and_ports_init(struct application_dpdk_config *app_dpdk_config)
。
struct application_dpdk_config app_dpdk_config = {
.port_config = {
.isolated_mode = 1,
.nb_ports = ...
...
},
...
};
管道大小调整
此 DOCA 版本不支持此功能。它将在 DOCA 3.0 版本中重新启用。
迁移到 HWS 提高了性能,因为规则插入是在硬件而不是软件中实现的。但是,此迁移施加了额外的限制,例如需要预先提交管道的大小(规则条目的数量)。对于需要管道大小随时间增长的应用程序,静态大小可能具有挑战性:提交的管道大小太小可能会导致应用程序在规则条目数量超过提交数量时失败,而预先提交过多的规则可能会导致内存过度分配。
这就是管道大小调整派上用场的地方。此功能允许在运行时增加管道大小,并支持新调整大小的管道中的所有条目。
基本管道 和 控制管道 中支持管道大小调整。
增加管道大小
可以按百分比设置拥塞级别 (CONGESTION_PERCENTAGE
)。一旦管道中的条目数超过此值,就会调用回调。例如,对于具有 1000 个条目且 CONGESTION_PERCENTAGE
为 80% 的管道,在添加第 800 个条目后,将调用 CONGESTION_REACHED
回调。
在 CONGESTION_REACHED
回调之后,应用程序应调用管道大小调整 API (resize()
)。以下是在大小调整回调期间的可选回调
关于分配给管道的新条目数的回调
关于较小管道中已存在且现在已分配给调整大小的管道的每个条目的回调
即使在调整大小后,管道指针仍保持不变,供应用程序使用。
在完成将所有条目从小型管道内部传输到调整大小的管道后,将调用 RESIZED
回调。
在 RESIZED
回调之前,将准确收到一次 CONGESTION_REACHED
回调。仅在调用 resize()
并收到带有 RESIZED
回调的完成消息后,才会再次收到另一个 CONGESTION_REACHED
。
回调列表
CONGESTION_REACHED
– 关于管道中更新的条目数(如果管道可调整大小)信息在添加少量条目后以及将条目从小型管道移动到调整大小的管道时,可能会发生接收
CONGESTION_REACHED
回调。应用程序必须始终在接收到CONGESTION_REACHED
回调后调用管道大小调整以处理此类情况。RESIZED
– 在完成大小调整操作后注意调用管道大小调整会立即返回。它启动一个内部进程,该进程稍后以
RESIZED
回调结束。NR_ENTRIES_CHANGED
(可选) – 关于管道中新的最大条目数ENTRY_RELOCATE
(可选) – 关于从小型管道移动到调整大小的管道的每个条目
管道大小调整的操作顺序
在流配置上设置进程回调
struct doca_flow_cfg *flow_cfg; doca_flow_cfg_create(&flow_cfg); doca_flow_cfg_set_cb_pipe_process(flow_cfg, <pipe-process-callback>);
信息这会在适用时通知
OP_CONGESTION_REACHED
和OP_RESIZED
操作。设置以下管道属性配置
struct doca_flow_pipe_cfg *pipe_cfg; doca_flow_pipe_cfg_create(&pipe_cfg, port); doca_flow_pipe_cfg_set_nr_entries(pipe_cfg, <initial-number-of-entries>); doca_flow_pipe_cfg_set_is_resizable(pipe_cfg,
true
); doca_flow_pipe_cfg_set_congestion_level_threshold(pipe_cfg, <CONGESTION_PERCENTAGE>); doca_flow_pipe_cfg_set_user_ctx(pipe_cfg, <pipe-user-context>);开始添加条目
/* Basic pipe */
doca_flow_pipe_add_entry()/* Contorl pipe */
doca_flow_pipe_control_add_entry()一旦管道中的条目数超过拥塞阈值,就会收到
OP_CONGESTION_REACHED
操作回调。标记管道的拥塞阈值事件,并在返回时调用
doca_flow_pipe_resize()
。对于此调用,添加以下参数用于计算新大小的新阈值百分比。
关于新管道大小的回调(可选)
doca_flow_pipe_resize_nr_entries_changed_cb nr_entries_changed_cb
关于要传输到调整大小的管道的条目的回调
doca_flow_pipe_resize_entry_relocate_cb entry_relocation_cb
调用
doca_flow_entries_process()
以触发条目的传输。它与基本管道和控制管道都相关。在此阶段,允许向管道添加新条目。条目直接添加到调整大小的管道,因此不需要传输。
一旦所有条目都传输完毕,就会收到
OP_RESIZED
操作回调。此外,此时可能会再次收到新的OP_CONGESTION_REACHED
操作回调。此时,可以停止为控制管道调用
doca_flow_entries_process()
。对于基本管道,需要额外调用才能完成对doca_flow_pipe_add_entry()
的调用。信息doca_flow_entries_process()
具有以下作用触发条目从较小管道到较大管道的传输(直到收到
OP_RESIZED
回调)先前
add_entries
API 的后续 API(仅与基本管道相关)
环回配置
在交换机模式下,如果在 struct doca_flow_port_cfg
中设置了 dev
(使用 doca_flow_port_cfg_set_dev()
),则会创建一个内部环回,用于直接线对线 FWD。用户可以使用 mode_args
指定环回配置。支持的选项如下
hairpinq_num=[n]
– 环回队列号use_huge_mem
– 确定 Tx 缓冲区是否使用巨页内存lock_rx_mem
– 锁定 Rx 队列内存
拆卸
管道条目拆卸
当条目由用户应用程序终止或老化时,用户应调用条目销毁函数 doca_flow_pipe_rm_entry()
。这将释放管道条目并取消硬件卸载。
管道拆卸
当管道由用户应用程序终止时,用户应调用管道销毁函数 doca_flow_pipe_destroy()
。这将销毁管道和与其匹配的管道条目。
当端口的所有管道都由用户应用程序终止时,用户应调用管道刷新函数 doca_flow_port_pipes_flush()
。这将销毁此端口的所有管道和所有管道条目。
在 doca_flow_pipe_destroy()
执行期间,应用程序必须避免添加/删除条目或检查任何其他管道的老化条目。
端口拆卸
当不再使用端口时,用户应调用端口停止函数 doca_flow_port_stop()
。这将停止 DOCA 端口,禁用流量,销毁端口并释放端口的所有资源。
流拆卸
当不再使用 DOCA Flow 时,用户应调用流销毁函数 doca_flow_destroy()
。这将释放 DOCA Flow 使用的所有资源。
整个管道中都存在一个暂存区,其最大大小为 DOCA_FLOW_META_MAX
字节。
用户可以设置元数据值,从数据包字段复制,然后在后续管道中匹配。匹配和修改操作都支持掩码。
用户可以根据其操作的 掩码 或描述符 以不同的方式修改元数据
ADD
– 从管道操作或特定条目的操作设置元数据暂存值。宽度由描述符指定。COPY
– 从数据包字段(包括元数据暂存区本身)复制元数据暂存值。宽度由描述符指定。
有关 struct doca_flow_meta
的详细信息,请参阅 DOCA API 文档。
某些 DOCA 管道类型(或操作)在暂存区中使用多个字节以供内部使用。因此,如果用户在 PIPE-1 中设置了这些字节并在 PIPE-2 中读取它们,并且在 PIPE-1 和 PIPE-2 之间存在 PIPE-A,PIPE-A 也将这些字节用于内部目的,则这些字节将被 PIPE-A 覆盖。在设计管道树时必须考虑到这一点。
下表列出了暂存区中使用的字节(按管道类型)
管道类型/操作 | 暂存区中使用的字节 |
ordered_list | [0, 1, 2, 3] |
LPM | [0, 1, 2, 3] |
LPM EM | [0, 1, 2, 3, 4, 5, 6, 7] |
Mirror | [0, 1, 2, 3] |
ACL | [0, 1, 2, 3, 4, 5, 6, 7, 8 ,9, 10, 11, 12, 13, 14, 15] |
从入口到出口的 Fwd | [0, 1, 2, 3] |
IPsec | [0, 1, 2, 3, 4, 5, 6, 7] |
METER COLOR | [24] |
在存在未定义管道的端口,或者定义了管道但没有任何条目的情况下,默认行为是所有数据包都到达软件中的端口。

一旦将条目添加到管道,如果数据包没有匹配项,则它将继续到达软件中的端口。如果匹配,则执行管道中定义的规则。

如果数据包在 RSS 中转发,则根据 RSS 定义将数据包转发到软件。如果数据包转发到端口,则将数据包重定向回线路。如果数据包转发到下一个管道,则软件会尝试将其与下一个管道匹配。
请注意,管道的数量会影响性能。数据包经过的匹配项和操作越多,硬件处理所需的时间就越长。当条目数量非常多时,硬件必须访问主内存以检索条目上下文,这会增加延迟。
DOCA Flow 支持 DOCA Flow 应用程序的跟踪和调试,这可以收集预定义的内部关键绩效指标 (KPI) 和管道可视化。
安装
DOCA 的 SDK 开发包集还包括一个面向开发人员的包,其中包括未包含在生产库中的其他跟踪和调试功能
.deb
基于系统的系统 –libdoca-sdk-flow-trace
.rpm
基于系统的系统 –doca-sdk-flow-trace
这些软件包将跟踪版本的库安装在以下目录下
.deb
基于系统的系统 –/opt/mellanox/doca/lib/<arch>/trace
.rpm
基于系统的系统 –/opt/mellanox/doca/lib64/trace
使用跟踪库
运行时链接
跟踪库旨在允许用户将其现有(生产)程序链接到跟踪库,而无需重新编译程序。为此,只需更新匹配的环境变量,以便 OS 将优先从上述跟踪目录加载库。
以下是 Ubuntu 22.04 BlueField 映像的此类更新示例
LD_LIBRARY_PATH=/opt/mellanox/doca/lib/aarch64-linux-gnu/trace:${LD_LIBRARY_PATH} doca_ipsec_security_gw <program parameters>
编译
上一节中的跟踪级别开发包提供了额外的编译定义 (doca-flow-trace.pc
),这些定义除了 DOCA Flow SDK 库的常规编译定义 (doca-flow.pc
) 外还可以使用。建议在以下情况下使用这些编译定义
将跟踪级别的 DOCA Flow 库静态链接到您的程序中
在开发和测试期间,将跟踪级别的 DOCA Flow 库定期(动态)链接到您的程序中
虽然后者也可以在运行时确定(如上一节所述),但许多开发人员发现直接针对初始开发阶段的跟踪版本进行编译很方便。
跟踪功能
DOCA 日志 – 跟踪级别
DOCA 的跟踪日志级别 (DOCA_LOG_LEVEL_TRACE
) 作为此跟踪版本的库的一部分进行编译。也就是说,针对该库编译的任何程序都可以通过 DOCA 的 API 甚至通过 DOCA 的内置参数解析 (ARGP) 库激活此额外的日志级别
LD_LIBRARY_PATH=/opt/mellanox/doca/lib/aarch64-linux-gnu/trace:${LD_LIBRARY_PATH} doca_ipsec_security_gw <program parameters> --sdk-log-level 70
DOCA 流 – 附加健全性检查
当使用跟踪版本的库时,会添加额外的输入清理检查,但代价是会引入轻微的性能影响。这些检查旨在帮助开发人员在他们使用库的早期步骤中,因为它们为常见的编码错误提供早期检测和改进的日志记录。
本节提供基于 BlueField 的 DOCA Flow 示例实现。
本节中描述的所有 DOCA 示例均受 BSD-3 软件许可协议管辖。
示例先决条件
基于 DOCA Flow 的程序可以在主机或 BlueField 上运行。
基于流的程序需要分配巨页,因此需要以下命令
$ echo '1024' | sudo tee -a /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
$ sudo mkdir /mnt/huge
$ sudo mount -t hugetlbfs -o pagesize=2M nodev /mnt/huge
运行示例
请参阅以下文档
Linux 版 DOCA 安装指南,了解如何安装 BlueField 相关软件的详细信息。
DOCA 故障排除,了解您在 DOCA 示例的安装、编译或执行中可能遇到的任何问题。
要构建给定的示例
cd /opt/mellanox/doca/samples/doca_flow/<sample_name> meson /tmp/build ninja -C /tmp/build
注意二进制文件
doca_<sample_name>
将在/tmp/build/
下创建。示例(例如,
flow_aging
)用法Usage: doca_flow_aging [DPDK Flags] –- [DOCA Flags] DOCA Flags: -h, --help Print a help synopsis -v, --version Print program version information -l, --log-level Set the (numeric) log level
for
the program <10
=DISABLE,20
=CRITICAL,30
=ERROR,40
=WARNING,50
=INFO,60
=DEBUG,70
=TRACE> --sdk-log-level Set the SDK (numeric) log levelfor
the program <10
=DISABLE,20
=CRITICAL,30
=ERROR,40
=WARNING,50
=INFO,60
=DEBUG,70
=TRACE> -j, --json <path> Parse all command flags from an input json file有关每个示例的更多信息,请在
--
分隔符后使用-h
选项/tmp/build/doca_<sample_name> -- -h
DOCA Flow 示例基于 DPDK 库。因此,用户需要提供 DPDK 标志。以下是在 DPU 上执行的示例
使用“vnf”模式运行示例的 CLI 示例
/tmp/build/doca_<sample_name> -a auxiliary:mlx5_core.sf.2 -a auxiliary:mlx5_core.sf.3 -- -l 60
使用
vnf,hws
模式运行 VNF 示例的 CLI 示例/tmp/build/doca_<sample_name> -a auxiliary:mlx5_core.sf.2,dv_flow_en=2 -a auxiliary:mlx5_core.sf.3,dv_flow_en=2 -- -l 60
使用
switch,hws
模式运行交换机示例的 CLI 示例/tmp/build/doca_<sample_name> -- -p 03:00.0 -r sf[2-3] -l 60
注意在 BlueField 上以
switch,hws
模式运行时,无需配置 OVS。DOCA 交换机示例使用简单的
-p
和-r
隐藏了额外的fdb_def_rule_en=0,vport_match=1,repr_matching_en=0,dv_xmeta_en=4
DPDK devargs,以指定 PCIe ID 和表示器信息。注意当在 DPU 上使用上述命令运行时,必须根据 BlueField 可扩展功能用户指南 启用子功能。
注意当在主机上运行时,必须根据 DOCA 虚拟功能用户指南 中的说明使用虚拟功能。
示例
流老化
此示例说明了 DOCA Flow 的老化功能的用法。它演示了如何构建管道并添加具有不同老化时间和用户数据的不同条目。
示例逻辑包括
在
doca_flow_cfg
中使用mode_args="vnf,hws"
初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建具有可更改的 5 元组匹配和转发端口操作的管道。
添加 10 个条目,每个条目具有不同的 5 元组匹配、具有不同老化时间(5-60 秒)的监视器,并在监视器中设置用户数据。用户数据将包含端口 ID、条目号和条目指针。
每 5 秒处理一次老化,并在老化后删除每个条目。
运行这些命令,直到所有条目老化。
参考
/opt/mellanox/doca/samples/doca_flow/flow_aging/flow_agingc
/opt/mellanox/doca/samples/doca_flow/flow_aging/flow_aging_main.c
/opt/mellanox/doca/samples/doca_flow/flow_aging/meson.build
流 ACL
此示例说明了如何使用访问控制列表 (ACL) 管道。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个 ACL 管道,该管道匹配可更改的
源 IPv4 地址
目标 IPv4 地址
源端口
目标端口
添加四个示例 5 元组条目
第一个条目具有
源 IPv4 地址上的完整掩码
目标 IPv4 地址上的完整掩码
源端口上的空掩码(任何源端口)
目标端口上的空掩码(任何目标端口)
TCP 协议
优先级 10
操作“拒绝”(丢弃操作)
第二个条目具有
源 IPv4 地址上的完整掩码
目标 IPv4 地址上的完整掩码
源端口上的空掩码(任何源端口)
掩码中设置的值在目标端口上用作端口范围的一部分
匹配中的目标端口用作起始端口
掩码中的目标端口用作结束端口
UDP 协议
优先级 50
操作“允许”(转发端口操作)
第三个条目具有
源 IPv4 地址上的完整掩码
目标 IPv4 地址上的完整掩码
掩码中设置的值在源端口上等于匹配中的源端口。它是精确端口。ACL 使用具有完整掩码的端口。
目标端口上的空掩码(任何目标端口)
TCP 协议
优先级 40
操作“允许”(转发端口操作)
第四个条目具有
源 IPv4 地址上的 24 位掩码
目标 IPv4 地址上的 24 位掩码
掩码中设置的值在源端口上用作端口范围的一部分:匹配中的源端口用作起始端口,掩码中的源端口用作结束端口。
掩码中设置的值在目标端口上等于匹配中的目标端口。它是精确端口。ACL 使用具有完整掩码的端口。
TCP 协议
优先级 20
操作“允许”(转发端口操作)
该示例展示了如何在入口和出口域上运行 ACL 管道。要更改域,请使用全局参数
flow_acl_sample.c
。入口域:ACL 创建为根管道
出口域
构建一个控制管道,其中包含一个条目,该条目转发 IPv4 流量环回端口。
ACL 在环回端口上创建为根管道。
参考
/opt/mellanox/doca/samples/doca_flow/flow_acl/flow_acl_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_acl/flow_acl_main.c
/opt/mellanox/doca/samples/doca_flow/flow_acl/meson.build
流老化
此示例说明了 DOCA Flow 的老化功能的用法。它演示了如何构建管道并添加具有不同老化时间和用户数据的不同条目。
示例逻辑包括
在
doca_flow_cfg
结构体中,使用mode_args="vnf,hws"
初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建具有可更改的 5 元组匹配和转发端口操作的管道。
添加 10 个条目,每个条目具有不同的 5 元组匹配、具有不同老化时间(5-60 秒)的监视器,并在监视器中设置用户数据。用户数据将包含端口 ID、条目号和条目指针。
每 5 秒处理一次老化,并在老化后删除每个条目。
运行这些命令,直到所有条目老化。
参考
/opt/mellanox/doca/samples/doca_flow/flow_aging/flow_aging_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_aging/flow_aging_main.c
/opt/mellanox/doca/samples/doca_flow/flow_aging/meson.build
流控制管道
本示例展示了如何使用 DOCA Flow 控制管道和解封装 (decap) 操作。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建 VXLAN 管道,匹配 VNI 字段,执行解封装操作,解封装操作描述符,并将匹配的数据包转发到第二个端口。
构建 VXLAN-GPE 管道,匹配 VNI、flags 和 next protocol 字段,并将匹配的数据包转发到第二个端口。
构建 GRE 管道,匹配 GRE key 字段,执行解封装和构建 eth 报头操作,解封装操作描述符,并将匹配的数据包转发到第二个端口。
构建 NVGRE 管道,匹配协议为 0x6558,
vs_id
,flow_id
和内部 UDP 源端口字段,并将匹配的数据包转发到第二个端口。此管道的优先级高于 GRE 管道。NVGRE 数据包优先匹配。构建 MPLS 管道,匹配第三个 MPLS 标签字段,执行解封装和构建 eth 报头操作,解封装操作描述符,并将匹配的数据包转发到第二个端口。
构建具有以下条目的控制管道
如果 L4 类型为 UDP 且目标端口为 4789,则转发到 VXLAN 管道
如果 L4 类型为 UDP 且目标端口为 4790,则转发到 VXLAN-GPE 管道
如果 L4 类型为 UDP 且目标端口为 6635,则转发到 MPLS 管道
如果隧道类型和 L4 类型为 GRE,则转发到 GRE 管道
当任何隧道被解封装时,用户有责任在操作中识别它是 L2 隧道还是 L3 隧道。 如果隧道是 L3,则完整的外部层、隧道和内部 L2 层将被移除,并且内部 L3 层将被暴露。 为了保持数据包有效,用户应提供 ETH 报头来封装内部数据包。 例如
actions.decap_type = DOCA_FLOW_RESOURCE_TYPE_NON_SHARED;
actions.decap_cfg.is_l2 = false
;
/* append eth header after decap GRE tunnel */
SET_MAC_ADDR(actions.decap_cfg.eth.src_mac, src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5]);
SET_MAC_ADDR(actions.decap_cfg.eth.dst_mac, dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]);
actions.decap_cfg.eth.type
= DOCA_FLOW_L3_TYPE_IP4;
对于 VXLAN 隧道,由于 VXLAN 是 L2 隧道,用户必须在操作中指明这一点
actions.decap_type = DOCA_FLOW_RESOURCE_TYPE_NON_SHARED;
actions.decap_cfg.is_l2 = true
;
参考
/opt/mellanox/doca/samples/doca_flow/flow_control_pipe/flow_control_pipe_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_control_pipe/flow_control_pipe_main.c
/opt/mellanox/doca/samples/doca_flow/flow_control_pipe/meson.build
流复制到元数据
本示例展示了如何使用 DOCA Flow copy-to-metadata 操作来复制源 MAC 地址,然后对其进行匹配。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示ode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,该管道对
meta_data
进行可更改的匹配,并将匹配的数据包转发到第二个端口。添加一个条目,该条目匹配已复制到元数据的示例源 MAC。
构建一个管道,该管道具有可更改的 5 元组匹配、复制源 MAC 操作和转发到第一个管道。
向管道添加示例 5 元组条目。
参考
/opt/mellanox/doca/samples/doca_flow/flow_copy_to_meta/flow_copy_to_meta_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_copy_to_meta/flow_copy_to_meta_main.c
/opt/mellanox/doca/samples/doca_flow/flow_copy_to_meta/meson.build
流添加到元数据
本示例展示了如何使用 DOCA Flow add-to-metadata 操作来累加源 IPv4 地址,使其加倍到元数据,然后匹配元数据。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,该管道对
meta_data
进行可更改的匹配,并将匹配的数据包转发到第二个端口。添加一个条目,该条目匹配已添加到元数据的示例双倍源 IPv4 地址。
构建一个管道,该管道具有可更改的 5 元组匹配、复制源 IPv4,并将该值再次添加到元数据操作,并转发到第一个管道。
向管道添加示例 5 元组条目。
参考
/opt/mellanox/doca/samples/doca_flow/flow_add_to_meta/flow_add_to_meta_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_add_to_meta/flow_add_to_meta_main.c
/opt/mellanox/doca/samples/doca_flow/flow_add_to_meta/meson.build
Flow Drop
本示例说明了如何构建一个管道,该管道具有 5 元组匹配、转发操作 drop 和转发未命中操作到 hairpin 管道。 该示例还演示了如何将管道信息转储到文件并查询条目。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个 hairpin 管道,该管道具有匹配所有流量并将流量转发到第二个端口的条目。
构建一个管道,该管道具有可更改的 5 元组匹配、转发操作 drop 和未命中转发到 hairpin 管道。 此管道充当根管道。
向 drop 管道添加示例 5 元组条目,并将计数器作为监视器,以便稍后查询该条目。
等待 5 秒并查询 drop 条目(总字节数和总数据包数)。
将管道信息转储到文件。
参考
/opt/mellanox/doca/samples/doca_flow/flow_drop/flow_drop_sample_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_drop/flow_drop_sample_main.c
/opt/mellanox/doca/samples/doca_flow/flow_drop/meson.build
流 ECMP
本示例说明了使用哈希管道的 ECMP 功能。
本示例使用户能够确定 ECMP 分布中包含的端口数量
端口数
n
由 DPDK 设备参数representor=sf[0-m]
确定,其中m=n-1
。使用
n=4
个端口运行此示例的 CLI 示例/tmp/build/doca_flow_ecmp -- -p 03:00.0 -r sf[0-3] -l 60 --sdk-log-level 60
n
应为 2 的幂。最大支持值为n=8
。
示例逻辑包括
根据用户输入,计算 DPDK 创建的 SF representor 的数量 (
n
)。通过在
doca_flow_cfg
结构中指示mode_args="switch,hws"
来初始化 DOCA Flow。启动 DOCA Flow 端口:物理端口和
n
个 SF representor。在交换机端口上
构建哈希管道,该管道表示
match_mask
结构,以基于外部 IPv6 流标签字段计算哈希。向创建的管道添加
n
个条目,每个条目都将数据包转发到不同的端口 representor。
等待 15 秒并查询条目。
打印每个端口的 ECMP 结果(每个端口中的数据包数与总数据包数相关)。
参考
/opt/mellanox/doca/samples/doca_flow/flow_ecmp/flow_ecmp_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_ecmp/flow_ecmp_main.c
/opt/mellanox/doca/samples/doca_flow/flow_ecmp/meson.build
流 ESP
本示例说明了如何以两种方式匹配 ESP 字段
使用
doca_flow_match
结构体精确匹配esp_spi
和esp_en
字段。使用
doca_flow_match_condition
结构体比较匹配esp_en
字段。
此示例支持 ConnectX-7、BlueField-3 及更高版本。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个控制管道,该管道具有匹配
esp_en > 3
的条目(GT 管道)。构建一个控制管道,该管道具有匹配
esp_en < 3
的条目(LT 管道)。构建一个根管道,该管道具有可更改的
next_pipe
FWD 和esp_spi
匹配,以及特定的esp_sn
匹配 + IPv4 和 ESP 存在性(匹配parser_meta
)。向根管道添加示例
esp_spi = 8
条目,该条目转发到 GT 管道(和未命中条件)。向根管道添加示例
esp_spi = 5
条目,该条目转发到 LT 管道(和命中条件)。
参考
/opt/mellanox/doca/samples/doca_flow/flow_esp/flow_esp_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_esp/flow_esp_main.c
/opt/mellanox/doca/samples/doca_flow/flow_esp/meson.build
流转发未命中
本示例说明了如何使用 FWD 未命中查询和更新,无论是否使用未命中计数器。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个复制管道,该管道具有可更改的外部 L3 类型匹配,并将流量转发到第二个端口。
根据外部 L3 类型添加执行不同复制操作的条目
IPv4
– 将 IHL 字段复制到服务类型字段。IPv6
– 将有效负载长度字段复制到流量类别字段。
构建一个管道,该管道具有 IPv4 地址匹配,将流量转发到第二个端口,并将未命中转发到复制管道。
构建一个 IP 选择器管道,该管道具有外部 L3 类型匹配,将 IPv4 流量转发到 IPv4 管道,并将未命中转发到带有未命中计数器的复制管道。
构建一个根管道,该管道具有外部 L3 类型匹配,将 IPv4 和 IPv6 流量转发到 IP 选择器管道,并通过带有未命中计数器的未命中转发来丢弃所有其他流量。
等待 5 秒钟以接收第一批流量。
在每个端口上
使用
doca_flow_query_pipe_miss
API 查询未命中计数器。打印未命中结果。
在每个端口上
构建一个推送管道,该管道推送 VLAN 报头并将流量转发到第二个端口。
使用
doca_flow_pipe_update_miss
API 将 IP 选择器管道和 IPv4 管道的未命中 FWD 管道目标更新为推送管道。
等待 5 秒钟以接收第二批流量,与之前的流量相同。
在每个端口上
再次使用
doca_flow_query_pipe_miss
API 查询未命中计数器。再次打印未命中结果,结果应包括未命中操作更新之前或之后的未命中数据包。
参考
/opt/mellanox/doca/samples/doca_flow/flow_fwd_miss/flow_fwd_miss_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_fwd_miss/flow_fwd_miss_main.c
/opt/mellanox/doca/samples/doca_flow/flow_fwd_miss/meson.build
流转发目标 (DOCA_FLOW_TARGET_KERNEL)
本示例说明了如何使用 DOCA_FLOW_FWD_TARGET
类型的转发,以及 doca_flow_get_target
API 来获取 struct doca_flow_target
的实例。
示例逻辑包括
使用
"vnf,isolated,hws"
初始化 DOCA Flow。初始化两个端口。
通过调用
doca_flow_get_target(DOCA_FLOW_TARGET_KERNEL, &kernel_target);
获取doca_flow_target
的实例。在每个端口上,创建
具有 5 元组匹配的非根基本管道。
如果命中 – 将数据包转发到另一个端口。
如果未命中 – 使用先前步骤中获取的
doca_flow_target
实例将数据包转发到内核进行处理。然后添加一个具有特定 5 元组的单一条目,该条目被命中,其余的转发到内核。
根控制管道,匹配外部 L3 类型为 IPv4。
如果命中 – 将数据包转发到非根管道。
如果未命中 – 丢弃数据包。
添加一个实现所述逻辑的单一条目。
参考
/opt/mellanox/doca/samples/doca_flow/flow_fwd_target/flow_fwd_target_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_fwd_target/flow_fwd_target_main.c
/opt/mellanox/doca/samples/doca_flow/flow_fwd_target/meson.build
流 GENEVE 封装
本示例说明了如何使用 DOCA Flow 操作创建 GENEVE 隧道。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建入口管道,该管道具有可更改的 5 元组匹配、复制到
pkt_meta
操作和转发端口操作。构建出口管道,该管道具有
pkt_meta
匹配和 4 种不同的封装操作无选项的 L2 封装
带选项的 L2 封装
无选项的 L3 封装
带选项的 L3 封装
向管道添加示例 5 元组和封装值条目。
参考
/opt/mellanox/doca/samples/doca_flow/flow_geneve_encap/flow_geneve_encap_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_geneve_encap/flow_geneve_encap_main.c
/opt/mellanox/doca/samples/doca_flow/flow_geneve_encap/meson.build
流 GENEVE 选项
本示例说明了如何准备 GENEVE 选项解析器、匹配配置的选项以及解封装 GENEVE 隧道。
本示例仅适用于 PF。 不支持 VF 和 SF。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建 GENEVE 选项解析器,所有端口的输入相同。
构建匹配管道,该管道具有 GENEVE VNI 和选项匹配,并转发解封装管道。
构建解封装管道,该管道具有更多的 GENEVE 选项匹配和 2 种不同的解封装操作
L2 解封装
带有可更改 mac 地址的 L3 解封装
向管道添加示例 GENEVE 选项和 MAC 地址值条目。
参考
/opt/mellanox/doca/samples/doca_flow/flow_geneve_opt/flow_geneve_opt_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_geneve_opt/flow_geneve_opt_main.c
/opt/mellanox/doca/samples/doca_flow/flow_geneve_opt/meson.build
流 GTP
本示例演示了如何使用 DOCA Flow 处理和修改具有特定 QFI 值的 GTP PSC 数据包。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="vnf"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上创建两个管道
第一个管道
匹配 GTP PSC 数据包。
仅将 GTP PSC 数据包转发到第二个管道。
丢弃所有其他数据包。
第二个管道
匹配 QFI 等于
0x1
的数据包。修改这些数据包,将 QFI 值从
0x1
更改为0x3a
。将修改后的数据包 hairpin 到另一个端口。
丢弃所有其他数据包。
示例结果:只有初始 QFI 值为 0x1
的 GTP PSC 数据包被传输到另一个端口,其 QFI 值已更新为 0x3a
。 所有其他数据包均被丢弃。
参考
/opt/mellanox/doca/samples/doca_flow/flow_gtp/flow_gtp_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_gtp/flow_gtp_main.c
/opt/mellanox/doca/samples/doca_flow/flow_gtp/meson.build
流 GTP 封装
本示例说明了如何使用 DOCA Flow 操作创建 GTP 隧道。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="vnf"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建入口管道,该管道具有 IPv4 匹配和转发端口操作。
构建出口管道,该管道具有 GTP 封装操作。
gtp_teid
、gtp_ext_psc_qfi
、eth 和 IPv4 字段是可更改的。向管道添加示例封装值条目。
参考
/opt/mellanox/doca/samples/doca_flow/flow_gtp_encap/flow_gtp_encap_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_gtp_encap/flow_gtp_encap_main.c
/opt/mellanox/doca/samples/doca_flow/flow_gtp_encap/meson.build
流环回 VNF
本示例说明了如何构建具有 5 元组匹配的管道,以及如何将数据包转发到另一个端口。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,该管道具有可更改的 5 元组匹配和转发端口操作。
向管道添加示例 5 元组条目。
参考
/opt/mellanox/doca/samples/doca_flow/flow_hairpin_vnf/flow_hairpin_vnf_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_hairpin_vnf/flow_hairpin_vnf_main.c
/opt/mellanox/doca/samples/doca_flow/flow_hairpin_vnf/meson.build
Flow Switch to Wire
本示例说明了如何构建具有 5 元组匹配的管道,并将数据包从线路转发回线路。
本示例展示了如何在交换机和硬件转向 (HWS) 模式下构建基本管道。 每个管道包含两个条目,每个条目都将匹配的数据包转发到两个不同的 representor。
本示例还演示了如何使用 doca_flow_port_switch_get()
获取给定端口的交换机端口。
此测试需要一个 PF 和三个 representor(VF 或 SF)。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="switch,hws"
来初始化 DOCA Flow。使用
struct doca_flow_port_cfg
中的doca_dev
启动 DOCA Flow 端口。在交换机的 PF 端口上
构建入口、出口、vport 和 RSS 管道,这些管道具有可更改的 5 元组匹配和转发端口操作。
向管道添加示例 5 元组条目。
匹配的流量将到达其目标端口,未命中的流量由
rx_tx
函数处理,并根据协议发送到专用端口。入口管道
Entry
0
: IP src1.2
.3.4
/ TCP src1234
dst80
-> egress pipe Entry1
: IP src1.2
.3.5
/ TCP src1234
dst80
-> vport pipe出口管道(测试入口到出口跨域)
Entry
0
: IP dst8.8
.8.8
/ TCP src1234
dst80
-> port0
Entry1
: IP dst8.8
.8.9
/ TCP src1234
dst80
-> port1
Entry2
: IP dst8.8
.8.10
/ TCP src1234
dst80
-> port2
Entry3
: IP dst8.8
.8.11
/ TCP src1234
dst80
-> port3
Vport 管道(测试入口直接到 vport)
Entry
0
: IP dst8.8
.8.8
/ TCP src1234
-> port0
Entry1
: IP dst8.8
.8.9
/ TCP src1234
-> port1
Entry2
: IP dst8.8
.8.10
/ TCP src1234
-> port2
Entry3
: IP dst8.8
.8.11
/ TCP src1234
-> port3
RSS 管道(测试未命中流量
port_id
获取和目标port_id
设置)Entry
0
: IPv4 / TCP -> port0
Entry0
: IPv4 / UDP -> port1
Entry0
: IPv4 / ICMP -> port2
参考
/opt/mellanox/doca/samples/doca_flow/flow_switch_to_wire/flow_switch_to_wire_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_to_wire/flow_switch_to_wire_main.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_to_wire/meson.build
流哈希管道
本示例说明了如何在硬件转向 (HWS) 模式下构建哈希管道。
哈希管道包含两个条目,每个条目都将“匹配”的数据包转发到两个不同的 SF representor。 对于接收到的每个数据包,哈希管道根据 IPv4 目标地址计算要使用的条目索引。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="switch,hws"
来初始化 DOCA Flow。启动 DOCA Flow 端口:物理端口和两个 SF representor。
在交换机端口上
构建哈希管道,同时指示要在
struct match_mask
中用于计算哈希的字段。向创建的管道添加两个条目,每个条目都将数据包转发到不同的端口 representor。
打印软件计算的哈希结果,消息如下:
"hash value for" for dest ip = 192.168.1.1
。
参考
/opt/mellanox/doca/samples/doca_flow/flow_hash_pipe/flow_hash_pipe_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_hash_pipe/flow_hash_pipe_main.c
/opt/mellanox/doca/samples/doca_flow/flow_hash_pipe/meson.build
流 IPv6 流标签
本示例展示了如何在封装后使用 DOCA Flow 操作更新 IPv6 流标签字段。
作为副作用,它还展示了 IPv6 + MPLS 封装的示例。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个入口管道,该管道具有可更改的 L4 类型和端口匹配,从而更新元数据并进入对等端口。
向管道添加示例 UDP/TCP 类型和端口以及元数据值条目。 此管道与 L3 类型无关。
在对等端口上构建一个出口管道,该管道具有可更改的元数据匹配,从而使用 IPv6 + MPLS 报头封装数据包,并进入下一个管道。
向管道添加条目,其中针对不同的元数据值使用不同的封装值。
在对等端口上构建另一个出口管道,该管道具有可更改的 L3 内部类型匹配,从而将值复制到外部 IPv6 流标签字段。
向管道添加两个条目
L3 内部类型为 IPv6 - 将 IPv6 流标签从内部复制到外部。
L3 内部类型为 IPv6 - 从元数据复制外部 IPv6 流标签。
参考
/opt/mellanox/doca/samples/doca_flow/flow_ipv6_flow_label/flow_ipv6_flow_label_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_ipv6_flow_label/flow_ipv6_flow_label_main.c
/opt/mellanox/doca/samples/doca_flow/flow_ipv6_flow_label/meson.build
流环回
本示例说明了如何在 VNF 模式下实现数据包重注入或环回。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个 UDP 管道,该管道匹配可更改的源和目标 IPv4 地址,而转发组件是 RSS 到队列。 匹配时,在此 UDP 管道上设置数据包元数据,该管道称为
RSS_UDP_IP
管道。向
RSS_UDP_IP
管道添加一个条目,该条目匹配具有特定源和目标 IPv4 地址的数据包,并将元数据设置为 10。构建一个 TCP 管道,该管道匹配可更改的 4 元组源和目标 IPv4 和端口地址,而转发组件是 RSS 到队列(此管道称为
RSS_TCP_IP
,它是入口域上的根管道)。向
RSS_TCP_IP
管道添加一个条目,该条目匹配具有特定源和目标端口和 IPv4 地址的数据包。在出口域上,创建环回管道(它是根管道),并匹配 TCP over IPv4,其中包含可更改的 4 元组源和目标端口以及 IPv4 地址,同时使用 VXLAN 隧道封装匹配的数据包,并将目标和源 MAC 地址设置为每个条目都可更改。
向环回管道添加一个条目,其中包含匹配和操作部分的特定值,同时将目标 MAC 地址设置为要将数据包注入到的端口(在本例中,它是数据包到达的入口端口)。
开始接收数据包循环并打印元数据
对于重新注入的数据包,打印的元数据等于 10
否则,打印 0 作为元数据(指示这是第一次遇到该数据包)
参考
/opt/mellanox/doca/samples/doca_flow/flow_loopback/flow_loopback_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_loopback/flow_loopback_main.c
/opt/mellanox/doca/samples/doca_flow/flow_loopback/meson.build
流修改标头
本示例说明了如何使用 DOCA Flow 操作修改特定数据包字段。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上,创建串行管道,如果流量不匹配,则跳转到下一个管道
构建一个管道,该管道具有操作
dec_ttl=true
和可更改的mod_dst_mac
。 该管道匹配具有可更改的目标 IP 的 IPv4 流量,并将匹配的数据包转发到第二个端口。添加一个条目,其中包含示例目标 IP (8.8.8.8) 和
mod_dst_mac
值。
构建一个管道,该管道具有操作可更改的
mod_vxlan_tun_rsvd1
。 该管道匹配具有可更改的 UDP 目标端口和 VXLAN-GPE 隧道 ID 的 IPv4 流量,然后将匹配的数据包转发到第二个端口。添加一个条目,其中包含示例 VXLAN-GPE 隧道 ID (100) 和 UDP 目标端口 (4790),然后是
mod_vxlan_tun_rsvd1
值。
构建一个管道,该管道具有操作可更改的
mod_vxlan_tun_rsvd1
。 该管道匹配具有可更改的 UDP 目标端口和 VXLAN 隧道 ID 的 IPv4 流量,然后将匹配的数据包转发到第二个端口。添加一个条目,其中包含示例 VXLAN 隧道 ID (100) 和 UDP 目标端口 (4789),然后是
mod_vxlan_tun_rsvd1
值。
参考
/opt/mellanox/doca/samples/doca_flow/flow_modify_header/flow_modify_header_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_modify_header/flow_modify_header_main.c
/opt/mellanox/doca/samples/doca_flow/flow_modify_header/meson.build
流监视器计量器
本示例说明了如何使用 DOCA Flow 监视器 meter。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,该管道具有监视器 meter 标志和可更改的 5 元组匹配。 该管道将匹配的数据包转发到第二个端口。
添加一个条目,其中包含示例 CIR 和 CBS 值。
参考
/opt/mellanox/doca/samples/doca_flow/flow_monitor_meter/flow_monitor_meter_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_monitor_meter/flow_monitor_meter_main.c
/opt/mellanox/doca/samples/doca_flow/flow_monitor_meter/meson.build
流多操作
本示例展示了如何在管道中使用 DOCA Flow 操作数组。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,该管道具有可更改的源 IP 匹配,该匹配将匹配的数据包转发到第二个端口,并在操作数组中设置不同的操作
可更改的修改源 MAC 地址
可更改的修改源 IP 地址
向管道添加两个条目,其中包含不同的源 IP 匹配
第一个条目包含示例修改源 MAC 地址。
第二个条目包含修改源 IP 地址。
参考
/opt/mellanox/doca/samples/doca_flow/flow_multi_actions/flow_multi_actions_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_multi_actions/flow_multi_actions_main.c
/opt/mellanox/doca/samples/doca_flow/flow_multi_actions/meson.build
流多转发
本示例展示了如何在管道条目中使用不同的转发。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,该管道具有可更改的源 IP 匹配并在转发中发送 NULL。
向管道添加两个条目,其中包含不同的源 IP 匹配和不同的转发
第一个条目转发到第二个端口
第二个条目丢弃
参考
/opt/mellanox/doca/samples/doca_flow/flow_multi_fwd/flow_multi_fwd_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_multi_fwd/flow_multi_fwd_main.c
/opt/mellanox/doca/samples/doca_flow/flow_multi_fwd/meson.build
流解析器元数据
本示例展示了如何使用来自 3 个系列的 match.parser_meta
的一些字段
IP 分片 – 匹配数据包是否为 IP 分片
完整性位 – 匹配特定协议是否正常(长度、校验和等)
数据包类型 – 匹配特定层数据包类型
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个根管道,该管道具有外部 IP 分片匹配
如果数据包是 IP 分片的 – 将其转发到第二个端口,而无需考虑管道中的下一个管道
如果数据包不是 IP 分片的 – 通过将其转发到完整性管道来继续管道
构建一个“完整性”管道,该管道具有当以下情况发生时继续到下一个管道的单一条目
外部 IPv4 校验和正常
内部 L3 正常(应丢弃不正确的长度)
构建一个“数据包类型”管道,当以下情况发生时,该管道将数据包转发到第二个端口
外部 L3 类型为 IPv4
内部 L4 类型为 TCP 或 UDP
等待 5 秒钟以使流量到达。
参考
/opt/mellanox/doca/samples/doca_flow/flow_parser_meta/flow_parser_meta_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_parser_meta/flow_parser_meta_main.c
/opt/mellanox/doca/samples/doca_flow/flow_parser_meta/meson.build
流随机
本示例展示了如何在 2 种不同的用例中使用 match.parser_meta.random
字段
采样 – 采样一定百分比的流量,而与流内容无关
分配 – 在 8 个不同的队列中分配流量
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个根管道,该管道具有可更改的 5 元组匹配,并根据可更改的源 IP 地址转发到特定的用例管道。
向管道添加两个条目,其中包含不同的源 IP 匹配和不同的转发
第一个条目转发到采样管道。
第二个条目转发到分配管道。
构建一个“采样”管道,该管道具有单一条目并准备该条目以采样 12.5% 的流量。
构建一个“分配”哈希管道,该管道具有 8 个条目并准备这些条目以使每个队列获得 12.5% 的流量。
等待 15 秒钟并查询条目(采样/分配后的总数据包数与之前的总数据包数相关)。
参考
/opt/mellanox/doca/samples/doca_flow/flow_random/flow_random_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_random/flow_random_main.c
/opt/mellanox/doca/samples/doca_flow/flow_random/meson.build
流 RSS ESP
本示例展示了如何根据 ESP SPI 字段使用 DOCA Flow 转发 RSS,并在队列之间分配流量。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,该管道具有 L3 和 L4 类型匹配,将
SPI
字段复制到数据包元数据中,并转发到具有 7 个队列的 RSS。添加一个同时具有 IPv4 和 ESP 存在性匹配的条目。
等待 15 秒钟以使流量到达。
在每个端口上
计算分配到每个端口的流量百分比并打印结果。
打印每个数据包的
SPI
值。 (仅在调试模式下,-l ≥ 60
)
参考
/opt/mellanox/doca/samples/doca_flow/flow_rss_esp/flow_rss_esp_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_rss_esp/flow_rss_esp_main.c
/opt/mellanox/doca/samples/doca_flow/flow_rss_esp/meson.build
流 RSS 元数据
本示例展示了如何使用 DOCA Flow 转发 RSS、设置元数据操作,然后在示例中检索匹配的数据包。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,该管道具有可更改的 5 元组匹配,转发到索引为 0 的 RSS 队列,并设置可更改的数据包元数据。
向管道添加一个条目,其中包含示例 5 元组和元数据值。
从接收队列中检索两个端口上的数据包,并打印数据包元数据值。
参考
/opt/mellanox/doca/samples/doca_flow/flow_rss_meta/flow_rss_meta_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_rss_meta/flow_rss_meta_main.c
/opt/mellanox/doca/samples/doca_flow/flow_rss_meta/meson.build
流采样
本示例展示了如何使用带有 parser_meta.random.value
字段字符串的 doca_flow_match_condition
结构体来采样一定百分比的流量,而与流内容无关。
此示例支持 ConnectX-7/BlueField-3 及更高版本。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="switch,hws"
来初始化 DOCA Flow。启动 DOCA Flow 端口:物理端口和两个 SF representor。
在交换机端口上
构建一个根管道,该管道具有可更改的 5 元组匹配并转发到采样管道。
向管道添加一个包含示例 5 元组的条目。
构建一个“采样”控制管道,该管道具有单一条目。
计算请求的随机值,以获得 35% 的流量。
向管道添加一个包含示例条件随机值的条目。
等待 15 秒钟并查询条目(采样后的总数据包数与之前的总数据包数相关)。
参考
/opt/mellanox/doca/samples/doca_flow/flow_sampling/flow_sampling_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_sampling/flow_sampling_main.c
/opt/mellanox/doca/samples/doca_flow/flow_sampling/meson.build
流设置元数据
本示例展示了如何使用 DOCA Flow set metadata 操作,然后对其进行匹配。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,该管道具有对元数据的可更改匹配,并将匹配的数据包转发到第二个端口。
添加一个匹配示例元数据值的条目。
构建一个管道,该管道具有可更改的 5 元组匹配、可更改的元数据操作和转发到第一个管道。
向管道添加一个包含示例 5 元组和元数据值的条目。
参考
/opt/mellanox/doca/samples/doca_flow/flow_set_meta/flow_set_meta_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_set_meta/flow_set_meta_main.c
/opt/mellanox/doca/samples/doca_flow/flow_set_meta/meson.build
流共享计数器
本示例展示了如何使用 DOCA Flow 共享计数器并查询它以获取计数器统计信息。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
将共享计数器绑定到端口。
构建一个具有可变的 5 元组匹配和 UDP 协议的管道,可变的共享计数器 ID,并将匹配的数据包转发到第二个端口。
添加一个条目,其中包含示例 5 元组匹配和共享计数器,ID 为
port_id
。构建一个具有可变的 5 元组匹配和 TCP 协议的管道,可变的共享计数器 ID,并将匹配的数据包转发到第二个端口。
添加一个条目,其中包含示例 5 元组匹配和共享计数器,ID 为
port_id
。构建具有以下条目的控制管道
如果 L4 类型为 UDP,则将数据包转发到 UDP 管道
如果 L4 类型为 TCP,则将数据包转发到 TCP 管道
等待 5 秒并查询共享计数器(总字节数和总数据包数)。
参考
/opt/mellanox/doca/samples/doca_flow/flow_shared_counter/flow_shared_counter_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_shared_counter/flow_shared_counter_main.c
/opt/mellanox/doca/samples/doca_flow/flow_shared_counter/meson.build
流共享计量器
此示例演示如何使用 DOCA Flow 共享计数器。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
配置具有特定 cir 和 cbs 值的共享计量器。
将共享计量器绑定到端口。
构建一个具有可变的 5 元组匹配和 UDP 协议的管道,可变的共享计量器 ID,并将匹配的数据包转发到第二个端口。
添加一个条目,其中包含示例 5 元组匹配和共享计量器,ID 为
port_id
。构建一个具有可变的 5 元组匹配和 TCP 协议的管道,可变的共享计量器 ID,并将匹配的数据包转发到第二个端口。
添加一个条目,其中包含示例 5 元组匹配和共享计量器,ID 为
port_id
。构建具有以下条目的控制管道
如果 L4 类型为 UDP,则将数据包转发到 UDP 管道
如果 L4 类型为 TCP,则将数据包转发到 TCP 管道
参考
/opt/mellanox/doca/samples/doca_flow/flow_shared_meter/flow_shared_meter_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_shared_meter/flow_shared_meter_main.c
/opt/mellanox/doca/samples/doca_flow/flow_shared_meter/meson.build
流交换机控制管道
此示例演示如何在交换机模式下使用 DOCA Flow 控制管道。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="switch,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建控制管道,以匹配 VNI 字段。
向控制管道添加两个条目,这两个条目都匹配 IPv4 上的 TRANSPORT(UDP 或 TCP 协议),源端口为 80 并转发到另一个端口,其中第一个条目匹配目标端口 1234,第二个条目匹配 12345。
这两个条目都有计数器,因此在成功插入这两个条目后,示例会查询这些计数器以检查每个条目的匹配数据包数。
参考
/opt/mellanox/doca/samples/doca_flow/flow_switch_control_pipe/flow_switch_control_pipe_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_control_pipe/flow_switch_control_pipe_main.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_control_pipe/meson.build
流交换机 – 多个交换机
此示例说明了如何在两个不同的物理功能上同时使用两个交换机。
它演示了如何在交换机和硬件引导 (HWS) 模式下构建基本管道。每个管道包含两个条目,每个条目都将匹配的数据包转发到两个不同的表示器。
本示例还演示了如何使用 doca_flow_port_switch_get()
获取给定端口的交换机端口。
该测试需要两个 PF,每个 PF 上有两个(VF 或 SF)表示器。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="switch,hws"
来初始化 DOCA Flow。启动 DOCA Flow 端口:两个物理端口和每个端口两个表示器(总共六个端口)。
在交换机端口上
构建基本管道,同时指示要使用
struct doca_flow_match match
匹配的字段。向创建的管道添加两个条目,每个条目都将数据包转发到不同的端口 representor。
参考
/opt/mellanox/doca/samples/doca_flow/flow_switch/flow_switch_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_switch/flow_switch_main.c
/opt/mellanox/doca/samples/doca_flow/flow_switch/meson.build
流交换机 – 单个交换机
此示例与之前的示例相同,在 flow switch 示例扩展为利用 DOCA 支持多个并发交换机(每个交换机都基于不同的物理设备)的功能之前。
我们添加此原始版本的原因是,它消除了修改后的 flow switch 版本施加的约束,从而允许在交换机配置中使用任意数量的表示器。
此示例的逻辑与之前的示例相同,但增加了 2 个新管道。
用户 RSS 管道,用于接收错过 TC 规则的数据包(在本例中为内核域)
一个简单的管道,通过使用
DOCA_FLOW_FWD_TARGET
将数据包转发到内核域
在 to_kernel_pipe
中,所有 IPv4 数据包都转发到内核(即,to_kernel_pipe
中的条目 0)。在内核域中,如果没有 TC 规则,则所有 IPv4 数据包都会错过 NIC 域。在 NIC 域中,从 NIC 域错过 IPv4 数据包会转发到慢速路径(即 PF/VF 的表示器)。
根管道
Entry
0
: IP src1.2
.3.4
/ dst8.8
.8.8
/ TCP src1234
dst80
-> port0
Entry1
: IP src1.2
.3.5
/ dst8.8
.8.9
/ TCP src1234
dst80
-> port1
Miss: -> To kernel pipe到内核管道
Entry
0
: IPv4 -> send to kernel IPv6 traffic would be droppedRSS 管道
Entry
0
: IPv4 -> port0
rss queue0
参考
/opt/mellanox/doca/samples/doca_flow/flow_switch_single/flow_switch_single_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_single/flow_switch_single_main.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_single/meson.build
流交换机(方向信息)
此示例说明了如何为驱动程序提供有关基于方向信息进行潜在优化的提示。
此示例需要单个 PF,其中包含两个表示器(VF 或 SF)。
该示例还演示了如何使用 match.parser_meta.port_meta
通过交换机管道检测数据包的来源。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="switch,hws"
来初始化 DOCA Flow。启动 3 个 DOCA Flow 端口,1 个物理端口和 2 个表示器。
在交换机端口上
网络到主机管道
构建基本管道,其中包含可变的
ipv4.next_proto
字段,并通过设置attr.dir_info = DOCA_FLOW_DIRECTION_NETWORK_TO_HOST
来配置具有方向提示的管道。添加两个条目
如果
ipv4.next_proto
为 TCP,则数据包将转发到第一个表示器,即主机。如果
ipv4.next_proto
为 UDP,则数据包将转发到第二个表示器,即主机。
主机到网络管道
构建基本管道,其中匹配
aa:aa:aa:aa:aa:aa
作为源 MAC 地址,并通过设置attr.dir_info = DOCA_FLOW_DIRECTION_HOST_TO_NETWORK
来配置具有方向提示的管道。添加一个条目。如果源 MAC 匹配,则将数据包转发到物理端口(即,网络)。
交换机管道
构建基本管道,其中包含可变的
parser_meta.port_meta
以检测数据包的来源。添加 3 个条目
如果数据包来自端口 0(即,网络),则将其转发到网络到主机管道以决定后续逻辑
如果数据包来自端口 1(即,主机的第一个表示器),则将其转发到主机到网络管道以决定后续逻辑
如果数据包来自端口 2(即,主机的第二个表示器),则将其转发到主机到网络管道以决定后续逻辑
参考
/opt/mellanox/doca/samples/doca_flow/flow_switch_direction_info/flow_switch_direction_info_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_direction_info/flow_switch_direction_info_main.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_direction_info/meson.build
流交换机热升级
此示例演示了如何将端口操作状态机制用于热升级用例。它演示了如何在初始化期间配置端口的状态,以及如何在端口已启动后修改状态。
先决条件
该测试需要两个物理功能 (PF),每个 PF 上有两个(VF 或 SF)表示器。
命令行参数
该示例允许用户使用 --state <value>
参数指定实例的操作状态。相关值包括
0
表示DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
1
表示DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE_READY_TO_SWAP
2
表示DOCA_FLOW_PORT_OPERATION_STATE_STANDBY
示例逻辑
初始化 DOCA Flow
在
doca_flow_cfg
结构中指示mode_args="switch"
。
启动 DOCA Flow 端口
启动两个物理端口和每个端口两个表示器(总共六个端口)。
两个交换机端口都配置了
DOCA_FLOW_PORT_OPERATION_STATE_UNCONNECTED
状态。
配置每个交换机端口
构建基本管道,其中包含外部 L3 类型(特定 IPv4)和外部 L4 类型(可变)的未命中计数器。
向创建的管道添加两个带有计数器的条目,每个条目都将数据包转发到不同的端口表示器。
将端口操作状态从
DOCA_FLOW_PORT_OPERATION_STATE_UNCONNECTED
修改为所需状态。
流量处理
等待流量,直到收到 SIGQUIT 信号 (Ctrl+\)。
在接收流量时,流量统计信息将打印到 stdout。
热升级用例
要说明热升级用例,请按照以下步骤操作
在单独的窗口中使用不同的状态创建两个不同的实例。
注意DPDK 阻止用户创建两个主实例。为避免此限制,请使用
--file-prefix
EAL 参数。“活动”实例的示例
/tmp/build/samples/doca_flow_switch_hot_upgrade -- -p 08:00.0 -p 08:00.1 -r vf[0-1] -r vf[0-1] -l 70
“备用”实例的示例
/tmp/build/samples/doca_flow_switch_hot_upgrade --
file
-prefix standby -- -p 08:00.0 -p 08:00.1 -r vf[0-1] -r vf[0-1] -l 70 --state 2
当接收到流量时,通过键入 Ctrl+\ 关闭活动进程。流量统计信息将开始在备用实例中打印。
重新启动第一个实例。流量统计信息将停止在备用实例中打印,并再次开始在活动实例中打印。
交换用例
当两个实例都在运行时,可以通过键入 Ctrl+C 来演示交换用例
在活动实例中键入 Ctrl+C 会将其状态更改为
DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE_READY_TO_SWAP
在备用实例中键入 Ctrl+C 会将其状态更改为
DOCA_FLOW_PORT_OPERATION_STATE_ACTIVE
再次在活动实例中键入 Ctrl+C 会将其状态更改为
DOCA_FLOW_PORT_OPERATION_STATE_STANDBY
参考
/opt/mellanox/doca/samples/doca_flow/flow_switch_hot_upgrade/flow_switch_hot_upgrade_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_hot_upgrade/flow_switch_hot_upgrade_main.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_hot_upgrade/meson.build
Flow VXLAN 封装
此示例演示如何使用 DOCA Flow 操作创建 VXLAN/VXLANGPE/VXLANGBP 隧道,以及说明如何在同一管道中匹配 TCP 和 UDP 数据包的用法。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建具有可变的 5 元组匹配、封装操作和转发端口操作的管道。
向管道添加示例 5 元组和封装值条目。每个具有相同 5 元组的 TCP 或 UDP over IPv4 数据包都将被匹配和封装。
参考
/opt/mellanox/doca/samples/doca_flow/flow_vxlan_encap/flow_vxlan_encap_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_vxlan_encap/flow_vxlan_encap_main.c
/opt/mellanox/doca/samples/doca_flow/flow_vxlan_encap/meson.build
流共享镜像
此示例演示如何使用 DOCA Flow 共享镜像。
当前的限制不允许使用值为零的共享镜像 ID。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
配置共享镜像,克隆目标 hairpin 到第二个端口。
将共享镜像绑定到端口。
构建一个具有可变的 5 元组匹配和 UDP 协议的管道,可变的共享镜像 ID,并将匹配的数据包转发到第二个端口。
添加一个条目,其中包含示例 5 元组匹配和共享镜像,ID 为
port_id+1
。构建一个具有可变的 5 元组匹配和 TCP 协议的管道,可变的共享镜像 ID,并将匹配的数据包转发到第二个端口。
添加一个条目,其中包含示例 5 元组匹配和共享镜像,ID 为
port_id+1
。构建具有以下条目的控制管道
如果 L4 类型为 UDP,则将数据包转发到 UDP 管道
如果 L4 类型为 TCP,则将数据包转发到 TCP 管道
等待 15 秒以克隆任何传入流量。应该在第二个端口上看到相同的两个数据包(一个来自克隆,另一个来自原始数据包)。
参考
/opt/mellanox/doca/samples/doca_flow/flow_shared_mirror/flow_shared_mirror_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_shared_mirror/flow_shared_mirror_main.c
/opt/mellanox/doca/samples/doca_flow/flow_shared_mirror/meson.build
流匹配比较
此示例演示如何使用 DOCA Flow 匹配比较结果。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
构建一个管道,其中包含对
meta_data[0]
的可变匹配,并将匹配的数据包转发到第二个端口。添加一个条目,该条目匹配
meta_data[0]
等于 TCP 标头长度。构建用于比较目的的控制管道。
向控制管道添加一个条目,以匹配比较结果
meta_data[0]
值大于meta_data[1]
,并将匹配的数据包转发到元数据管道。构建一个管道,其中包含可变的 5 元组匹配,将
ipv4.total_len
复制到meta_data[1]
,并将ipv4.version_ihl << 2
tcp.data_offset << 2
累加到meta_data[1]
,然后转发到第二个管道。向管道添加示例 5 元组条目。
参考
/opt/mellanox/doca/samples/doca_flow/flow_match_comparison/flow_match_comparison_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_match_comparison/flow_match_comparison_main.c
/opt/mellanox/doca/samples/doca_flow/flow_match_comparison/meson.build
流熵
此示例演示如何使用 DOCA Flow 熵计算。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="switch,hws"
来初始化 DOCA Flow。启动一个 DOCA Flow 端口。
使用 5 元组值配置
doca_flow_entropy_format
结构。调用
doca_flow_port_calc_entropy
以获取计算出的熵。记录计算出的熵。
参考
/opt/mellanox/doca/samples/doca_flow/flow_entropy/flow_entropy_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_entropy/flow_entropy_main.c
/opt/mellanox/doca/samples/doca_flow/flow_entropy/meson.build
流 VXLAN 共享封装
此示例演示如何使用 DOCA Flow 操作创建 VXLAN 隧道,以及说明如何在同一管道中匹配 TCP 和 UDP 数据包的用法。
VXLAN 隧道由 shared_resource_encap
创建。
示例逻辑包括
通过在
doca_flow_cfg
结构中指示mode_args="vnf,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
在每个端口上
配置和绑定共享封装资源。封装资源用于 VXLAN 封装。
构建具有可变的 5 元组匹配、
shared_encap_id
和转发端口操作的管道。向管道添加示例 5 元组和封装值条目。每个具有相同 5 元组的 TCP 或 UDP over IPv4 数据包都将被匹配和封装。
参考
/opt/mellanox/doca/samples/doca_flow/flow_vxlan_shared_encap/flow_vxlan_shared_encap_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_vxlan_shared_encap/flow_vxlan_shared_encap_main.c
/opt/mellanox/doca/samples/doca_flow/flow_vxlan_shared_encap/meson.build
流交换机 RSS
此示例演示 DOCA Flow 交换机 RSS 创建,并验证具有共享/立即/内部 hairpin RSS 和数据包处理的交换机 RSS 功能。
DOCA Flow 中仅支持 512 种不同的立即 RSS 操作。
共享 RSS 由 shared_resource_rss
创建。
为了覆盖 MPESW 模式 P0/P1/VF,设计使用 3 个端口。
示例逻辑包括
通过在
doca_flow_cfg
结构体中指示mode_args="switch,hws"
来初始化 DOCA Flow。启动两个 DOCA Flow 端口。
配置和绑定共享资源。
在默认域和出口域中创建共享/立即 RSS 管道,并添加条目以检查域交换机 RSS 创建。
创建转发到端口的管道,并添加条目以检查内部线对线 hairpin。
发送流量以确保所有队列都可以接收流量。
匹配的流量将转到其目标队列或端口,错过的流量由 rx_tx
函数处理,并根据 IP 地址发送到专用队列/端口
默认管道网络到主机
Entry: IP src
1.2
.3.4
dst8.8
.8.8
-> basic pipe constant RSS Entry: IP src1.2
.3.5
dst8.8
.8.8
-> basic pipe changeable immediate RSS Entry: IP src1.2
.3.6
dst8.8
.8.8
-> basic pipe changeable shared RSS Entry: IP src1.2
.3.7
dst8.8
.8.8
-> control pipe immediate RSS Entry: IP src1.2
.3.8
dst8.8
.8.9
-> control pipe shared RSS出口管道
Entry: IP src
1.2
.3.9
dst8.8
.8.8
-> basic pipe constant RSS Entry: IP src1.2
.3.10
dst8.8
.8.8
-> basic pipe changeable immediate RSS Entry: IP src1.2
.3.11
dst8.8
.8.8
-> basic pipe changeable shared RSS Entry: IP src1.2
.3.12
dst8.8
.8.8
-> control pipe immediate RSS Entry: IP src1.2
.3.13
dst8.8
.8.9
-> control pipe shared RSSVport 管道
Entry: IP src
1.2
.3.14
dst8.8
.8.8
-> port0
Entry: IP src1.2
.3.14
dst8.8
.8.9
-> port1
Entry: IP src1.2
.3.14
dst8.8
.8.10
-> port2
参考
/opt/mellanox/doca/samples/doca_flow/flow_switch_rss/flow_switch_rss_main.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_rss/flow_switch_rss_sample.c
/opt/mellanox/doca/samples/doca_flow/flow_switch_rss/meson.build
字段字符串支持的操作
以下是可用于匹配条件和操作执行的所有 API 字段的列表。
字符串字段 | 结构中的路径 | 设置 | 添加 | 复制 | 条件 | ||||
匹配 | 操作 | Dst | Src | Dst | Src | A | B | ||
|
|
| ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
|
|
| ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
| 无。有关详细信息,请参阅“复制哈希结果”部分。 | 不适用 | 不适用 | ✔ | 不适用 | ✔ | ✘ | ✘ | |
|
| 不适用 | 不适用 | ✘ | 不适用 | ✘ | ✘ | ✘ | |
|
| 不适用 | 不适用 | ✘ | 不适用 | ✘ | ✘ | ✘ | |
|
| 不适用 | 不适用 | ✘ | 不适用 | ✘ | ✘ | ✘ | |
|
| 不适用 | 不适用 | ✘ | 不适用 | ✘ | ✔ | ✘ | |
|
| 不适用 | 不适用 | ✘ | 不适用 | ✘ | ✘ | ✘ | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✔ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✔ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✔ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✔ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✔ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✔ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✔ | ✘ | ✘ | ✔ | ✔ | ✘ | ✘ | |
|
| ✔ | ✘ | ✘ | ✔ | ✔ | ✘ | ✘ | |
|
| ✔ | ✘ | ✘ | ✔ | ✔ | ✘ | ✘ | |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✔ | ✔ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
|
|
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ |
| 无。有关详细信息,请参阅“复制 Geneve 选项”部分。 | ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ | |
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ | ||
| ✔ | ✘ | ✔ | ✔ | ✔ | ✘ | ✘ | ||
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✔ | ✘ | ✔ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | |
|
| ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
不可匹配的字段字符串
用户可以修改未包含在 doca_flow_match
结构中的字段。
复制哈希结果
用户可以使用 "parser_meta.hash"
字符串将匹配器哈希计算复制到其他字段。
复制 GENEVE 选项
用户可以使用以下字符串复制 GENEVE 选项类型/类/数据
"tunnel.geneve_opt[i].type"
– 从/向选项类型复制(仅适用于配置了DOCA_FLOW_PARSER_GENEVE_OPT_MODE_MATCHABLE
的选项)。"tunnel.geneve_opt[i].class"
– 从/向选项类复制(仅适用于配置了DOCA_FLOW_PARSER_GENEVE_OPT_MODE_MATCHABLE
的选项)。"tunnel.geneve_opt[i].data"
– 从/向选项数据复制,位偏移量从数据的开头算起。
i
是在 doca_flow_parser_geneve_opt_create
中提供的 tlv_list
数组中选项的索引。