XFRM 设备 - 卸载 IPsec 计算

本文详细解释了IPsec的加密和数据包卸载技术,特别是在硬件支持下如何提高网络吞吐量和降低CPU负载。文章介绍了内核支持的两种卸载类型,以及网卡驱动程序如何通过回调函数实现硬件卸载功能,并提供了相关命令和驱动程序设置示例。
摘要由CSDN通过智能技术生成

概述

IPsec是一种保护网络流量的有用功能,但计算成本很高:一个10Gbps 链路可以很容易地降低到 1Gbps 以下,具体决于流量和链路配置。幸运的是,有些网卡提供硬件支持的IPsec卸载( offload),可以从根本上提高吞吐量并降低 CPU 利用率。XFRM设备接口允许网卡驱动程序向堆栈提供对硬件卸载(hardware offload)的访问。

目前,内核支持两种类型的硬件卸载。

  • IPsec 加密卸载(crypto offload): * NIC 执行加密/解密 * 内核执行其他所有操作
  • IPsec 数据包卸载(packet offload): * NIC 执行加密/解密 * NIC 执行封装 * 内核和 NIC 的 SA 和策略同步 * NIC 处理 SA 和策略状态 * 内核与密钥管理器通信

用户空间对卸载的访问通常是通过 libreswan 或 KAME/raccoon 等系统进行的,但在试验时,iproute2 ‘ip xfrm’ 命令集会很方便。

对于加密卸载,示例命令可能如下所示:

ip x s add proto esp dst 14.0.0.70 src 14.0.0.52 spi 0x07 mode transport
reqid 0x07 replay-window 32 aead ‘rfc4106(gcm(aes))’ 0x44434241343332312423222114131211f4f3f2f1 128 sel src 14.0.0.52/24 dst 14.0.0.70/24 proto
tcp offload dev eth4 dir in

以及数据包卸载:

ip x s add proto esp dst 14.0.0.70 src 14.0.0.52 spi 0x07 mode transport
reqid 0x07 replay-window 32 aead ‘rfc4106(gcm(aes))’ 0x44434241343332312423222114131211f4f3f2f1 128 sel src 14.0.0.52/24 dst 14.0.0.70/24 proto
tcp offload packet dev eth4 dir in

ip x p add src 14.0.0.70 dst 14.0.0.52 offload packet dev eth4 dir in tmpl src 14.0.0.70 dst
14.0.0.52 proto esp reqid 10000 mode transport

是的,这很丑陋,但这就是 shell 脚本和/或 libreswan 的用途。

要实现的回调

/* from include/linux/netdevice.h */
struct xfrmdev_ops {
    /* Crypto and Packet offload callbacks */
    int     (*xdo_dev_state_add) (struct xfrm_state *x, struct netlink_ext_ack *extack);
    void    (*xdo_dev_state_delete) (struct xfrm_state *x);
    void    (*xdo_dev_state_free) (struct xfrm_state *x);
    bool    (*xdo_dev_offload_ok) (struct sk_buff *skb,
                                    struct xfrm_state *x);
    void    (*xdo_dev_state_advance_esn) (struct xfrm_state *x);

    /* Solely packet offload callbacks */
    void    (*xdo_dev_state_update_curlft) (struct xfrm_state *x);
    int     (*xdo_dev_policy_add) (struct xfrm_policy *x, struct netlink_ext_ack *extack);
    void    (*xdo_dev_policy_delete) (struct xfrm_policy *x);
    void    (*xdo_dev_policy_free) (struct xfrm_policy *x);

};

提供 ipsec 卸载的 NIC 驱动程序需要实现与支持的卸载相关的回调,以使卸载可用于网络堆栈的 XFRM 子系统。此外,功能位(feature bits) NETIF_F_HW_ESP 和 NETIF_F_HW_ESP_TX_CSUM 将指示卸载的可用性。

在探测时和调用 register_netdev() 之前,驱动程序应设置本地数据结构和 XFRM 回调,并设置功能位。XFRM 代码的侦听器(listener)将在 NETDEV_REGISTER 上完成设置。

