DOCA TLS Offload 指南
本指南概述了通过 kernel-TLS 使用 NVIDIA® BlueField® DPU 的硬件功能进行 TLS 硬件加速,并提供了配置步骤。
传输层安全 (TLS) 是一种加密协议,旨在为计算机网络上的通信提供安全保障。该协议广泛用于电子邮件、即时消息和 IP 语音 (VoIP) 等应用程序,但其在保护 HTTPS 中的应用仍然是最公开可见的。
TLS 协议的主要目标是提供加密,包括隐私(保密性)、完整性和真实性,使用证书在两个或多个通信计算机应用程序之间进行。它在应用层运行,本身由两层组成:TLS 记录协议和 TLS 握手协议。
TLS 通过 TCP 工作,由 3 个阶段组成
握手 – 建立连接
应用 – 发送和接收加密数据包
终止 – 连接终止
TLS 握手
在握手阶段,客户端和服务器决定他们将使用的密码套件,并根据以下流程交换密钥和证书
客户端 hello,至少向服务器提供以下内容
密钥交换算法,以确定对称密钥的交换方式
身份验证或数字签名算法,它决定了如何实现服务器身份验证和客户端身份验证(如果需要)
批量加密密码,用于加密数据
哈希/MAC(消息身份验证码)函数,它决定了如何执行数据完整性检查
它理解的协议版本
它可以使用的密码套件
唯一的随机数,这对于防止重放攻击非常重要
服务器 hello
选择密码套件
生成自己的随机数
为 TLS 连接分配会话 ID
发送足够的信息以完成密钥交换——通常,这意味着发送包含 RSA 公钥的证书
客户端
负责使用服务器提供的信息完成密钥交换
此时,连接已安全,双方已就加密算法、MAC 算法和各自的密钥达成一致。
kTLS
Linux 内核提供 TLS offload 基础设施。kTLS(内核 TLS)将 TLS 处理从用户空间 offload 到内核空间。
kTLS 有 3 种运行模式
SW – 所有操作都在内核中处理(即,握手、加密、解密)
硬件加速 (HW-offload)(本指南的重点)– 握手和错误处理在软件中执行。数据包在硬件中加密/解密。在这种情况下,还有从内核到硬件的额外 offload。
硬件记录 (HW-record) – 所有操作都由硬件(驱动程序和固件)处理,包括握手。它还处理自己的 TCP 会话。目前不支持此选项。
重要的是要理解 Rx(接收)和 Tx(发送)可以有两种独立的模式。例如,Rx 可以在 SW 模式下处理,而 Tx 可以在硬件加速模式下处理(即,硬件将仅加密但不解密)。
硬件加速 kTLS
一般来说,TLS 硬件加速在较长会话和相对较大的数据包上表现最佳并提供最佳价值。并发连接和每秒连接数的扩展取决于用例(例如,来自总体打开的并发连接的活动并发连接量是重要的)。
在继续之前,有必要了解以下术语
传输接口发送 (TIS) 对象负责执行发送端的所有传输相关操作。来自发送队列 (SQ) 的消息由 TIS 分段和传输,包括所有传输所需的含义。例如,在大型发送加速的情况下,TIS 负责分段。NVIDIA® ConnectX® 硬件使用 TIS 对象来保存和访问已加速的 Tx kTLS 连接的 TLS 加密信息和状态。
传输接口接收 (TIR) 对象负责执行接收端的所有传输相关操作。TIR 执行数据包处理和重组,还负责将数据包多路分解到不同的接收队列 (RQ) 中。
TIS 和 TIR 都保存数据加密密钥 (DEK)。
kTLS Offload 高级流程
以下流程不包括重新同步和错误。
通过在当前主机上通过内核处理 TLS 握手,与远程主机(服务器或客户端)建立 TLS 连接。
为每个连接(Rx 和 Tx)初始化以下状态
加密密钥(例如,公钥)
加密处理状态
记录元数据(例如,记录序列号、偏移量)
预期 TCP 序列号
Tx 流程
属于设备加速套接字的数据包到达内核,内核不对其进行加密。
内核执行记录成帧,并使用连接标识符标记数据包。
内核将数据包发送到设备驱动程序以进行加速。
设备检查序列号是否与 TIS 中的状态匹配,并执行加密和身份验证。
Rx 流程
创建连接时,会添加硬件 steering 规则,以将数据包 steering 到其各自的 TIR。
设备接收数据包,然后验证并检查 TCP 的序列号是否与 TIR 中的状态匹配。
执行解密和身份验证,并在 CQE(完成队列条目)中指示。
内核了解数据包已被解密,因此它本身不解密,而是将其传递给用户空间。
重新同步和错误处理
当序列号与预期不符或发生任何其他错误时,硬件会将控制权交还给 SW,由 SW 处理问题。
有关 kTLS 模式、重新同步和错误处理的更多信息,请参阅Linux 内核文档。
本节中的所有命令都应在主机上执行(除非另有说明,否则不在 BlueField 上)。
检查硬件是否支持加密加速
要检查 BlueField 或 ConnectX 是否具有加密加速,请从主机运行以下命令
host> mst start # turn on mst driver
host> flint -d <device under /dev/mst/ directory> dc
| grep
Crypto
输出应包括 Crypto Enabled
。例如
host> flint -d /dev/mst/mt41686_pciconf0 dc
| grep
Crypto
....
;;Description = NVIDIA BlueField-2 E-Series Eng. sample DPU; 200GbE single-port QSFP56; PCIe Gen4 x16; Secure Boot Disabled; Crypto Enabled; 16GB on-board DDR; 1GbE OOB management
....
内核要求
操作系统必须是以下之一
FreeBSD 13.0+。
基于 Linux 内核版本 5.3 或更高版本(用于 Tx 支持)和版本 5.9 或更高版本(用于 Rx 支持)构建的 Linux 发行版。我们建议尽可能使用最新版本以获得最佳优化。
注意TIS 池优化已添加到 Linux 内核版本 6.0。将回收先前连接中未使用的 TIS,而不是为每个新连接创建 TIS。这将提高 Tx 连接速率。除了安装内核本身之外,无需进一步安装。
检查主机上的当前内核版本。运行
host>
uname
-r内核必须配置为支持 TLS,方法是将选项
TLS_DEVICE
和MLX5_TLS
设置为y
。要检查是否配置了 TLS,请运行host>
cat
/boot/config-$(uname
-r) |grep
TLS示例输出
host>
cat
/boot/config-5.4.0-121-generic |grep
TLS ... CONFIG_TLS_DEVICE=y CONFIG_MLX5_TLS=y ...如果当前内核不支持其中一个选项,您可以更改配置并重新编译,或构建新内核。
注意请按照内核提供商提供的构建说明进行操作。
构建 Linux 内核的示意流程
进入下载的 Linux 内核目录(通常在
/usr/src/
中)host> make menuconfig # Set TLS_DEVICE=y and MLX5_TLS=y in options. Setting location in the menu can be found by pressing
'/'
and typing'setting'
. host> make -j <num-of-cores> && make -j <num-of-cores> modules_install && make -j <num of cores> install更新 grub 以使用新的配置内核,然后重新启动。
TLS 设置

