3、硬件卸载架构设计:智能网卡与DPU的演进、卸载引擎设计、数据面与控制面分离、硬件加速器
好,咱们进入第三章。这一章我打算聊聊硬件卸载的架构设计。说实话,这部分内容是我个人觉得最「硬核」也最有趣的地方。你想想看,一个网卡从简单的数据收发,进化到能替CPU分担那么多活,这中间的设计思路,本身就是一部精彩的演进史。
3.1 智能网卡与DPU的演进:从「管道」到「大脑」
最早的时候,网卡就是个管道。CPU把数据扔给它,它负责发出去;数据来了,它通知CPU来取。那时候的网卡,说白了就是个DMA引擎加一个MAC控制器。
但后来问题来了。数据中心里流量越来越大,CPU被中断和协议处理占得死死的。我印象很深,大概十年前,我在一个金融客户现场调优,发现一台双路服务器光处理网络包,CPU占用就飙到了60%以上。业务方问我:「能不能把网络开销降下来?」
嗯,这就是智能网卡出现的直接原因。
智能网卡的核心思路,就是把那些「CPU干着费劲、但网卡也能干」的活,从CPU上搬走。一开始只是简单的校验和计算、分段卸载,后来慢慢加入了流分类、QoS、甚至虚拟化交换。
再往后,DPU(数据处理单元)这个概念就出来了。我个人理解,DPU和智能网卡最大的区别在于:智能网卡是「网卡+加速器」,DPU是「以数据为中心的计算单元」。DPU上跑着完整的操作系统,有自己的控制平面,能独立管理网络、存储和安全策略。
关键演进节点:
- 传统网卡:纯数据通道,CPU处理一切
- 智能网卡(SmartNIC):可编程数据面,卸载特定功能
- DPU:独立计算域,控制面与数据面完全分离
我曾经在一个云厂商的机房见过他们的DPU部署。一台DPU卡,接管了主机所有的网络和存储I/O,主机CPU几乎零中断。那个效果,确实让人印象深刻。
3.2 卸载引擎(Offload Engine)设计:把「脏活累活」交给硬件
卸载引擎,是硬件卸载的核心。它不是一个单一的模块,而是一组硬件加速器的集合。每个加速器负责一类特定的任务。
设计卸载引擎时,我习惯先问三个问题:
- 这个任务适合卸载吗?——任务要足够「重」,卸载才有收益;要足够「规整」,硬件才能高效实现。
- 卸载后性能能提升多少?——有些任务卸载后反而更慢,因为PCIe传输和硬件配置的开销可能抵消收益。
- 卸载后CPU的复杂度降低了吗?——别为了卸载而卸载,搞得驱动和固件复杂到没人能维护。
举个例子,RoCE v2的拥塞控制(DCQCN),就是个典型的适合卸载的任务。它需要频繁地处理CNP(拥塞通知包)和更新速率。如果让CPU来做,每个CNP都要触发一次中断,CPU根本扛不住。硬件卸载后,网卡内部的状态机直接处理,CPU完全感知不到。
避坑指南: 我曾经在一个项目中,试图把TCP的乱序重排也卸载到硬件。结果发现,硬件为了处理各种边界情况,逻辑复杂度爆炸,功耗和面积都超标。最后不得不放弃,改用软件方案。所以,不是所有协议逻辑都适合硬件化。
3.3 数据面与控制面分离:让「快」的更快,「慢」的更灵活
这个设计思想,其实在SDN(软件定义网络)里就已经很成熟了。在硬件卸载架构里,它同样关键。
- 数据面(Data Plane):处理每一个数据包。要求极低延迟、高吞吐。通常用硬件流水线实现,比如P4可编程交换机或FPGA。
- 控制面(Control Plane):管理配置、路由、策略。对延迟不敏感,但需要灵活性和可编程性。通常由CPU上的软件实现。
你想想看,如果每个数据包都要经过CPU去查路由表,那延迟得多高?数据面硬件直接查表转发,微秒级搞定。控制面软件负责更新路由表,毫秒级甚至秒级都行。
在RoCE网卡里,这个分离体现在哪里?
- 数据面:处理RoCE数据包的封装/解封装、CRC校验、拥塞标记、流控。
- 控制面:配置QP(队列对)、管理GID(全局标识符)、处理连接建立和拆除。
我记得有一次调试一个性能问题,发现数据面硬件跑得飞快,但控制面软件配置QP时有个锁竞争,导致连接建立延迟飙升。这就是典型的「控制面拖了数据面后腿」。后来我们优化了控制面的配置路径,问题才解决。
3.4 硬件加速器详解:RSS / Checksum / TSO / LRO
这些是网卡上最经典的硬件加速器。虽然现在看起来不算新鲜,但它们是硬件卸载的「基本功」。我一个个说。
3.4.1 RSS(接收端缩放)
说白了,就是把收到的网络包,根据五元组哈希,均匀分配到多个CPU核心上。这样多个核心可以并行处理,避免单核成为瓶颈。
我建议你在配置RSS时,注意哈希算法的选择。有些网卡支持对称哈希(Toeplitz),有些支持非对称。对称哈希的好处是,同一个流的双向包会落到同一个核心,方便做连接跟踪。
3.4.2 Checksum Offload(校验和卸载)
这个最简单。TCP/UDP/IP头的校验和计算,交给网卡硬件来做。CPU省下几个指令周期。别看它小,积少成多,在高吞吐场景下收益很明显。
3.4.3 TSO(TCP分段卸载)
TCP层发送大块数据时,需要按MSS(最大分段大小)切成小段。TSO让网卡硬件来做这个分段工作。CPU只需要把一个大包(比如64KB)交给网卡,网卡自己切成若干个小段,加上TCP头、IP头发出去。
嗯,这里要注意:TSO虽然降低了CPU开销,但也会带来一些副作用。比如,如果网卡切分不均匀,可能导致接收端产生大量小包,反而增加接收端的处理压力。所以,TSO要和LRO配合使用。
3.4.4 LRO(大接收卸载)
LRO是TSO的逆操作。接收端网卡把多个连续的TCP小段,合并成一个大包,再交给CPU。这样CPU一次处理一个大包,效率高得多。
不过,LRO也有坑。我曾经遇到过一个案例,LRO把多个小包合并后,导致应用层无法正确识别包边界。后来发现是LRO的合并策略太激进,把不同连接的包也合并了。所以,LRO必须严格按连接(五元组)来合并。
注意事项: 在RoCE场景下,TSO和LRO通常不用于RoCE流量本身(因为RoCE是RDMA,不需要TCP分段)。但它们对承载RoCE的TCP/IP控制流(比如连接管理)仍然有效。别搞混了。
3.5 架构总览:一张图说清楚
下面这张图,是我画的一个硬件卸载架构的简化示意图。它展示了数据面、控制面、以及各个加速器之间的关系。
这张图里,主机CPU负责控制面,智能网卡/DPU负责数据面。两者通过PCIe总线通信。硬件加速器(RSS、Checksum、TSO、LRO)位于数据面内部,各自处理特定的卸载任务。
好了,这一章的内容就到这里。硬件卸载架构的设计,核心就是「把对的活交给对的硬件」。数据面追求极致性能,控制面追求灵活可配。加速器则是在性能和复杂度之间找平衡。下一章,我们会深入RoCE的拥塞控制机制,看看硬件是如何处理那些「麻烦」的拥塞信号的。
公众号:蓝海资料掘金营,微信deep3321