Exablaze Exanic X25 网卡介绍

Exablaze Exanic X25

Exanic X25 是目前金融交易领域常见的一款 FPGA 加速网卡,通常被用在行情接收侧用极致的速度接收来自交易所的行情组播(交易侧几乎已经被 Solarflare 一统天下了)。

X25 其实还有一个名字,K3PS (Cisco Nexus K3P-S FPGA SmartNIC),Exablaze 是澳洲一家专门做 HFT 网络设备的公司,后面被 Cisco 收购了,Cisco 收购之后就给 X25 改了个新名字叫 K3PS, 甚至现在卡上面没有任何一个地方印了 X25 的字样,不过大家仍然习惯叫它 X25~

虽然 Exablaze 网卡线被收购之后就有点摆烂,很久没有新产品和新 feature 了,但是 X25 仍然是一款非常优秀的遗产!

X25 的核心卖点就是,极致的低延迟,双向穿透延迟只要 568ns!

普通的网卡双向穿透延迟大概是在几十微秒级别,而普通的低延迟卡,通常也只能做到 1-2us 量级;即使是 X25 最强有力的竞争对手,X4522 也需要 590ns,上一代的 X2522 则更慢一点需要 750ns。

除了 568 ns 的穿透延迟,官方介绍的核心卖点还有这些:

  • FDK 可编程(Solarflare X2 X4 系列卡就是纯 ASIC 不能编程)
  • Cut-through 流式 RX

  • TX 模板预加载

  • exasock socket 库(当然其实这个算是个减分项。。。)

  • 4ns 精度硬件时间戳

总的来说,是一款既性能极致又功能丰富的网卡。

Exanic X25 实物 1 Exanic X25 实物 2 Exanic X25 实物 3

网卡收包路径

从光信号 -> 用户态字节,X25 的收包路径大概是:

  1. 光信号
  2. SFP28 模块光电转换,把光信号转化为电信号
  3. 收发器 CDR 恢复时钟、解串成 66b 字
  4. PCS 块同步 66b 解码
  5. MAC 分帧
  6. (optional)用户自定义 FPGA 开发逻辑处理
  7. flow steering 选环
  8. 攒够 120B 数据 or 帧结束
  9. PCIe 直接把 128B 数据写入 Host 内存 2MB Ring (卡上不缓冲、无流控)
  10. exanic_receive_chunk 用户态轮询到数据
  11. 返回给用户态程序自行读取处理

X25 收包路径

相较于常规网卡,X25 收包不一样的部分在于,首先 X25 支持 Cut-through 流式,阶段 8 的时候,假设收到一个 1200B 的以太网帧,常规的网卡是 Store-and-Forward 模式,需要等这个 1200B 全部处理完,然后才能发起 DMA 写入,而 X25 收到前 120 字节之后就可以发出,流式读取,一边网卡上还在收着帧呢,一边用户态就已经可以开始处理了,可以极大减少网络包前部的延迟;不过代价是用户可能全部处理完之后才发现 CRC 校验没过~

另外第 9 阶段,常规网卡通常是在用户态会有一个 RX Descriptor Ring,每次网卡需要先取一些 descriptor,然后再写入到 descriptor 指向的内存,写完还得回写 descriptor 的状态,然后通过中断通知 CPU 写完了,descriptor 存在的意义本质上是“内存归软件管”,网卡只有使用权,网卡需要为这套灵活性的机制付出一些性能税。

而 X25 则只有一个简单的 RX Ring,非常非常粗暴,ring 固定 2MB、chunk 固定 128B、地址由 base 加计数器直接算出, 也没有节流机制,网卡就粗暴的来了包就 Cut-Through 搬过去,溢出了就直接覆盖了,用户态进程要是消费不过来,那是你自己问题,反思一下是不是消费的不够快,是不是哪里有 bug。

甚至 X25 也不支持中断 or 通知机制,你只能一直轮询那个 ring,一直不断地轮询,这样 CPU 开销会非常巨大,不过会用这种卡的用户为了延迟通常是不会吝啬一个 isolated CPU 核心的。

网卡发包路径

从用户态发出去 -> 网卡设备光信号进入光纤,流程如下:

  • 调用用户态 API exanic_transmit_frame
  • 封装 tx_chunk 通过 mmap 的 write-combining 映射写入卡上
  • CPU 每 64B 一个 PCIe 写入网卡上的 buffer,最后 flush WC 清除残留
  • doorbell 写 TX 寄存器,写入帧起始 offset 通知网卡开始工作
  • MAC 封帧
  • PCS 64b/66b 编码、加扰
  • 收发器并串转换
  • SFP28 电 -> 光
  • 卡把 feedback_id 回写到主机 feedback slot,通知发送完成

X25 发包路径

发包和常规网卡本质区别在于,常规网卡是 pull 模式发包,而 X25 是 push 模式,这个速度差距应该就不言而喻了。

常规模式网卡是先要把要发送的完整报文在拼装好,放到内存里面,可能是 kernel 封的,也有可能是一些用户态的库封的,anyway 封好之后,申请 TX Descriptor 然后 doorbell 通知网卡,网卡再通过 DMA 读取对应的内存地址数据,后面的流程就基本都一样了,MAC、线路编码、并串转换、变光。