查找 NVIDIA 接口
host> mst start # if mst driver is not loaded.
host> mst status -v
NVIDIA 的 netdev 接口位于 NET
列下。
例如
host> mst status -v
....
DEVICE_TYPE MST PCI RDMA NET NUMA
BlueField2(rev:0) /dev/mst/mt41686_pciconf0.1 b1:00.1 mlx5_1 net-ens5f1 1
BlueField2(rev:0) /dev/mst/mt41686_pciconf0 b1:00.0 mlx5_0 net-ens5f0 1
在此示例中,接口 ens5f1
和 ens5f0
是 NVIDIA 的 netdev 接口。
配置 TLS Offload
要检查 offload 选项是打开还是关闭,请运行
host>
ethtool
-k $iface |grep
tls示例输出
tls-hw-tx-offload: on tls-hw-rx-offload: off tls-hw-record: off [fixed]
注意tls-hw-record
不是设备必需的,因为 kTLS 不支持“硬件记录”模式。要打开或关闭 Tx offload
host>
ethtool
-K $iface tls-hw-tx-offload <on | off>要打开或关闭 Rx offload
host>
ethtool
-K $iface tls-hw-rx-offload <on | off>
在 BlueField 上配置 OVS 网桥
当主机连接到 BlueField 设备时,必须在 BlueField 上配置 OVS 网桥,以便流量从主机到上行链路双向传递。如果未配置 OVS 网桥,则主机与网络隔离(请参阅上面的示意图)。
在 BlueField 镜像版本 3.7.0 或更高版本上,可以使用默认的 OVS 配置,无需额外修改。
要在 BlueField 上配置 OVS 网桥,请在 BlueField 上运行以下命令
dpu> for
br in
$(ovs-vsctl list-br); do
ovs-vsctl del-br $br; done
# erasing existing bridges
dpu> ovs-vsctl add-br ovs-br0 && ovs-vsctl add-port ovs-br0 p0 && ovs-vsctl add-port ovs-br0 pf0hpf
dpu> ovs-vsctl add-br ovs-br1 && ovs-vsctl add-port ovs-br1 p1 && ovs-vsctl add-port ovs-br1 pf1hpf
dpu> ovs-vsctl set
Open_vSwitch . other_config:hw-offload=true
&& systemctl restart openvswitch-switch
其中 p0
/p1
是上行链路接口,pf0hpf
/pf1hpf
是面向主机的接口。
OpenSSL
OpenSSL 是一个全能的加密库,提供 TLS 协议的开源应用。它是使用 kTLS 和其他应用程序的主要库,因为 Nginx 依赖于它作为其基础库。
kTLS 和硬件加速不依赖于 OpenSSL。任何可以实现 TLS 堆栈的程序都可以替代运行。但是,由于 OpenSSL 的广泛使用,本指南将介绍安装建议。
kTLS 仅在 OpenSSL 版本 3.2.0 或更高版本中受支持,并且仅在受支持的内核版本上受支持。受支持的 OpenSSL 版本可从发行版软件包下载,也可以从 OpenSSL GitHub 下载和编译。
许多模块依赖于 OpenSSL。更改默认版本可能会导致问题。在下面的 ./Configure
命令中添加 --prefix=/var/tmp/ssl --openssldir=/var/tmp/ssl
可以防止构建的 OpenSSL 成为系统使用的默认版本。确保手动构建的 OpenSSL 目录不在 PATH 环境变量中列出的任何路径中。
检查默认 OpenSSL 的版本
host> openssl version
按照 OpenSSL 提供的指南中的 OpenSSL 安装说明进行操作。在配置过程中,请确保在构建之前设置
enable-ktls
选项,方法是从 OpenSSL 目录中运行它(在版本 3.2.0 和更高版本中有效)。例如host> ./Configure linux-$(
uname
-p)enable
-ktls --prefix=/var/tmp/ssl --openssldir=/var/tmp/ssl# Add "threads" as well for multithread support
通过从 OpenSSL 目录中运行以下命令来检查 kTLS 是否在 OpenSSL 中启用,并检查
ktls
是否在Enabled features
下列出host> perl configdata.pm --dump |
less
如果 OpenSSL 是手动下载的,则 OpenSSL 可执行文件将位于 /<openssl-dir>/apps/
目录中。例如,从 OpenSSL 目录中检查版本是使用命令 ./apps/openssl version
完成的。
安装新的 OpenSSL 需要重新编译在 OpenSSL 上配置的用户工具(例如,Nginx)。
在 OpenSSL 的主源代码中,有一个功能“Support for kTLS Zero-Copy sendfile() on Linux”(Zero-Copy commit)。如果设置了 Zero-Copy 选项,SSL_sendfile()
将使用 Zero-Copy TX 模式,这意味着数据本身不会从用户空间复制到内核空间。这在使用 kTLS 硬件加速时会带来性能提升。请注意,如果文件在发送时被更改,可能会传输无效的 TLS 记录。
Nginx
Nginx 是一款免费的开源软件 Web 服务器,也可以用作反向代理、负载均衡器、邮件代理和 HTTP 缓存。Nginx 可以配置为依赖 OpenSSL 库,因此 Nginx 可以充分利用 ConnectX-6 Dx、ConnectX-7 或 DPU 上的 TLS 硬件加速。
先决条件
有关设置 OpenSSL,请参阅OpenSSL 部分。
配置
安装依赖项。例如,对于 Ubuntu 发行版
host> apt install libpcre3 libpcre3-dev
克隆 Nginx 的存储库并进入目录
host> git clone https://github.com/nginx/nginx.git && cd nginx
配置 Nginx 组件以支持 kTLS
host> ./auto/configure --with-openssl=/<insert_path_to_openssl_directory> --with-debug --with-http_ssl_module --with-openssl-opt="enable-ktls -DOPENSSL_LINUX_TLS -g3"
构建 Nginx
host> make -j <num of cores> && sudo make -j <num-of-cores> install
注意如果
make
失败并出现deprecated openssl functions
错误,请删除 objs/Makefile 中CFLAGS
的-Werror
,然后重试。将以下行添加到
/usr/local/nginx/conf/nginx.conf
文件的末尾(在最后一个右括号之前)server { listen 443 ssl default_server reuseport; server_name localhost; root /tmp/nginx/docs/html/; include /etc/nginx/default.d/*.conf; ssl_certificate /usr/local/nginx/conf/cert.pem; ssl_certificate_key /usr/local/nginx/conf/key.pem; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256; ssl_conf_command Options KTLS; ssl_protocols TLSv1.2; location / { index index.html; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
请注意,Nginx 服务器的密钥和证书应位于
/usr/local/nginx/conf/
中。因此,在创建密钥和证书后(如“添加证书和密钥”部分所述),应将其复制到上述目录中host> cp key.pem /usr/local/nginx/conf/ && cp cert.pem /usr/local/nginx/conf/
要运行 Nginx
host> cd nginx && objs/nginx
此命令在后台启动 Nginx 服务器。
停止 Nginx
host> pkill nginx
Wrk – 客户端
用于请求 Nginx 服务器的简单客户端是“wrk”。可以通过运行以下命令安装它
host> git clone https://github.com/wg/wrk.git && cd wrk/ && make -j <num-of-cores>
使用 Wrk
以下是使用 wrk 客户端从地址 4.4.4.4
中的 Nginx 服务器请求页面 index.html
的示例(在 wrk 目录中运行)
host> taskset -c 0 ./wrk -t1 -c10 -d30s https://4.4.4.4:443/index.html
kTLS offload 的测试(无论是否进行硬件加速)与“测试 kTLS”部分中提到的方式相同。待定
本章演示如何测试 kTLS 硬件加速。
在继续之前,请务必参考“OpenSSL”部分。
TLS 测试设置
为了测试目的,需要服务器和客户端。测试部分仅测试主机和 BlueField-2 或主机 ConnectX 的单个设置,它们将充当服务器或客户端。设置相同类型的背靠背设置并安装相同的 OpenSSL 版本可以帮助避免配置错误。但是,客户端和服务器都需要具有相同的 OpenSSL 版本。
确保按照“配置 TLS Offload”部分中的详细说明配置所需的 kTLS。要测试硬件加速,请确保 tls-hw-tx-offload
和/或 tls-hw-rx-offload
处于打开状态。要测试 kTLS 软件模式,请确保将其关闭。
此外,确保两个主机(服务器和客户端)可以通过 ConnectX 或 BlueField 双向通信。可以将支持 offload 的接口(在主机上)设置为 IP,在同一子网中。确保在使用 BlueField 时,在 BlueField 上设置 OVS 网桥,如“在 BlueField 上配置 OVS 网桥”中所示。

添加证书和密钥
服务器端应创建证书和密钥。客户端也可以使用证书,但对于此测试用例来说不是必需的。在安装的 OpenSSL 目录中运行以下命令,并填写所有请求的详细信息
host> openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
将创建以下文件
key.pem
– 私钥文件,用于生成 CSR,以及稍后使用证书保护和验证连接cert.pem
– 证书签名请求 (CSR) 文件,用于订购您的 SSL 证书,以及稍后加密只有其对应的私钥才能解密的消息
服务器端应在客户端之前运行,以便客户端的请求由服务器响应。
运行服务器端
以下示例适用于 OpenSSL 版本 3.1.0
host> openssl s_server -key key.pem -cert cert.pem -tls1_2 -cipher ECDHE-RSA-AES128-GCM-SHA256 -accept 443 -ktls
请注意 -ktls
标志。
有关 s_server
的更多信息,请参阅官方 OpenSSL 文档。
在此示例中,提供了密钥和证书,配置了密码套件和 TLS 版本,服务器侦听端口 443 并被指示使用 kTLS。
运行客户端
以下示例适用于 OpenSSL 版本 3.1.0
host> openssl s_client -connect 4.4.4.4:443 -tls1_2 -ktls
其中 4.4.4.4 是被测端口/接口的 IP(例如,enp177s0f0np0
)。
有关 s_client
的更多信息,请参阅官方 OpenSSL 文档。
测试 kTLS
连接建立后(握手完成),将打开一个提示符,客户端和服务器端的用户都可以在类似聊天的模式下向另一端发送消息。消息在收到后应显示在另一端。
以下示例通过跟踪设备计数器上的 Rx 和 Tx TLS 来检查测试设置上的 kTLS 硬件加速
host> ethtool
-S $iface | grep
-i 'tx_tls_encrypted\|rx_tls_decrypted'
# ($iface is the interface that offloads)
要检查内核计数器上的 kTLS
host> cat
/proc/net/tls_stat
输出示例
注释不是输出的一部分,而是作为解释添加的。
host> cat
/proc/net/tls_stat
TlsCurrTxSw 0 # Current Tx connections opened in SW mode
TlsCurrRxSw 0 # Current Rx connections opened in SW mode
TlsCurrTxDevice 0 # Current Tx connections opened in HW-offload mode
TlsCurrRxDevice 0 # Current Rx connections opened in HW-offload mode
TlsTxSw 2323828 # Accumulated number of Tx connections opened in SW mode
TlsRxSw 1 # Accumulated number of Rx connections opened in SW mode
TlsTxDevice 12203652 # Accumulated number of Tx connections opened in HW-offload mode
TlsRxDevice 0 # Accumulated number of Rx connections opened in HW-offload mode
TlsDecryptError 0 # Failed record decryption (e.g., due to incorrect authentication tag)
TlsRxDeviceResync 0 # Rx resyncs sent to HW's handling cryptography
TlsDecryptRetry 0 # All Rx records re-decrypted due to TLS_RX_EXPECT_NO_PAD misprediction
TlsRxNoPadViolation 0 # Data Rx records re-decrypted due to TLS_RX_EXPECT_NO_PAD misprediction
有关内核计数器的更多信息,请参阅内核 TLS 文档的统计信息部分。
XLIO
NVIDIA 加速 IO (XLIO) 软件库提高了基于 Nginx(例如,CDN、DoH)和存储解决方案(作为 SPDK 的一部分)的 TCP/IP 应用程序的性能。XLIO 是一个用户空间软件库,它公开了具有内核旁路架构的标准套接字 API,从而实现了应用程序用户空间内存和网络接口之间的基于硬件的直接复制。特别是,XLIO 可以提高使用 kTLS 硬件加速(如 OpenSSL 和 Nginx)的应用程序的性能。有关 XLIO 的更多信息,请阅读NVIDIA XLIO 文档,以及有关 kTLS 的 XLIO TLS 硬件加速,请阅读TLS 硬件加速部分。
即使 XLIO 是一个内核旁路库,内核也必须支持 kTLS 才能使旁路正常工作。
TLS offload 性能与数据可以通过 offload 引擎泵送的速度有关。在用户空间应用程序的情况下,可以调整某些系统配置以优化其性能。
以下是可以调整以获得最佳性能的项目,主要侧重于将服务器的工作专用于 NUMA 或非统一内存访问内核
非统一内存访问 (NUMA) 内核是为每个内核分配专用内存的内核,使内核可以快速访问自己的内存,而访问其他内核的内存速度较慢。这种架构最适合不需要在内核之间共享内存的场景。
将 NIC 的 NUMA 内核添加到每个服务器的
isolcpus
内核引导参数中,以便内核调度程序不会中断内核正在运行的用户线程。以下是添加命令的示例识别 NIC NUMA 节点(请参阅 NUMA 列)
host> mst status -v DEVICE_TYPE MST PCI RDMA NET NUMA ConnectX6DX(rev:0) /dev/mst/mt4125_pciconf0 41:00.0 mlx5_0 net-enp65s0f0np0 1
使用从先前输出中获取的 NUMA 节点号识别 NIC NUMA 节点的内核
host> lscpu | grep "NUMA node1" NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23
通过添加行
GRUB_CMDLINE_LINUX_DEFAULT="isolcpus=<NUMA-cores-from-previous-output>"
将 NIC NUMA 内核添加到 grub 文件(例如,/etc/default/grub
)。例如GRUB_CMDLINE_LINUX_DEFAULT="isolcpus=1,3,5,7,9,11,13,15,17,19,21,23"
更新 grub
host> sudo update-grub
重新启动并检查配置是否已应用
host> cat /proc/cmdline BOOT_IMAGE=/vmlinuz-5.10.12 root=UUID=1879326c-711f-4f95-a974-d732af14ef04 ro department=general user_notifier=dovd osi_string None BOOTIF=01-90-b1-1c-14-02-44 quiet splash isolcpus=1,3,5,7,9,11,13,15,17,19,21,23
禁用
irqbalance
服务注意中断请求 (IRQ) 确定哪些硬件中断到达每个内核。
host> service irqbalance stop
运行
set_irq_affinity.sh
以将 IRQ 重新分配到各个内核。注意该脚本位于 MLNX_OFED 的源代码中
您可以在MLNX_OFED 下载中找到它。
在“下载”下,选择正确的版本并下载“SOURCES”
.tgz
文件。解压
.tgz
。在 SOURCES 下,解压
mlnx_tools
。
您应该在
sbin
目录下找到文件set_irq_affinity.sh
及其帮助文件common_irq_affinity.sh
。host> ./set_irq_affinity.sh <ConnectX_or_BlueField_network_interface>
将接口 RSS 设置为要使用的内核数
host> ethtool -X <ConnectX_or_BlueField_network_interface> equal <number_of_isolcpus_cores>
为要使用的内核数设置接口队列
host> ethtool -L <ConnectX_or_BlueField_network_interface> combined <number_of_isolcpus_cores>
使用
taskset
将应用程序固定到使用的isolcpus
内核。例如host> taskset -c 1,3,5,7,9,11,13,15,17,19,21,23 openssl s_server -key key.pem -cert cert.pem -tls1_2 -cipher ECDHE-RSA-AES128-GCM-SHA256 -accept 443 -ktls