ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Xilinx UltraScale+的100G ROCE V2 RDMA实战解析

基于Xilinx UltraScale+的100G ROCE V2 RDMA实战解析 Xilinx FPGA 100G RDMA这套东西我去年在一款Xilinx UltraScale板卡上完整跑通过一次控制面全部走AXI Lite寄存器数据面是自己写的ROCE V2协议逻辑最终实现和商用RDMA网卡互通。这篇文章就把整个项目的选型思路、架构设计、AXI Lite配置细节、ROCE V2协议实现要点和调试过程一起整理出来。如果你正在做类似的事情——准备用FPGA做100G接入、想绕过商用网卡的限制自己控制RDMA协议行为或者刚入手ROCE V2但被协议栈和IP配置卡住那这篇文章值得你花点时间看完。1. 项目背景与整体设计思路1.1 为什么要在FPGA上做100G RDMA先说说项目背景。当时我们做的是存储卸载卡需要在网卡侧直接支持RDMA读写让后端存储节点通过100G ROCE V2网络高速访问前端内存。之所以不买现成的Mellanox网卡是因为数据路径中间还夹着自研的加解密、重删、地址转换逻辑这些必须跟网络入口强耦合插在网卡后面就不成立了。FPGA在这个场景下的优势是数据通路可定制。你可以把接收到的RDMA报文在FPGA内部解析后直接送入自己的加速流水线而不是先到主机内存再绕一圈。另一个优势是和存储控制器的DDR控制器、PCIe DMA、自定义DMA都能无缝集成。但代价也很明显ROCE V2是一种依赖可靠传输的协议有QP状态机、PSN确认、重传、拥塞控制这些机制全用逻辑去实现工作量不小。如果只是做原型验证选一块带100G光口、有DDR4资源、逻辑规模足够的Xilinx UltraScale板卡就够了。我们用的是VCU118级别的板子VU9P芯片带双路100G光口和四组DDR4跑100G ROCE V2没有瓶颈。1.2 协议选型ROCE V2凭什么胜出InfiniBand、ROCE V1、ROCE V2、iWARP这几种协议都支持RDMA语义但落地场景差别很大。InfiniBand要专用交换机成本高iWARP基于TCP对丢包健壮性强但协议栈重、延迟高ROCE V1直接用MAC地址做寻址只能在二层网络跑很难跨子网。ROCE V2把RDMA报文封装在UDP/IP里保留了InfiniBand的BTH头部数据面直接建立在以太网上。这意味着可以用现有的以太网交换机和网管体系同时还能享受RDMA的零拷贝、内核旁路和低延迟。默认使用UDP端口4791交换机不需要特殊配置也能转发只是要保证无损或不丢包才稳定。也正是因为这一点很多高性能存储和AI训练集群都选择了ROCE V2。对于FPGA实现来说ROCE V2的报文格式清晰头部解析和构造全是固定偏移非常适合用流水线做。相比之下iWARP的TCP流管理在FPGA里要实现完整可靠传输复杂度要高一个数量级。1.3 整体架构与数据通路设计我们的系统控制面与数据面是彻底分离的。控制面由主机或管理CPU通过AXI Lite总线向FPGA写寄存器配置MAC地址、IP地址、UDP端口、QP上下文、MR表项。数据面完全靠硬件逻辑跑不经过CPU。TX方向的流程是用户逻辑产生RDMA写请求读本地DDR里的数据然后按配置好的QP上下文和MR表项构造RDMA报文加上BTH、UDP、IP、MAC头送进CMAC100G Ethernet Subsystem发出。RX方向是反过来CMAC收到报文后先做以太网、IP、UDP解析再解析BTH查到对应的QP上下文执行内存读写操作最后按需生成ACK或者读取响应报文。这套架构里最关键的两个模块就是AXI Lite控制通路和ROCE V2协议引擎。前者决定配置是否可靠后者决定通信是否符合RDMA语义并能和标准网卡互通。下面分章节详细拆解。2. 硬件选型与IP配置2.1 FPGA与板卡选择Xilinx官方生态里涉及100G网络的IP主要是CMAC、XDMA、Interlaken、AXI Ethernet等。做ROCE V2的话选择逻辑资源充裕、高速收发器多的UltraScale系列比较稳比如VU9P、VU11P、VU13P这些。VU9P有超过250万个逻辑单元高速收发器支持100GDDR4控制器带宽也够留给协议逻辑余量很大。你要特别注意板卡的光模块形态。100G光模块有QSFP28也有一分四的QSFP到SFP28分支模式。我们用的是双QSFP28接口配合100G SR4模块和MPO光纤连接到对端的ConnectX-6网卡。光模块的兼容性也要提前确认有些模块锁TWI操作或者寄存器映射异常会导致link up不了这些坑后面调试部分细说。2.2 100G CMAC IP关键参数在Vivado里Xilinx的100G Ethernet Subsystem也就是常说的CMAC是必经之路。它负责PCS/PMA、MAC、流控、FEC这些底层功能用户侧拿到的是一个AXI4-Stream接口。IP配置时几个关键点Line Rate选择100G接口数据位宽选择512bit还是1024bit。512bit运行在322.265625MHz1024bit运行在161.1328125MHz。大多数逻辑在322MHz时序能收敛我们选512bit。FEC选项根据对端和光纤链路长度确定。短距离SR4光模块在机柜内互联可以先不开FEC调试距离超过几百米建议开RS-FEC容错能力完全不同。时钟源选择“GT Reference Clock”输入156.25MHzCMAC会自动完成时钟生成。统计和状态接口建议打开调试时看帧计数、CRC错误会方便很多。这里有一个非常重要的原则打开CMAC的“core reset”后不要急着收发数据必须等待gtpowergood、gt_rxresetdone、tx_resetdone这些信号全部拉高才能真正工作。很多刚开始接触100G的人在这里栽跟头以为复位信号给一下就结束了。2.3 XDMA与其他基础IP控制通路如果走PCIe就再加一个XDMA IP用XDMA的AXI Lite从接口映射寄存器空间。我们的场景比较特殊控制面只需要AXI Lite因此直接用AXI Lite Interconnect把寄存器总线引出来既简单又不会有XDMA带来的额外复杂度。另外还要根据应用需要配一个DDR4 MIG控制器用于存放注册内存区域的数据。ROCE V2的写请求最终要落到物理内存读请求要从物理内存取数据。MIG的接口带宽要足够至少是一读一写两个AXI端口否则数据通路会成为瓶颈。AXI Lite Interconnect的地址映射配置要特别小心这是最容易出错但又最基础的一步。每个从端口分配一段地址主机侧写0xA0010000就必须让Interconnect能把这段地址路由到对应的从端口。我们最初因为地址段重叠导致程序写寄存器时数据写进去了但读出来全是0排查了大半天。3. AXI Lite配置通路把控制面做稳3.1 寄存器规划一张表管理所有配置AXI Lite配置通路是整个系统的“方向盘”我们需要把驱动或者测试脚本要写的所有寄存器列出来设计成一张清晰的寄存器映射表。以下是我们实际使用的寄存器布局可以直接参考。偏移宽度名称功能0x0032CTRLbit0软复位bit1ROCE引擎使能bit2回环模式0x0432MAC_LOW本端MAC地址低32位0x0832MAC_HIGH本端MAC地址高16位0x0C32IP_ADDR本端IPv4地址0x1032UDP_PORT本端UDP端口默认47910x1432PEER_MAC_LOW对端MAC地址低32位0x1832PEER_MAC_HIGH对端MAC地址高16位0x1C32PEER_IP对端IPv4地址0x2032PEER_UDP_PORT对端UDP端口0x40 - 0x7F32×16QP_TABLE每个QP的上下文包括QP号、状态、PSN、对端QP号0x80 - 0xFF32×32MR_TABLE内存注册表项包括物理地址、长度、R_Key、L_Key0x1000 - 0x1FFF32×NSTAT_BASE各种统计计数器和状态寄存器只读QP表项的核心字段包括本地QP号24bit、对端QP号24bit、发送PSN、期望接收PSN、QP状态RTS/RTR/ERR、对端IP和UDP端口。MR表项则要记录虚拟地址、物理地址通常是FPGA本地DDR地址、长度、访问权限、键值。在设计寄存器表时我强烈建议把每个表项都做成独立的连续地址空间而不是浓缩到一个寄存器里用位段去塞。位段虽然省地址但驱动侧解析麻烦硬件逻辑也容易在读写时出错。地址空间在FPGA里又不值钱宁可多留空。3.2 AXI Lite时序与常见坑AXI Lite虽然是“Lite”但握手信号一个都不能少。写事务是AW通道和W通道同时发然后等B通道返回读事务是AR通道发出地址后等R通道返回数据。// 一个简单的AXI Lite写寄存器状态机示例 always (posedge clk) begin case (state) IDLE: begin if (wr_start) begin awaddr wr_addr; wdata wr_data; state W_ISSUE; end end W_ISSUE: begin awvalid 1b1; wvalid 1b1; state WAIT_BRESP; end WAIT_BRESP: begin if (bvalid bresp 2b00) begin awvalid 1b0; wvalid 1b0; state IDLE; end end endcase end实际工程中我遇到过几个坑。第一个是AXI Interconnect的地址位宽如果主机侧总线位宽是64位AXI Lite从端口是32位地址的低位对齐处理容易出错。第二个是写寄存器的握手顺序有些IP要求AW和W同时有效分开拉高可能导致事务卡死。第三是寄存器表项的原子性比如一个QP上下文要用连续4个寄存器表示主机侧如果一边写一边有数据包进来逻辑读到一半的状态就可能构造出错误的报文。解决办法是加一个“shadow寄存器组”先全部写入临时寄存器确认完整后再用一个commit寄存器一次性更新到工作寄存器。3.3 上电初始化流程AXI Lite本身不会自动初始化必须由外部主动写寄存器。我们的上电顺序是拉低CTRL的软复位位让协议引擎处于复位状态。配置本端和对端的MAC、IP、UDP端口。写QP_TABLE把所有要用的QP上下文准备好此时QP状态先设为Reset。写MR_TABLE把DDR里可用内存区域注册好分配R_Key和L_Key。全部配置完之后再写CTRL清除软复位同时置位ROCE引擎使能。这里有一个经验GT和CMAC的复位配置完成后一定要等一段时间再开始配置上层协议。光模块的CDR锁定、PCS同步都需要时间通常要等几十毫秒到几百毫秒不等。如果一上电就立刻使能协议引擎很可能因为CMAC还没就绪导致首包丢失。4. ROCE V2核心逻辑实现4.1 报文格式与头部构造ROCE V2报文外层和普通UDP报文长得很像只是在UDP头之后增加了RDMA头部。整体结构是以太网头14字节可选VLANIPv4头20字节IP协议号填17UDPUDP头8字节目的端口固定4791BTH头12字节这是RDMA的核心信息载荷数据SEND数据或RDMA读写的有效负载ICRC4字节覆盖从UDP头到载荷的CRC校验BTH里的关键字段包括操作码OpCode比如SEND、RDMA WRITE、RDMA READ请求、RDMA READ响应、ACK等PKey是分区键两端要一致目的QP号是24位PSN是24位分组序列号用于可靠传输的确认和重传。构造发送报文时我们的流水线是先查QP上下文拿到对端MAC、IP、端口和目的QP号再查MR表拿到本地物理地址和长度然后依次拼接以太网头、IP头、UDP头、BTH最后把数据从DDR搬进发送FIFO。这个过程中IP头里的总长度和校验和是关键UDP的checksum在ROCE V2里大多数网卡不校验但我们还是会算上因为有些交换机的内置诊断会报checksum错误。接收解析时第一步判断目的MAC是否是本端第二步判断IP和UDP端口第三步检查BTH里的目的QP号是否存在且处于可接收状态第四步校验PSN是否连续。全部通过后才把载荷送到DMA引擎。4.2 QP管理与PSN滑动窗口QPQueue Pair可以理解成一个双向通信的端点每对通信双方各持有一个QP。我们的设计里QP上下文存储在Block RAM或URAM中用QP号做索引。QP状态至少要实现Reset、Initialize、RTR、RTS、SQ Error这几个不过实际调试时只要保证RTR和RTS的切换正确就够了。PSN的管理是可靠连接RC的核心。发送方每发一个数据包PSN加一接收方收到一个包后校验PSN是否为期望值。如果连续就返回一个ACK包里面携带期望收到的新PSN。如果PSN不连续说明中间丢了包接收方应该返回NACK发送方则要从重传缓冲区中把丢掉的包重新发一遍。重传缓冲设计是这个项目里最让硬件工程师头疼的部分。协议要求RC模式下数据可靠到达所以每个发出的包都要保留在缓冲区里直到收到对应的ACK才能释放。缓冲区的大小取决于带宽延迟积100G链路假设RTT是2微秒那么窗口内最多有100Gbps乘以2us等于200Kbit也就是大约25KB的数据。考虑到重传发生的时序和队列深度我们实际给每个QP分配了4MB重传缓冲这样才能保证在深队列场景下不丢数据。实际做下来最简单的实现是每个QP维护一个PSN环形队列发送完成后把数据写进重传RAM收到ACK后根据PSN排出对应的条目。这样可以做到精确释放。4.3 内存访问与地址转换ROCE V2的RDMA操作都基于内存区域MR和键值。远端发起RDMA WRITE时报文中携带目的端的R_Key和虚拟地址目的端需要根据这两个信息找到对应的物理地址把数据写入。在FPGA实现里我们没有操作系统和真实MMU所以地址转换逻辑是自己做的。每个MR表项记录起始虚拟地址、长度、物理地址FPGA本地DDR基地址、R_Key、L_Key、访问权限。收到写请求后硬件用报文里的目的虚拟地址和R_Key去查表校验虚拟地址是否落在注册区间内再通过基址偏移换算成物理地址。这里有个容易忽略的问题R_Key本身有校验机制。标准RDMA网卡会用R_Key中的高8位作为“内存窗口索引”而我们还额外要求R_Key匹配表项才能执行读写。如果校验不严任何知道IP和端口的节点都可以读你的内存在存储场景下这是不可接受的。5. 100G数据通路与性能调优5.1 从CMAC到用户逻辑的接口CMAC的用户侧接口是AXI4-Stream。在512bit位宽模式下每个时钟周期可以传输64字节322MHz下刚好接近100G线速。接口信号中除了tdata、tvalid、tready、tkeep外tuser也很重要用来标识帧的开始和结束。数据通路设计上要保证每个时钟周期都能接受一个完整的字否则就会掉带宽。我们的TX流水线做了两级缓冲第一级是发送描述符队列第二级是数据FIFO。启动发送时先查描述符拿到对应的DDR地址、长度、目标QP信息然后发起DMA读数据流进FIFO后再按帧组织好送进CMAC。对于RX方向CMAC输出的报文直接进解析模块。解析模块第一拍判断帧类型第二拍剥离头部第三拍提取载荷地址信息并触发DMA写。为避免背压DMA写接口的ready信号必须保持足够长的综合表现否则CMAC的FIFO满了之后会拉低tready导致RX暂停。5.2 时钟复位与FEC100G CMAC的复位设计比普通MAC严格得多。Xilinx推荐的做法是用GT复位控制器统一管理GT的复位然后等待各resetdone信号就绪。我之前图省事直接在系统复位里拉一下PCS复位就完事结果link status起来了但抓包全是错误检查发现是GT TX没有从复位中恢复。FEC的问题是很多项目的隐藏雷。如果你的对端设备开启了RS-FEC而FPGA侧的CMAC没有开启会出现link能up但误码率极高的现象。反过来你开了FEC而对方没开也会导致各种CRC错误。建议100G互联场景两端统一配置长距离链路优先开RS-FEC(544,514)。FEC还有一个副作用是增加延迟RS-FEC的编解码处理要几微秒。对于延迟极度敏感的场景比如多级交换网络里的同步操作可以评估是否值得为了抗误码牺牲这部分延迟。我们在同机房VCSEL短距离场景最终选择不开FEC延迟能低一个档位。5.3 性能瓶颈与优化手段从最终测试结果看单路100G ROCE V2的RDMA写带宽可以跑到线速的90%以上。我们实测无FEC、SR4光模块、对端ConnectX-6网卡RDMA写带宽大约91GbpsFPGA到FPGA之间甚至能接近线速。性能卡点主要在三处DMA读带宽、重传缓冲的RAM带宽、以及头部分析流水线的阻塞。DMA读带宽要注意MIG控制器的bank管理和突发长度。二选一要么用AXI4接口配置成最大突发256拍要么拆成多个通道并行访问不同的DDR rank。我们在VU9P上用了两个DDR4控制器一个专门给写请求的数据搬运用另一个给读请求的数据搬运用避免读写仲裁互相拖累。重传缓冲用URAM实现URAM容量大且排列密集带宽比BRAM差一点但做好两端口乒乓访问后不是瓶颈。真正的问题在于PSN窗口管理逻辑确认包回来时如果同时有大量排队的重传块要释放必须用FIFO做异步处理。我们在一次测试中因为释放逻辑处理不过来导致新发送的包被等待队列堵住带宽掉到70%。后来改成“释放请求进FIFO后台逐条处理发送不等待释放完成”的方式问题才解决。头部分析的流水线则要注意一次处理一整个64字节字。如果每个时钟周期都能完成一个帧的头部解析那么理论吞吐就能跟上。我们实际上把头部解析拆成了四拍流水每拍只做简单的比较和提取最终能稳定跑到322MHz。6. 调试经验与常见问题排查6.1 从Loopback到端到端的调试路径100G ROCE V2开发最忌讳一亮机就做端到端测试那样一旦失败根本不知道问题出在哪层。我们采用分层的调试路径CMAC内部回环在CMAC IP内部把TX回环到RX用ILA抓接口信号确认MAC侧数据通路完整。光模块远端回环用一根MPO回环线连接光模块的TX和RX测试SerDes和光模块通路的稳定性。ICMP/UDP测试在CMAC上层写一个简单的UDP echo模块主机用ping或者UDP包去测确认IP/UDP层工作正常。ROCE V2互通对端换成RDMA网卡用perftest工具发起读写FPGA侧用ILA抓BTH解析结果。每一步都要有明确的判定标准。比如CMAC回环测试至少要跑满10秒钟不出CRC错误才敢继续往下走。光模块回环更是要测半小时以上因为小概率误码需要长时间才能暴露。6.2 高频问题速查表现象可能原因解决方案端口物理link up但CMAC侧无收发统计CMAC或GT复位未完全释放光模块firmware异常检查gtpowergood、gt_rxresetdone按顺序执行GT复位抓到大量错误帧或CRC错误FEC配置不匹配光纤或模块质量差排查两端FEC配置更换模块/线缆验证ROCE连接建不起来对端设备报timeoutUDP端口不是4791QP上下文里对端QP号错误核对UDP端口和BTH中目的QP号用ILA抓发出去的头部寄存器写不进去或读回来不对AXI Interconnect地址映射配置错误数据位宽不匹配检查地址段映射确认32bit对齐用ILA抓AXI时序RDMA写带宽远低于预期DMA读冲突、重传缓冲释放阻塞、PSN窗口太小分别测DMA裸带宽增加重传缓冲和QP窗口随机偶发丢包队列深度不足RX路径背压处理不好增加FIFO深度优化tready信号生成逻辑调试工具上ILA的采样深度一定要拉高。数据位宽512bit采样深度至少32768否则抓几个包就被填满了看不到完整的事件序列。另外我强烈建议在ROCE引擎里加一组硬件计数器专门统计发送包数、接收包数、ACK数、NACK数、重传次数这些计数器要比任何在线逻辑分析仪都好用因为测试跑几小时后看计数器就能定位问题趋势。6.3 实测数据与心得整套系统最终稳定运行后我们对端用ConnectX-6做RDMA写和读测试。无FEC、SR4模块、房间内短距离光纤条件下RDMA Write带宽约91GbpsRDMA Read带宽约85Gbps。往返延迟在1.5微秒左右其中包含了FPGA的逻辑处理和网卡的协议开销。FPGA到FPGA的直连测试里延迟能降到0.9微秒附近。这个项目做下来我最大的体会是ROCE V2的协议逻辑本身并不算难真正难的是把100G通路上的每一个环节都调稳。链路层一个错误的FEC配置数据面一个不合理的背压控制面一个不仔细的地址映射都会让整体性能崩盘。另外一个值得分享的技巧是寄存器配置的回归测试。我们在主机侧写了一套Python脚本每次修改完逻辑后先通过AXI Lite把所有寄存器值读出来和预期比对再跑一轮perftest。这套回归测试在后续迭代中救了我很多次因为改了协议解析逻辑后经常出现某些寄存器配置被连带破坏的情况没有自动化比对根本发现不了。如果你也在做类似的项目建议先从点对点静态配置打通再考虑CM握手自动建链先保证无错跑通再谈拥塞控制。ROCE V2里的ECN和CNP处理可以等基础收发稳定之后再加否则调试复杂度会呈几何级增长。
返回列表