adapter->netdev->xfrmdev_ops = &ixgbe_xfrmdev_ops;
adapter->netdev->features |= NETIF_F_HW_ESP;
adapter->netdev->hw_enc_features |= NETIF_F_HW_ESP;

当使用“卸载”功能请求设置新 SA 时,驱动程序的 xdo_dev_state_add() 将获得要卸载的新 SA,并指示它是用于 Rx 还是 Tx。驱动程序应

  • 验证算法是否支持卸载

  • 存储 SA 信息(key、salt、target-ip、protocol 等)

  • 启用 SA 的硬件卸载

  • 返回状态值:
    在这里插入图片描述
    驱动程序还可以在 SA 中设置一个 offload_handle,这是一个不透明的 void 指针,可用于将上下文传达到快速路径卸载请求中:

    xs->xso.offload_handle = context;

当网络堆栈为已设置为卸载的 SA 准备 IPsec 数据包时,它首先使用 skb 和预期卸载状态调用 xdo_dev_offload_ok(),以询问驱动程序卸载是否可用。这可以检查数据包信息以确保可以支持卸载(例如 IPv4 或 IPv6、没有 IPv4 选项等),并返回 true 或 false 以表示其支持程度。

加密卸载模式:准备发送时,驱动程序需要检查 Tx 数据包的卸载信息,包括不透明上下文,并设置相应的数据包发送:

xs = xfrm_input_state(skb);
context = xs->xso.offload_handle;
set up HW for send

栈已经在数据包中插入了适当的IPsec头部,只需要进行加密并修复头部值。

当接收到一个数据包,并且HW表明它已经卸载了一个解密( offloaded a decryption),驱动程序需要将对已解码SA的引用添加到数据包的 skb 中。此时,数据应该已经解密,但IPsec首部仍然在分组数据中。它们稍后在 xfrm_input() 的栈中被移除。

查找并保存用于Rx skb的SA:

get spi, protocol, and destination IP from packet headers
xs = find xs from (spi, protocol, dest_IP)
xfrm_state_hold(xs);

将状态信息存储到 SKB 中:

sp = secpath_set(skb);
if (!sp) return;
sp->xvec[sp->len++] = xs;
sp->olen++;

指示卸载的成功和/或错误状态:

xo = xfrm_offload(skb);
xo->flags = CRYPTO_DONE;
xo->status = crypto_status;

像往常一样将数据包交给 napi_gro_receive()

在 ESN 模式下,xdo_dev_state_advance_esn() 是从 xfrm_replay_advance_esn() 调用的。如果需要,驱动程序将检查数据包序列号并更新硬件 ESN 状态机。

分组卸载模式:HW 添加和删除 XFRM 报头。因此,在RX路径中,如果 HW 报告成功,则绕过 XFRM 堆栈。在发送路径中,分组离开内核时没有额外的首部,也没有加密,硬件负责执行它。

当用户删除SA时,驱动程序会请求xdo_dev_state_delete()和xdo_dev_policy_delete()来禁用卸载。稍后,在移除了状态和策略的所有引用计数,并为卸载状态清除剩余资源之后,再从垃圾回收例程中调用xdo_dev_state_free()和xdo_dev_policy_free()。驱动程序如何使用这些参数取决于特定的硬件需求。

当 netdev 设置为 DOWN 时,XFRM 堆栈的 netdev 侦听器将在任何剩余的卸载状态上调用 xdo_dev_state_delete()、xdo_dev_policy_delete()、xdo_dev_state_free() 和 xdo_dev_policy_free()。

硬件处理数据包的结果,XFRM 内核无法计算硬限制和软限制。硬件/驱动程序负责执行它,并在调用 xdo_dev_state_update_curlft() 时提供准确的数据。如果出现这些限制之一,驱动程序需要调用 xfrm_state_check_expire() 以确保 XFRM 执行重新生成密钥序列。

ref: https://www.kernel.org/doc/html/latest/networking/xfrm_device.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值