DOCA 文档 v2.10.0

DOCA PSP 网关应用指南

本文档介绍了 NVIDIA DOCA PSP 网关示例应用程序在 NVIDIA® BlueField® 网络平台或 NVIDIA® ConnectX® SmartNIC 之上的用法。

注意

DOCA PSP 网关在 alpha 级别受支持。

注意

DOCA PSP 网关仅在 BlueField-3 或 ConnectX-7 及更高版本上受支持。

DOCA PSP 网关应用程序利用 BlueField 或 ConnectX 硬件功能,使用 PSP 安全协议进行完全卸载的安全网络通信。该应用程序演示了如何在应用程序实例之间交换密钥,并使用 DOCA Flow 库插入规则来控制 PSP 加密和解密。

警告

该应用程序使用未加密的 gRPC 通道交换密钥。如果您的环境需要保护加密密钥,则必须修改应用程序以使用适用的证书创建 gRPC 通道。

信息

PSP 网关应用程序仅支持 PSP 隧道协议。此版本中的应用程序不支持 PSP 传输协议,但底层 DOCA Flow 库支持该协议。

信息

PSP 网关应用程序仅支持 IPv4 内部标头和 IPv6 外部标头。当前版本中的应用程序不支持其他组合,但底层 DOCA Flow 库支持这些组合。

可以将应用程序配置为通过单独的命令行参数或通过命令行参数配置的文本文件来建立出站 PSP 隧道连接。连接默认按需建立,但也可以配置为在启动时连接。