X25 之所以使用 TX 网卡上的 TX Buffer,而不是 CTPIO 路线,其实它是赌一个场景:本身这个卡就是为了金融高频交易领域设计的,用户拿它的卡出方向无非就是报单,他就笃定报单的时候,报文是一个非常固定的模板,每次可能只要改动价格、数量、合约这几个少数的字段,然后直接 doorbell 即可,而其他大部数字段都是不需要改变的。

所以它在 TX Buffer 的基础上面做了一招“预加载”:用户可以先把要发送的报文模板预先写到 TX Buffer 里面,等 PCIe 过来的时候,就只修改几个特定位置的数据然后直接发送,能降低关键路径上发送完整报文的部分开销。

用户态 API

exanic sock 用起来也很简单,真正重要的函数只有三个:

  • exanic_receive_chunk
  • exanic_receive_frame
  • exanic_transmit_frame

收包的话,就是用这两个 recv API,receive_chunk 就是单独接收一个 120B 的 cut-through 网络包块,recv_frame 就是接收一个完整的帧,跟别的 socket API 用起来更像,但是底层其实就是循环调用 recv_chunk 然后把这些 chunk 拼成一个完整的帧,算是前者的一个包装函数。

发包的话,就是常规发送的 API,但是如果要用模板发送功能的话,就要拆成两个 API

  • exanic_begin_transmit_frame
  • exanic_end_transmit_frame

有点类似数据事务,在中间这个期间这个 handle 是不能发别的帧的,通常来说,要结合业务场景去利用这个功能。

比如说金融领域的报单场景,通常每一次报完单之后,就可以立刻调用 begin_frame 然后 mmap 把模板准备好,等下一次订单到来的时候,直接 mmap 修改关键参数,然后调用 end_frame 发出即可。

参数对比

跟类似竞品的参数对比表格我整理了一份,如下:

X25 X10 X2522 X4522 U50
上市时间 2020-01 2016-02 2018 2025-10 2019-08
厂商 / 血统 Exablaze → Cisco(Nexus K3P-S) Exablaze → Cisco(Nexus K35-S) Solarflare → Xilinx → AMD AMD Solarflare Xilinx → AMD Alveo
定位 低延迟 NIC,FPGA 可编程 低延迟 NIC,FPGA 可编程 ASIC 低延迟 NIC,kernel bypass ASIC 低延迟 NIC,Express / Enterprise 双数据通道 通用 FPGA 加速卡,自己开发固件
穿透延迟¹ 568ns 最低 / 696ns 中位,raw 帧 780ns 中位,raw 帧 750ns ½RTT @25G / 819ns @10G,ef_vi 32B 590ns ½RTT @10G,ef_vi 4B(X4542 数据,同代) vendor 估算 T2T <0.5µs,无可比口径
FPGA / 芯片 Xilinx Kintex UltraScale+ XCKU3P-2 Xilinx Kintex UltraScale XCKU035-2 Solarflare SFC9250 ASIC AMD NS9480 ASIC Xilinx UltraScale+ XCU50(2 SLR)
端口 2× SFP28,25G / 10G / 1G / 100M(25G 靠固件) 2× SFP+,10G / 1G / 100M 2× SFP28,25G / 10G 2× SFP56,50G / 25G / 10G 1× QSFP28,100G / 40G / 4×25G / 4×10G
PCIe Gen3 x8(硬核封顶 8 GT/s) Gen3 x8 Gen3 x8 Gen5 x8 Gen3 x16 或 Gen4 x8(PCIE4C 硬核),可拆双 x8
硬件时间戳 4ns(datasheet,User Guide 写 6.2ns) 6.2ns(161.13 MHz 计数器) 硬件粒度 <8ns,API 1/4ns 分辨率 API 亚 ns 分辨率(Onload 9.0+),硬件粒度未公开 由固件决定
发送路径 卡上 TX buffer 128KiB/port,可选 1MB 固件(+20ns),支持 preload 卡上 TX buffer 128KiB/port,支持 preload PIO(16× 4KB buffer)+ CTPIO CTPIO(PCIe cut-through),无 PIO 由固件决定
硬件过滤 128 IP + 64 MAC 规则/port,零延迟代价 128 IP + 64 MAC 规则/port,零延迟代价 硬件 filter + 组播硬件复制 Enterprise 通道硬件复制,Express 通道无(需 SHRUB) 固件内解码过滤
卡上内存 可选 4GB DDR4(仅 FDK 用) 无 无 无 8GB HBM2,无 DDR
软件栈 libexanic / exasock,驱动 exanic libexanic / exasock,驱动 exanic ef_vi / TCPDirect / Onload,驱动 sfc ef_vi / TCPDirect / Onload,驱动 sfc 驱动enyx_hfp
可编程 FDK,用户逻辑进 FPGA fabric FDK,用户逻辑进 FPGA fabric 不可 不可 Vitis / 厂商 bitstream
形态 / 功耗 Low-profile,117×68mm,0–55°C Low-profile,117×68mm,0–55°C Low-profile Low-profile,<25W,被动散热 HHHL,75W,被动散热

注: ExaNIC 口径是单机进一次出一次:X25 datasheet 叫 trigger-to-response,X10 datasheet 叫 application to network to application;Solarflare 口径是 ping-pong 的 ½RTT。三者都穿两次 PCIe,数量级可比,测试主机和年代不同。

Last Words

总的来说,X25 确实是张很完美的卡,但是 Solarflare X5522 如果来了呢?不再更新的产品线总归是要被淘汰的。