第1章:低延迟网络栈:TCP/IP卸载引擎(TOE)、UDP硬件加速、MAC层与PHY层直连
各位做高频交易的朋友,咱们开门见山。
网络延迟,是量化交易系统的命门。你想想看,别人从网卡收到行情到你策略算出信号,这中间哪怕多一个微秒,可能就错失了一笔交易。我见过太多团队,CPU侧优化到极致了,结果瓶颈卡在网络协议栈上。
说白了,标准Linux内核的网络栈,是为通用场景设计的。它要处理丢包重传、要管理内存、要调度进程。这些功能在高频交易里,全是累赘。我们要的,就是让数据从网线到FPGA逻辑,走一条最短的路径。
1.1 TCP/IP卸载引擎(TOE)——把CPU从协议处理中解放出来
TCP协议,可靠是可靠,但代价不小。三次握手、滑动窗口、校验和计算、ACK确认……这些操作如果让CPU来做,延迟和抖动都很大。我个人习惯,在FPGA里直接实现一个TOE核。
TOE的核心思路很简单:把TCP/IP协议栈的处理逻辑,从软件搬到硬件。FPGA里的状态机直接解析以太网帧、IP头、TCP头,然后提取出有效载荷。CPU只需要读数据就行,不用管协议细节。
关键点:TOE不是简单地加速,而是彻底卸载。CPU不再参与任何TCP连接管理、重传计时、拥塞控制。这些全由FPGA逻辑完成。
我在项目中遇到过一个问题:标准TOE核为了兼容性,会实现完整的TCP状态机,包括慢启动、拥塞避免等。但在高频交易场景下,我们通常只跟少数几个交易所服务器通信,网络环境相对可控。所以,我建议做定制化的TOE——只保留必要的功能,砍掉那些为了通用性而存在的冗余逻辑。
举个例子,我们不需要复杂的拥塞控制算法。交易所服务器通常就在隔壁机房,网络质量很好。我们可以把重传超时时间设得很短,甚至直接禁用重传(如果上层应用能容忍丢包)。这样,延迟能再降一个数量级。
避坑指南:我曾经在一个项目里直接用了开源的TOE核,结果发现它在高吞吐下会偶尔丢包。查了三天,发现是内部FIFO深度不够。后来我改成乒乓缓冲结构,问题才解决。所以,用TOE核之前,一定要做充分的压力测试。
1.2 UDP硬件加速——简单粗暴,延迟最低
如果交易所支持UDP协议,那恭喜你,你离极限延迟又近了一步。UDP没有连接管理,没有重传,没有拥塞控制。它就是一个“发出去就不管”的协议。在FPGA里实现UDP加速,比TCP简单得多。
UDP硬件加速的核心,就是让FPGA直接处理UDP数据报的封装和解封装。我们只需要解析UDP头(源端口、目的端口、长度、校验和),然后提取数据。整个过程,几个时钟周期就能完成。
我建议的做法是:在FPGA里实现一个UDP offload引擎。它接收MAC层传来的数据,检查UDP校验和(可选,如果链路可靠可以跳过),然后根据目的端口号,把数据分发到不同的处理通道。比如,行情数据走一个通道,交易指令走另一个通道。
// 简化的UDP解析逻辑(Verilog风格描述)
always @(posedge clk) begin
if (rx_valid && mac_type == 16'h0800) begin // IP包
if (ip_protocol == 8'h11) begin // UDP协议
udp_dst_port <= rx_data[47:32]; // 提取目的端口
udp_length <= rx_data[31:16]; // 提取长度
// 校验和可选,直接跳过
payload_start <= 1'b1; // 标记数据开始
end
end
end
你看,就这么几行逻辑,UDP包就解析完了。没有中断,没有上下文切换,没有内存拷贝。数据直接从网线进FPGA,然后被送到你的策略逻辑里。
注意:UDP虽然快,但不可靠。如果链路有丢包,你的策略需要自己处理。我见过有人直接用UDP做交易指令传输,结果丢了一个包,订单没发出去,损失惨重。所以,UDP加速适合行情接收,交易指令还是建议用TCP或者带应用层确认的UDP。
1.3 MAC层与PHY层直连——绕过一切软件栈
这是终极方案。说白了,就是让FPGA直接控制物理层(PHY)和介质访问控制层(MAC)。不走操作系统,不走驱动,甚至不走任何软件。FPGA里的逻辑直接跟PHY芯片对话。
标准做法是:FPGA内部实现一个MAC核,通过GMII/RGMII/XGMII接口连接到外部PHY芯片。PHY芯片负责把数字信号转换成模拟信号,发到网线上。反过来,PHY从网线收到模拟信号,转换成数字信号,交给FPGA的MAC核。
这样做的好处是什么?零软件开销。数据从PHY到FPGA逻辑,延迟只有几个纳秒。而且,我们可以完全控制MAC层的行为。比如,我们可以自定义帧间隙、可以调整前导码长度、可以禁用CRC校验(如果链路可靠)。
核心思路:MAC层和PHY层直连,意味着FPGA就是网卡。没有PCIe总线延迟,没有DMA传输延迟,没有驱动中断延迟。数据流是:网线 → PHY → FPGA逻辑 → 策略处理。全程硬件。
我记得有一次,我们测试一个第三方网卡,发现它的PHY芯片到MAC核之间有一个内部FIFO,引入了大约100纳秒的延迟。后来我们改用FPGA直连PHY,自己实现MAC,把那个FIFO去掉了,延迟直接降了80纳秒。别小看这80纳秒,在高频交易里,这就是胜负手。
知识体系总览
下面这张图,是我画的低延迟网络栈的核心结构。你可以看到,从网线到应用数据,我们砍掉了所有不必要的中间层。
这张图展示了我们追求的目标:每一层都尽可能精简,每一层都直接由硬件处理。没有操作系统,没有驱动,没有中断。数据流是单向的、流水线式的,延迟可以精确到纳秒级别。
总结一下
低延迟网络栈的核心,就是三个字:去软件化。TOE把TCP协议卸载到硬件,UDP加速让无连接协议跑得更快,MAC与PHY直连彻底绕过软件栈。这三板斧下去,网络延迟可以从几十微秒降到几百纳秒。
嗯,这里要注意一点:不是所有场景都需要这么极致的优化。如果你的交易策略是分钟级别的,那标准网卡加内核协议栈完全够用。但如果你做的是纳秒级高频交易,那这条路,你必须走。
我个人习惯,在设计网络栈之前,先搞清楚两个问题:第一,交易所支持什么协议?第二,你的策略能容忍多大的延迟抖动?搞清楚这两个问题,再决定用TOE还是UDP加速,还是直接MAC直连。
我曾经在一个项目中,为了追求极致延迟,把所有协议校验都跳过了。结果遇到一次网络故障,数据全错,策略亏了一周。从那以后,我学会了在速度和可靠性之间找平衡。你可以快,但不能傻快。
我的建议:先做UDP加速,因为它简单、延迟低。如果交易所要求TCP,再上TOE。至于MAC直连,那是终极武器,非必要不用。毕竟,维护一个完整的硬件MAC核,工作量不小。