第4章:网络协议基础

做低延迟交易,说白了就是跟网络协议打交道。你想想看,行情数据从交易所出来,经过网线、交换机、网卡,最后到你的FPGA逻辑,这一路上每一层协议都在“扒皮”。今天我就带你把这些协议扒个干净。

4.1 以太网帧结构

以太网帧是网络通信的“最小单元”。我刚开始做FPGA网络处理时,第一件事就是对着逻辑分析仪看帧结构。嗯,这东西其实不复杂。

标准以太网帧结构(IEEE 802.3)

字段长度(字节)说明
前导码7同步时钟用,FPGA接收时用来锁定位同步
帧起始定界符1标志帧开始,值为0xD5
目的MAC地址6接收方网卡地址
源MAC地址6发送方网卡地址
类型/长度20x0800表示IP,0x0806表示ARP
数据载荷46-1500上层协议数据
帧校验序列4CRC32校验

这里有个坑。我曾经在项目中遇到一个奇怪的问题:FPGA收到的帧总是丢包。查了半天,发现是前导码处理不对。很多FPGA的MAC核会自动剥离前导码,但如果你自己写RGMII接口,就得手动处理这7个字节。说白了,前导码就是给接收端“热身”用的,别把它当数据存起来。

4.2 ARP协议

ARP协议解决的是“我知道你IP,但不知道你MAC”的问题。在低延迟交易场景下,ARP其实是个麻烦事——它会产生广播风暴。

我个人习惯的做法是:在FPGA里做一个ARP缓存表,把交易对手的MAC地址硬编码进去。为什么?因为交易链路是固定的,不需要动态学习。你想想看,每次行情来了还要先发个ARP请求,那延迟就上去了。

ARP报文结构

  • 硬件类型:0x0001(以太网)
  • 协议类型:0x0800(IP)
  • 操作码:1=请求,2=应答
  • 发送方MAC/IP、目标MAC/IP

我记得有一次调试,发现FPGA发的ARP请求没人理。后来一查,是目标MAC地址填错了。ARP应答里目标MAC是广播地址(FF:FF:FF:FF:FF:FF),但请求里目标MAC得填全0。这种细节,文档上写得很清楚,但实际做起来就容易忘。

4.3 IP协议

IP协议负责把数据包从源地址送到目的地址。在FPGA里处理IP,核心就是解析头部、校验和计算。

IPv4头部(20字节固定部分)

字段长度说明
版本/首部长度1字节版本4,长度通常为5(20字节)
服务类型1字节低延迟场景常设高优先级
总长度2字节包含头部和数据
标识/标志/片偏移4字节分片用,交易场景很少用
生存时间1字节防止环路,通常设64
协议1字节17=UDP,6=TCP
头部校验和2字节只校验头部,不校验数据
源IP地址4字节32位IP
目的IP地址4字节32位IP

校验和计算是FPGA的强项。用流水线做,一个时钟周期就能算完。我一般用补码求和再取反的方式,注意每16位累加一次,最后把进位加回去。嗯,这里有个细节:IP校验和只覆盖头部,UDP校验和才覆盖数据。别搞混了。

4.4 UDP协议

UDP是低延迟交易的首选。为什么?因为它简单、无状态、延迟低。说白了就是“发出去就不管了”。

UDP头部(8字节)

字段长度说明
源端口2字节发送方端口
目的端口2字节接收方端口
长度2字节UDP头部+数据的总长度
校验和2字节可选,0表示不校验

在FPGA里解析UDP,我建议直接按字节流处理。收到以太网帧后,先剥掉MAC头(14字节),再剥掉IP头(20字节),剩下的就是UDP头+数据。整个过程用状态机控制,非常简单。

注意:UDP校验和在低延迟场景下经常被设为0。为什么?因为计算校验和需要遍历整个数据包,这会增加延迟。但如果你做的是金融交易,数据完整性很重要,我建议还是算一下。我曾经见过因为UDP校验和错误导致订单数据损坏的案例,那损失可不小。

4.5 TCP协议

TCP协议在低延迟交易里用得少,但也不是完全不用。比如一些管理通道、配置通道会用TCP。TCP的核心是可靠传输,但代价是延迟高。

TCP头部比UDP复杂得多,有20字节固定部分,还有可选字段。关键字段包括:

  • 序列号/确认号:保证数据有序到达
  • 标志位:SYN、ACK、FIN等,控制连接状态
  • 窗口大小:流量控制用
  • 校验和:覆盖头部和数据

在FPGA里实现TCP协议栈,说实话挺麻烦的。状态机要处理连接建立、数据传输、连接释放、重传、拥塞控制……我建议除非必要,否则别在FPGA里做完整的TCP。用UDP+应用层确认机制,延迟更低,实现也更简单。

我的建议:交易链路用UDP,管理通道用TCP。这样既保证了低延迟,又保留了管理功能的可靠性。我在一个项目中就是这么做的,效果很好。

4.6 知识体系总览

下面这张图展示了网络协议栈在FPGA处理中的层次关系。从物理层到应用层,每一层都有对应的处理模块。

FPGA网络协议处理层次 应用层 交易应用逻辑(订单处理、行情解析) 传输层 UDP/TCP头部解析与校验和计算 网络层 IP头部解析、路由查找、校验和验证 数据链路层 MAC地址过滤、帧校验(CRC32) 物理层 RGMII/SGMII接口、时钟恢复、位同步 数据流向 FPGA处理

这张图我画了很多次。每次给团队新人讲网络协议处理,我都会先让他们看这张图。你想想看,从网线进来的数据,先经过物理层恢复时钟和位同步,然后数据链路层做MAC过滤和CRC校验,网络层解析IP头部,传输层处理UDP/TCP,最后应用层才拿到真正的交易数据。每一层都有延迟,每一层也都有优化的空间。

避坑指南:我曾经在项目中遇到一个问题——FPGA收到的UDP包校验和总是错。查了两天,发现是IP头部的总长度字段填错了。UDP校验和计算时要用到IP头部里的总长度,如果这个值不对,校验和肯定算不对。所以,写FPGA代码时,一定要确保每个字段的值都是正确的,别想当然。

好了,网络协议基础就讲到这里。这些协议看起来简单,但实际在FPGA里实现时,每个细节都可能成为性能瓶颈。下一章我们会深入讲如何在FPGA里高效实现这些协议的解析和生成。


公众号:蓝海资料掘金营,微信deep3321