DOCA PSP 网关旨在与三个端口一起运行

  • 安全(加密)上行链路网络设备(即,p0

  • 不安全(明文)网络设备表示 (VF 或 SF)

  • 带外 (OOB) 管理端口,用于使用标准套接字与对等实例通信

无论 DOCA PSP 网关部署到 BlueField 还是 ConnectX 设备,其功能都是相同的。带外 (OOB) 网络设备在对等方之间传输 PSP 参数,上行链路端口传输安全(加密)流量,VF 传输未加密流量。

image-2024-5-17_9-34-57-version-1-modificationdate-1735720060950-api-v2.png

当应用程序部署到 DPU 时,PSP 加密协议的操作对主机完全透明。管理 PSP 连接所需的所有资源都物理位于 DPU 上。

image-2024-5-6_15-33-24-version-1-modificationdate-1735720061180-api-v2.png

当应用程序部署到主机时,PSP 加密协议的操作是主机的责任,资源从主机分配。但是,PSP 加密协议的操作对连接到 VF 网络设备的任何虚拟机和容器完全透明。

PSP 隧道连接的创建需要对等方之间的双向通信。每个“发送者”都必须从预期的“接收者”请求唯一的安全参数索引 (SPI) 和加密密钥。接收者使用 BlueField 或 ConnectX 设备内部的硬件资源派生顺序 SPI 和加密密钥,这些硬件资源管理一对秘密主密钥以生成 SPI 和加密密钥。

PSP 优于类似协议(例如,IPsec)的一个关键架构优势是,每当接收者创建新的 SPI 和加密密钥时,都不会产生任何额外的资源利用率。这是因为与 SPI 关联的解密密钥是根据 SPI 和主密钥,为每个接收到的数据包动态计算的。对于每个额外的解密规则,不需要额外的上下文内存,这在一定程度上是 PSP 协议能够扩展到数千个对等方的原因。

启动时隧道创建 vs. 按需隧道创建

默认操作模式是按需隧道创建。也就是说,当从非安全端口接收到数据包,且流管道没有加密规则时,数据包将丢失到 RSS,CPU 必须在此处决定如何处理数据包。如果数据包中的目标 IP 地址属于已知对等方的虚拟网络,则 CPU 使用 OOB 网络连接上的 gRPC 尝试与对等方进行密钥交换。如果密钥交换成功并且成功创建了新的加密流,则数据包将重新提交到管道,在那里对其进行加密并发送,就像任何后续具有相同目标 IP 地址的数据包一样。

下图说明了虚拟机 V1 打算向虚拟机 V2 发送数据包的此序列(“慢速路径”)。在本例中,V1 托管在物理主机 H1 上,V2 托管在物理主机 H2 上。发送的第一个数据包 (1) 导致丢失 (2),因此数据包被保留 (3),同时在两个方向上交换密钥 (4-8)。然后更新管道 (9),并重新提交原始数据包 (10)。从那里开始,数据包遵循与下面的快速路径相同的逻辑。

image-2024-4-23_14-21-16-version-1-modificationdate-1735720061363-api-v2.png

一旦隧道建立,从 VF 接收到的数据包 (1) 匹配规则 (2) 并被加密和发送 (3-4),而无需 CPU 的任何干预(“快速路径”)。

image-2024-4-23_14-24-13-version-1-modificationdate-1735720061573-api-v2.png

在启动时隧道创建的情况下,应用程序的主线程会重复尝试为命令行上指定的每个对等方执行密钥交换,直到列表完成。每个对等方仅连接一次,如果与一个对等方的连接失败,则循环继续到下一个对等方,并在尝试完所有其他对等方后重试失败的连接。

采样

PSP 网关应用程序支持 PSP 标头中的 sample-at-receiver (S) 位。如果启用了采样,则标有 S 位的数据包将被镜像到 RSS 队列并记录到控制台。此外,在传输时,随机数据包子集(命令行参数 N 为 2^N 分之一)的 S 位设置为 1,并且这些数据包被镜像到 RSS。

为了避免 ROCE 流量中出现乱序指示,可以使用 --maintain-order 标志。使用时,应用程序会为出口采样创建两个镜像资源

  • 一个用于采样位打开时 – 镜像到 RSS

  • 一个用于采样位关闭时 – 镜像,转发类型为丢弃

注意

出口数据包的传输时采样当前仅在加密后支持。在未来的版本中将支持加密前出口数据包的采样。


管道

主机到网络流

从本地非安全端口(主机到网络)发送的未启用采样的数据包将通过管道传输,如下图所示。请注意,入口根管道是来自 VF 或安全上行链路端口的数据包的第一个目的地。但是,出口 ACL 管道是通过 PF 上的 tx_burst 发送的数据包的第一个目的地(在交换机模型的专家模式下)。

空管道是从默认域(在其中创建入口根管道)到安全出口域(出口 ACL 管道在其中执行加密)的残留过渡。

注意

此管道可能会在未来的版本中删除。

image-2024-4-23_14-50-36-version-1-modificationdate-1735720063273-api-v2.png

如果启用了采样,则主机到网络管道将按以下方式修改

image-2024-4-23_15-12-1-version-1-modificationdate-1735720063500-api-v2.png

此处,在出口 ACL 管道和安全端口之间添加了出口采样管道。它执行 random 元数据的匹配,根据命令行参数进行掩码,然后

  • 在匹配时,会发生以下操作

    1. 数据包修改

      1. PSP 标头中的 S 位设置为 true

      2. pkt_meta 字段设置为哨兵值,以向 CPU 软件指示数据包为何发送到 RSS。

    2. 原始数据包转发到 RSS。

    3. 镜像操作将数据包转发到安全端口。

  • 在未匹配时,会发生以下操作

    1. 不进行数据包修改。

    2. 数据包转发到残留管道,然后该管道可以将数据包转发到线路。

      信息

      fwd_miss 无法以端口为目标。

      注意

      此管道可能会在未来的版本中删除。

网络到主机流

当数据包从安全端口到达时,将执行以下流。

image-2024-4-23_15-30-41-version-1-modificationdate-1735720063690-api-v2.png

与之前一样,入口根管道是第一个目的地,此处,也匹配了安全端口 ID 以及 IPv6 外部 L3 类型。匹配的数据包流向解密管道,该管道将外部 UDP 端口号与 PSP 规范中指定的常量 1000 进行匹配。匹配后,数据包将被解密,但尚未解封装。然后,入口 ACL 管道检查以下内容

  • PSP_Syndrome – 数据包是否正确解密并通过了 ICV 检查?

  • PSP SPI 和内部 IP 源地址 – 此数据包是否使用与给定源关联的密钥加密?

如果数据包通过了综合征和 ACL 检查,则将其转发到 VF。否则,综合征统计管道将统计 PSP 综合征字中不同位的出现次数。

启用采样后,入口采样管道将插入到 ACL 之前。与出口采样管道不同,不涉及随机性;匹配条件是 PSP 标头中的接收时采样标志。在匹配时,传入的数据包将镜像到 RSS,其中 pkt_meta 指示将数据包转发到 RSS 的原因。在匹配或未匹配时,下一个管道是入口 ACL 管道。

image-2024-4-23_15-41-2-version-1-modificationdate-1735720063927-api-v2.png

DOCA 库

此应用程序利用以下 DOCA 库

有关更多信息,请参阅它们各自的编程指南。

信息

有关如何安装 BlueField 相关软件的详细信息,请参阅 NVIDIA DOCA Linux 安装指南

DOCA 参考应用程序的安装包含应用程序的源代码以及匹配的编译说明。这允许“按原样”编译应用程序,并提供修改源代码然后编译应用程序新版本的能力。

提示

有关应用程序以及开发和编译技巧的更多信息,请参阅 DOCA 应用程序页面。

应用程序的源代码可以在应用程序的目录下找到:/opt/mellanox/doca/applications/psp_gateway/

先决条件

  • 应用程序依赖于 json-c 开源,需要安装以下内容

    • Ubuntu/Debian

      复制
      已复制!
                  

      $ sudo apt install libjson-c-dev

    • CentOS/RHEL

      复制
      已复制!
                  

      $ sudo yum install json-c-devel

  • 安装 gRPC 开源

    注意

    gRPC 可以从上游软件包安装,也可以直接从源代码构建。由于 gRPC 端的构建更改,如果直接从源代码构建新版本,则还需要以下 DOCA 应用程序构建标志

    复制
    已复制!
                

    $ meson -Dupstream_grpc=false /tmp/build

编译所有应用程序

所有 DOCA 应用程序都在单个 meson 项目下定义。因此,默认情况下,编译包括所有应用程序。

要一起构建所有应用程序,请运行

复制
已复制!
            

cd /opt/mellanox/doca/applications/ meson /tmp/build ninja -C /tmp/build

信息

doca_psp_gateway/tmp/build/psp_gateway/ 下创建。


仅编译当前应用程序

要直接仅构建 PSP 网关应用程序

复制
已复制!
            

cd /opt/mellanox/doca/applications/ meson /tmp/build -Denable_all_applications=false -Denable_psp_gateway=true ninja -C /tmp/build

信息

doca_psp_gateway/tmp/build/psp_gateway/ 下创建。

或者,用户可以在 meson_options.txt 文件中设置所需的标志,而不是在编译命令行中提供它们

  1. 编辑 /opt/mellanox/doca/applications/meson_options.txt 中的以下标志

    • enable_all_applications 设置为 false

    • enable_psp_gateway 设置为 true

  2. 运行以下编译命令

    复制
    已复制!
                

    cd /opt/mellanox/doca/applications/ meson /tmp/build ninja -C /tmp/build

    信息

    doca_psp_gateway/tmp/build/psp_gateway/ 下创建。

故障排除

有关应用程序编译中遇到的任何问题,请参阅 NVIDIA DOCA 故障排除指南

先决条件

PSP 网关应用程序基于 DOCA Flow。因此,用户需要分配巨页

复制
已复制!
            

$ echo '2048' | 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


应用程序执行

PSP 网关应用程序以源代码形式提供。因此,在执行应用程序之前需要进行编译。

  1. 应用程序使用说明

    复制
    已复制!
                

    Usage: doca_psp_gateway [DOCA Flags] [Program 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 level for 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   Program Flags: -p, --pci-addr PCI BDF of the device in BB:DD.F format (required) -r, --repr Device representor list in vf[x-y]pf[x-y] format (required) -m, --core-mask EAL Core Mask --decap-dmac Mac_dst addr of the decapped packets -d, --vf-name Name of the virtual function device / unsecured port -n, --nexthop-dmac Next-hop mac_dst addr of the encapped packets --cookie Enable use of PSP virtualization cookies -a, --disable-ingress-acl Allows any ingress packet that successfully decrypts --sample-rate Sets the log2 sample rate: 0: disabled, 1: 50%, ... 16: 1.5e-3% -x, --max-tunnels Specify the max number of PSP tunnels -o, --crypt-offset Specify the PSP crypt offset --psp-version Specify the PSP version for outgoing connections (0 or 1) -z, --static-tunnels Create tunnels at startup -k, --debug-keys Enable debug keys --stat-print Enable printing statistics --perf-print Enable printing performance metrics (key-gen, insertion, all) --show-rss-rx-packets Show RSS rx packets --outer-ip-type Outer IP type --inner-ip-type Inner IP type -c, --config Path to the JSON file with application configuration --maintain-order Maintain original packet ordering

  2. 此用法打印输出可以使用 -h(或 --help)选项打印到命令行

    复制
    已复制!
                

    ./doca_psp_gateway -h

    信息

    有关更多信息,请参阅“命令行标志”部分。

  3. 在 BlueField 或主机上运行应用程序的 CLI 示例

    复制
    已复制!
                

    ./doca_psp_gateway -p 03:00.0 -r vf0pf0 -d ens2f0v0 -c /tmp/psp_gw_config.json

    • PCIe 地址标识符(-p 标志)应与所需 PCIe 设备的地址匹配

    • -d 标志指示用于提取 MAC 地址和本地 IP 的 vf。它应与 -r 参数指定的虚拟功能的 MAC 地址匹配。

    • -c 标志是 json 配置文件的路径,该文件包含有关隧道的所有信息。

  4. 该应用程序还支持基于 JSON 的部署模式,其中所有命令行参数都通过 JSON 文件提供

    复制
    已复制!
                

    ./doca_psp_gateway --json [json_file]

    例如

    复制
    已复制!
                

    ./doca_psp_gateway --json psp_gateway_params.json

    注意

    执行前,请确保使用的 JSON 文件包含正确的配置参数,尤其是部署所需的 PCIe 地址。

命令行标志

标志类型

短标志

长标志/JSON 键

描述

JSON 内容

通用标志

h

help

打印帮助概要

N/A

v

version

打印程序版本信息

N/A

l

log-level

设置应用程序的日志级别

  • DISABLE=10

  • CRITICAL=20

  • ERROR=30

  • WARNING=40

  • INFO=50

  • DEBUG=60

  • TRACE=70(需要使用 TRACE 日志级别支持进行编译)

复制
已复制!
            

"log-level": 60

N/A

sdk-log-level

设置程序的日志级别

  • DISABLE=10

  • CRITICAL=20

  • ERROR=30

  • WARNING=40

  • INFO=50

  • DEBUG=60

  • TRACE=70

复制
已复制!
            

"sdk-log-level": 40

j

json

从输入 JSON 文件解析所有命令标志

N/A

程序标志

p

pci-addr

设备 PCIe BDF,格式为 BB:DD.F

复制
已复制!
            

"p""03:00.0"

r

repr

设备表示列表,格式为 vf[x-y]pf[x-y]

复制
已复制!
            

"r": "vf0pf0"

m

core-mask

EAL 核心掩码

复制
已复制!
            

"m""0xf"

N/A

decap-dmac

解封装数据包的 mac_dst 地址(不能与 vf-name 一起使用)

复制
已复制!
            

"dcap-dmac": "11:22:33:44:55::66"

N/A

vf-name

VF 设备/非安全端口的名称(仅限主机。自动检测 MAC/VIP。需要绑定到 VF 的 IP 地址。)

复制
已复制!
            

"vf-name": "ens2f0v0"

n

nexthop-dmac

封装数据包的下一跳 mac_dst 地址

复制
已复制!
            

"nexthop-dmac""77:88:99:aa:bb:cc"

N/A

cookie

启用 PSP 虚拟化 Cookie 的使用

复制
已复制!
            

"cookie"true

a

disable-ingress-acl

允许任何成功解密的入口数据包

复制
已复制!
            

"disable-ingress-acl"true

N/A

sample-rate

设置 log2 采样率

  • 0 – 禁用,

  • 1 – 50%,...

  • 16 – 1.5e-3%

复制
已复制!
            

"sample-rate": 16

x

max-tunnels

指定 PSP 隧道的最大数量

复制
已复制!
            

"max-tunnels": 4096

o

crypt-offset

指定 PSP 加密偏移量

复制
已复制!
            

"crypt-offset": 7

N/A

psp-version

为传出连接指定 PSP 版本(01

复制
已复制!
            

"psp-version": 0

z

static-tunnels

使用给定的本地 IP 地址在启动时创建隧道

复制
已复制!
            

"static-tunnels""192.168.1.99"

k

debug-keys

启用调试密钥

复制
已复制!
            

"debug-keys"true

N/A

stat-print

打印有关活动会话的统计信息

复制
已复制!
            

"stat-print": true

N/A

perf-print

打印密钥-SPI 对密钥生成的性能指标 (key-gen) 或插入速率 (insertion) 或两者 (all)

复制
已复制!
            

"perf-print": "all"

N/A

show-rss-rx-packets

打印到达 RSS 队列(即,软件)的 RX 数据包

复制
已复制!
            

"show-rss-rx-packets": false

N/A

outer-ip-type

外部 IP 隧道类型(ipv4ipv6)。如果未指定,则默认为 ipv6

复制
已复制!
            

"outer-ip-type": "ipv4"

N/A

inner-ip-type

内部 IP 隧道类型(ipv4ipv6)。如果未指定,则默认为 ipv4

复制
已复制!
            

"inner-ip-type": "ipv6"

c

config

包含隧道信息的 JSON 文件的路径

信息

有关 JSON 文件格式的详细信息,请参阅“配置文件 JSON 格式”部分。

复制
已复制!
            

"config": "/tmp/psp_gw_config.json"

N/A

maintain-order

强制保持原始数据包顺序

复制
已复制!
            

"maintain-order": true

有关支持的标志和执行模式的更多信息,请参阅 DOCA Arg Parser

配置文件 JSON 格式

JSON 配置文件将 OOB 网络地址 (gRPC 服务器) 映射到该物理地址后面的虚拟 IP 地址列表。列表中的每个“对等方”都包含有关远程 gRPC 服务器的信息,local-vipremote-vip 对映射到该服务器。

以下是 JSON 文件结构的模板

Json 配置

复制
已复制!
            

{ "config": { "local-grpc-address": <local gRPC server ip address to listen for connections on, possible with port> }, "peers": [ /* list of peers (differentiated by remote gRPC server) */ { "remote-grpc-address": <remote gRPC server address to connect to for connections of given sessions> , "sessions": [ /* list of sessions allowed with peer (differentiated by local vip) */ { "local-vip": <local virtual ip>, /* if not present, take the value from vf interface's IP ("--vf-name" flag) */ "remote-vips": [ <ip address, possible with prefix mask>, /* [<more ip addresses>...] */ ] }, /* [<more sessions>... ] */ ] }, /* [<more peers>...] */ ] }

当来自 VF 的数据包与任何现有流不匹配时,此表定义应提供给定(虚拟)源 IP、目标 IP 二元组隧道的物理对等方。

JSON 示例

Json 配置

复制
已复制!
            

{ "config": { "local-grpc-address": "10.237.113.143:3000" }, "peers": [ { "remote-grpc-address": "10.237.113.144", "sessions": [ { "local-vip": "6.6.6.5", "remote-vips": [ "8.8.8.0/24", "7.7.7.7" ] }, { "local-vip": "6.6.6.4", "remote-vips": [ "9.9.9.9" ] } ] }, { "remote-grpc-address": "10.237.1.1", "sessions": [ { // "local vip" not present - default value from vf interface's IP (Must run application with "--vf-name" param) "remote-vips": [ "11.11.11.11/24" ] } ] } ] }


故障排除

有关 DOCA 应用程序的安装或执行中遇到的任何问题,请参阅 NVIDIA DOCA 故障排除指南

  1. 主循环代码流程

    1. 初始化日志记录器工具。

      1. 创建标准日志记录器和 SDK 日志记录器,并选择 SDK 日志记录器默认日志级别。

        复制
        已复制!
                    

        doca_log_backend_create_standard(); doca_log_backend_create_with_file_sdk(stdout, &sdk_log); doca_log_backend_set_sdk_level(sdk_log, DOCA_LOG_LEVEL_WARNING);

      2. 信号处理程序已连接以启用干净的关闭。

        复制
        已复制!
                    

        signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler);

    2. 解析应用程序参数。主函数调用 psp_gw_argp_exec(),它初始化 arg 解析器资源并注册 DOCA 通用参数,然后注册 PSP 应用程序特定参数。然后调用解析器。

      复制
      已复制!
                  

      doca_argp_init(); psp_gw_register_params(); doca_argp_start();

    3. 解析输入配置 JSON 文件。这将包括有关对等方及其会话的所有信息。

      复制
      已复制!
                  

      psp_gw_parse_config_file();

    4. DPDK 初始化。调用 rte_eal_init() 以使用提供的 EAL 标志初始化 EAL 资源,以不探测端口 (-a00:0.0)。

      复制
      已复制!
                  

      rte_eal_init(n_eal_args, (char **)eal_args);

    5. 初始化设备和端口。

      1. 使用输入的 PCIe 地址/接口名称打开 DOCA 设备。

      2. 从每个打开的设备探测 DPDK 端口。

        复制
        已复制!
                    

        open_doca_device_with_pci(...); // not part of doca_flow; see doca/samples/common.c doca_dpdk_port_probe(...);

      3. 查询并记录 PF 的 MAC 和 IP 地址。

        复制
        已复制!
                    

        rte_eth_macaddr_get(...); doca_devinfo_get_ipv6_addr(...); DOCA_LOG_INFO("Port %d: Detected PF mac addr: %s, IPv6 addr: %s, total ports: %d", ...);

    6. 初始化并启动 DPDK 端口。初始化 DPDK 端口,包括内存池分配。不创建 hairpin 队列。

      复制
      已复制!
                  

      dpdk_queues_and_ports_init(); // not part of doca_flow; see doca/applications/common/dpdk_utils.c

    7. 初始化 PSP 网关应用程序使用的 DOCA Flow 对象。DOCA Flow 库使用字符串 "switch,hws,isolated,expert" 初始化,因为应用程序需要充当上行链路物理端口和一些 VF 表示器(交换机模式)之间的中介,并且 hws(硬件转向模式)和 isolated 模式对于交换机模式是强制性的。可选的 expert 标志阻止 DOCA Flow 自动化某些数据包操作,并为应用程序提供更多控制权,如 DOCA Flow 页面中所述。

      复制
      已复制!
                  

      PSP_GatewayFlows psp_flows(&pf_dev, vf_port_id, &app_config); psp_flows.init();

      1. 初始化 DOCA Flow 库。

      2. 启动端口。

      3. 分配共享资源(PSP 加密对象和镜像操作)。

      4. 创建入口和出口管道。

    8. 创建 gRPC 服务。

      复制
      已复制!
                  

      PSP_GatewayImpl psp_svc(&app_config, &psp_flows);

    9. 启动 L-Core 线程以处理 RSS 数据包。

      复制
      已复制!
                  

      rte_eal_remote_launch(lcore_pkt_proc_func, &lcore_params, lcore_id);

    10. 启动 gRPC 服务。

      1. 此实现使用 InsecureServerCredentials。根据需要更新。

        复制
        已复制!
                    

        grpc::ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&psp_svc); auto server_instance = builder.BuildAndStart();

    11. 等待流量。如果配置为在启动时连接,则处理剩余连接的列表。然后显示流管道计数器。

      复制
      已复制!
                  

      while (!force_quit) { psp_svc.try_connect(remotes_to_connect, local_vf_addr); ... psp_flows.show_static_flow_counts(); psp_svc.show_flow_counts(); }

      • 在循环中等待,直到用户终止程序。

    12. PSP 网关清理

      1. 销毁 DPDK 端口和队列。

        复制
        已复制!
                    

        dpdk_queues_and_ports_fini();

      2. DPDK 完成。

        复制
        已复制!
                    

        dpdk_fini();

        调用 rte_eal_destroy() 以销毁初始化的 EAL 资源。

      3. Arg 解析器销毁。

        复制
        已复制!
                    

        doca_argp_destroy()

  2. 丢失数据包代码流程。

    1. 来自主循环的 L-Core 启动例程指向 lcore_pkt_proc_func 例程。

    2. 轮询 force_quit 标志以响应信号处理程序。

      复制
      已复制!
                  

      while (!*params->force_quit) { ... }

    3. rte_eth_rx_burst 函数轮询 PF 队列以接收数据包。

      复制
      已复制!
                  

      nb_rx_packets = rte_eth_rx_burst(port_id, queue_id, rx_packets, MAX_RX_BURST_SIZE);

    4. handle_packet() 内部,检查数据包元数据以检测此数据包是在入口处采样、在出口处采样还是丢失数据包。

      复制
      已复制!
                  

      uint32_t pkt_meta = rte_flow_dynf_metadata_get(packet);

      1. 采样的数据包仅使用 rte_pktmbuf_dump 函数记录。

    5. 丢失的数据包传递给 gRPC 服务的 handle_miss_packet 方法。此方法处理连接到 VF 的应用程序希望向另一个虚拟地址发送数据包的情况,但必须首先通过在主机之间交换 SPI 和密钥信息来建立 PSP 隧道。

    6. 该服务充当 gRPC 客户端,并且从 config->net_config.hosts 向量中查找相应的服务器,该向量由通过 -t 隧道参数或 -f 隧道文件参数传递的主机组成。

    7. 一旦客户端连接存在,request_tunnel_to_host 方法负责调用架构中定义的 RequestTunnelParams 操作。

      • 可选地,此函数生成一组相应的隧道参数,适用于服务器主机通过 generate_tunnel_params() 发回流量。

        复制
        已复制!
                    

        doca_flow_crypto_psp_spi_key_bulk_generate(bulk_key_gen); doca_flow_crypto_psp_spi_key_bulk_get(bulk_key_gen, 0, &spi, key); doca_flow_crypto_psp_spi_key_wipe(bulk_key_gen, 0);

    8. 调用 RPC 操作,如果成功,则调用 create_tunnel_flow 以创建出口流

      复制
      已复制!
                  

      status = stub->RequestTunnelParams(&context, request, &response);

    9. create_tunnel_flow 方法将生成的 Protobuf 对象转换为应用程序特定的数据结构,并将它们传递给流对象的 add_encrypt_entry 方法。在此处,PSP SPI 和密钥被编程到可用的 crypto_id 索引中,如下所示。

      注意

      SPI 和 crypto_id 是两个独立的概念

      • PSP 数据包标头中的 SPI 值向接收者指示发送者用于加密数据的密钥。每个接收者都计算 SPI 和密钥以提供给发送者。由于每个接收者都负责跟踪其下一个 SPI,因此多个接收者可以向发送者提供相同的 SPI,因此一个发送者可以将相同的 SPI 发送到多个不同的对等方。这是允许的,因为每个接收对等方都有自己的解密密钥来处理该 SPI。

      • crypto_id 充当 DOCA Flow 分配的 PSP 密钥存储桶的索引。doca_flow_shared_resource_cfg() 函数将给定的 PSP 加密密钥写入 NIC 内存中密钥存储桶的给定槽中。这些槽可以根据应用程序的需要进行覆盖。

      • crypto_id 和 SPI 之间没有显式关联。doca_flow_shared_resource_cfg() 函数将密钥写入 crypto_id 参数提供的槽中,然后流管道条目 actions.crypto.crypto_id 引用此密钥,并且 actions.crypto_encap.encap_data 包括带有所需 SPI 的 PSP 标头。

      复制
      已复制!
                  

      struct doca_flow_shared_resource_cfg res_cfg = {}; res_cfg.domain = DOCA_FLOW_PIPE_DOMAIN_SECURE_EGRESS; res_cfg.psp_cfg.key_cfg.key_type = DOCA_FLOW_CRYPTO_KEY_256; res_cfg.psp_cfg.key_cfg.key = (uint32_t *)encrypt_key; doca_flow_shared_resource_cfg(DOCA_FLOW_SHARED_RESOURCE_PSP, session->crypto_id, &res_cfg);

    10. 必须插入引用新编程的 PSP 加密密钥(通过其索引 crypto.crypto_id)的流管道条目。此外,此管道条目必须指定要插入的所有外部以太网、IP、UDP 和 PSP 标头字段。

      复制
      已复制!
                  

      format_encap_data(session, actions.crypto_encap.encap_data); actions.crypto.action_type = DOCA_FLOW_CRYPTO_ACTION_ENCRYPT; actions.crypto.resource_type = DOCA_FLOW_CRYPTO_RESOURCE_PSP; actions.crypto.crypto_id = session->crypto_id; ...   doca_flow_pipe_add_entry(pipe_queue, pipe, match, actions, mon, fwd, flags, &status, entry); ...   doca_flow_entries_process(port, 0, DEFAULT_TIMEOUT_US, num_of_entries);

    11. 通过 rte_ethdev_rx_burst 接收的原始数据包通过新更新的管道使用 rte_ethdev_tx_burst 发送回。由于 port_id 参数是 PF 的参数,并且由于 DOCA Flow 已在 expert 模式下初始化,因此数据包将传输到出口域的根(egress_acl_pipe 之前的“空管道”)。

      复制
      已复制!
                  

      nsent = rte_eth_tx_burst(port_id, queue_id, &packet, 1);

  3. 隧道参数请求处理

    1. PSP 网关提供的 gRPC 服务实现了上面引用的 RequestTunnelParams 操作。客户端使用此操作来请求 SPI 和密钥,以加密要发送到服务器 NIC 设备的数据流量。该请求指示将为其创建隧道的虚拟远程地址。

    2. 此操作首先在 generate_tunnel_params() 内部生成新的 SPI 和密钥,如前所述。

    3. 该操作创建一个 ACL 条目,允许使用 Flows 对象的 add_ingress_acl_entry 方法的新 SPI 和远程虚拟地址。

      复制
      已复制!
                  

      doca_flow_match match = {}; match.parser_meta.psp_syndrome = 0; match.tun.type = DOCA_FLOW_TUN_PSP; match.tun.psp.spi = RTE_BE32(session->spi_ingress); match.inner.l3_type = DOCA_FLOW_L3_TYPE_IP4; match.inner.ip4.src_ip = session->src_vip; ...   doca_flow_pipe_add_entry(pipe_queue, pipe, match, actions, mon, fwd, flags, &status, entry); ...   doca_flow_entries_process(port, 0, DEFAULT_TIMEOUT_US, num_of_entries);

    4. 如果请求包括反向流量(要加密并发送到客户端的流量)的参数,则这些参数将被转换并通过调用 上面描述的 create_tunnel_flow 传递给 Flows 对象。

参考

© 版权所有 2025,NVIDIA。 上次更新时间:2025 年 2 月 12 日。