DPU智能网卡FPGA落地方案
> 目标:从工程可落地角度,给出一套可实施的 DPU FPGA 设计方案。重点:
>
> 1) 以 DPDK 规范组织数据面和控制面;
> 2) 用布谷鸟(Cuckoo)Hash 做高速流表;
> 3) 明确 FPGA 如何通过外围设备与接口控制实现完整业务闭环;
> 4) 给出“虚拟地址替换(VA rewrite)”实例,确保可落地。
---
1. 方案定位与目标边界
本方案面向:
• FPGA + PCIe 的智能网卡/DPU 形态
• 主机侧使用 DPDK(用户态高速收发)
• 数据面在 FPGA,控制面在主机(驱动/DPDK 应用)
目标能力:
• L2/L3/L4 解析 + 流分类 + 动作执行
• 支持队列化收发(多队列)
• 支持 DPDK 流规则下发(rte_flow 对应硬件规则)
• 支持线速方向的数据面转发(按器件能力)
非目标(第一版可不做):
• 完整 SR-IOV 虚函数生态
• 全栈加密卸载(IPsec/TLS)
• 复杂拥塞控制算法全实现
---
2. DPDK 规范驱动的总体架构
2.1 逻辑分层
+--------------------------------------------------------------------------------+
| Host Userspace |
| DPDK App (rte_ethdev / rte_flow / rte_mbuf / rte_ring / lcore poll loop) |
+------------------------------------+-------------------------------------------+
| PMD + UIO/VFIO
+--------------------------------------------------------------------------------+
| Host Kernel/Driver Layer |
| PCIe BAR / MSI-X / DMA queue management |
+------------------------------------+-------------------------------------------+
| PCIe Gen4/Gen5
+--------------------------------------------------------------------------------+
| FPGA DPU |
| Control Plane: BAR registers + rule loader + stats |
| Data Plane: Parser -> KeyBuilder -> CuckooHash -> Action -> Queue -> DMA |
| Peripherals: DDR/HBM, MAC/PCS/PMA, PHY MDIO, I2C(SFP/QSFP), PTP timer |
+--------------------------------------------------------------------------------+
2.2 与 DPDK 的接口映射
• rte_eth_rx_burst / tx_burst → 硬件 SQ/CQ 队列 + Doorbell
• rte_mbuf → 描述符中的地址、长度、offload flags、RSS hash 等字段
• rte_flow → 硬件流表项(match + action)
• rte_eth_stats_get → 硬件统计寄存器
结论:
• 硬件接口设计要“天然对齐 DPDK 概念”,这样 PMD 实现最清晰。
---
3. DPDK 规范下的硬件队列与描述符设计
3.1 队列模型(建议)
• RXQ[N]:网口入包 -> FPGA 分类 -> DMA 到主机内存
• TXQ[N]:主机提交要发包的数据 -> FPGA 取包 -> 网口发包
• CQ[N]:完成队列,回传状态(DONE/ERR/RETRY)
3.2 描述符字段建议(面向 DPDK)
struct dpu_desc {
addr // host physical/I/O virtual address (IOMMU场景)
len // packet length
ol_flags // csum/tso/vlan/rss 等
queue_id // queue index
flow_tag // flow id / mark
status // done/error code
rss_hash // optional
}
关键点:
• 硬件描述符要覆盖 DPDK mbuf 的关键语义字段。
• 状态回写必须可批量化,减少中断压力。
3.3 Doorbell 与中断策略
• Doorbell:主机写 SQ_TAIL 告知硬件新任务
• 完成回收:主机读 CQ 并写 CQ_HEAD
• 中断建议:MSI-X + 合并阈值(按包数/时间)
3.4 对应寄存器地址规划(实装模板)
> 说明:下面给的是“可直接用”的 BAR0 地址规划框架,字段可按项目裁剪。
| 偏移 | 寄存器名 | 位域 | 属性 | 说明 |
| -----: | ---------------- | ------------------------------------------- | ---- | ---------------------- |
| 0x0000 | DEV_INFO | [31:24] MAJOR, [23:16] MINOR, [15:0] DEV_ID | RO | 版本与设备标识 |
| 0x0004 | GLOBAL_CTRL | [0] EN, [1] SOFT_RST, [2] SAFE_MODE | RW | 全局使能与复位 |
| 0x0008 | GLOBAL_STATUS | [0] READY, [1] ERR, [2] LINK_UP | RO | 全局状态 |
| 0x0010 | RXQ_BASE_LO(n) | 32-bit | RW | RXQ n 基址低位 |
| 0x0014 | RXQ_BASE_HI(n) | 32-bit | RW | RXQ n 基址高位 |
| 0x0018 | RXQ_SIZE(n) | [15:0] entries | RW | RXQ 深度 |
| 0x001C | RXQ_TAIL_DB(n) | [15:0] tail | WO | RXQ doorbell |
| 0x0020 | TXQ_BASE_LO(n) | 32-bit | RW | TXQ n 基址低位 |
| 0x0024 | TXQ_BASE_HI(n) | 32-bit | RW | TXQ n 基址高位 |
| 0x0028 | TXQ_SIZE(n) | [15:0] entries | RW | TXQ 深度 |
| 0x002C | TXQ_TAIL_DB(n) | [15:0] tail | WO | TXQ doorbell |
| 0x0030 | CQ_BASE_LO(n) | 32-bit | RW | CQ n 基址低位 |
| 0x0034 | CQ_BASE_HI(n) | 32-bit | RW | CQ n 基址高位 |
| 0x0038 | CQ_SIZE(n) | [15:0] entries | RW | CQ 深度 |
| 0x003C | CQ_HEAD_DB(n) | [15:0] head | WO | CQ 回收 doorbell |
| 0x0040 | FLOW_LOAD_CTRL | [0] LOAD, [1] COMMIT, [2] ROLLBACK | RW | 规则事务控制 |
| 0x0044 | FLOW_LOAD_STATUS | [0] BUSY, [1] ERR, [15:8] ERR_CODE | RO | 规则装载状态 |
| 0x0048 | FLOW_KEY_CFG | key format bits | RW | key 选择(5元组/隧道) |
| 0x004C | FLOW_HASH_CFG | hash seed/alg | RW | hash 参数 |
| 0x0050 | FLOW_TBL_STAT | hit/miss/stash | RO | 流表统计 |
| 0x0054 | FLOW_STASH_STAT | stash hit/overflow | RO | 布谷鸟扩展统计 |
| 0x0060 | IRQ_MASK | bitmask | RW | 中断屏蔽 |
| 0x0064 | IRQ_STATUS | bitmask | W1C | 中断状态 |
| 0x0068 | IRQ_COALESCE | [15:0] pkt_th, [31:16] usec_th | RW | 中断合并 |
| 0x0070 | PORT_CTRL | [0] RX_EN, [1] TX_EN, [2] LOOPBACK | RW | 端口控制 |
| 0x0074 | PORT_STATUS | link/speed/duplex | RO | 端口状态 |
| 0x0080 | STAT_RX_PKT_LO | 32-bit | RO | RX 包计数低位 |
| 0x0084 | STAT_RX_PKT_HI | 32-bit | RO | RX 包计数高位 |
| 0x0088 | STAT_TX_PKT_LO | 32-bit | RO | TX 包计数低位 |
| 0x008C | STAT_TX_PKT_HI | 32-bit | RO | TX 包计数高位 |
| 0x0090 | DROP_REASON0 | bitfield | RO | 丢包原因统计 |
| 0x0094 | DROP_REASON1 | bitfield | RO | 丢包原因统计 |
寄存器事务化更新建议
Host: write FLOW_LOAD_CTRL.LOAD=1 stream rule blocks to mailbox region poll FLOW_LOAD_STATUS.BUSY==0 if no error: write FLOW_LOAD_CTRL.COMMIT=1 else: write FLOW_LOAD_CTRL.ROLLBACK=1
这样可避免“规则写一半就生效”的业务抖动。
3.5 rte_flow 字段到硬件字段映射表(实装模板)
3.5.1 Pattern 映射
| rte_flow Pattern Item | DPDK 字段 | 硬件 key 字段 | 备注 |
| ------------------------- | ---------------------- | -------------------------------- | ---------------------- |
| ETH | src/dst MAC, ethertype | key.eth.src/dst/type | L2 分类 |
| VLAN | tci, inner_type | key.vlan.tci/type | 单/双 VLAN |
| IPV4 | src/dst, proto, tos | key.ip4.src/dst/proto/tos | 常见五元组基础 |
| IPV6 | src/dst, next_hdr, tc | key.ip6.src/dst/nh/tc | 128-bit 地址处理 |
| TCP | src/dst port, flags | key.l4.tcp.sport/dport/flags | 连接导向 |
| UDP | src/dst port | key.l4.udp.sport/dport | DNS/QUIC 等 |
| VXLAN/GENEVE | vni, inner headers | key.tunnel.vni + inner_key | 隧道业务关键 |
| META/MARK | metadata/mark | key.meta/mark | 与 pipeline 元数据联动 |
3.5.2 Action 映射
| rte_flow Action | 硬件动作字段 | 数据面行为 |
| -------------------------- | -------------------------------- | ----------------------- |
| DROP | act.type=DROP | 丢包并计数 |
| QUEUE | act.type=QUEUE, act.qid | 指定队列转发 |
| RSS | act.type=RSS, rss_key, qmask | 多队列负载分担 |
| MARK | act.mark | 写 flow_tag/metadata |
| COUNT | act.counter_id | 命中计数 |
| JUMP | act.next_table | 跳转下一级表 |
| PORT_ID / REPRESENTED_PORT | act.egress_port | 端口或 representor 转发 |
| SET_IPV4_DST / SET_TP_DST | act.rewrite.* | 地址/端口改写(VA替换) |
3.5.3 rte_flow 到硬件规则对象伪代码
function compile_rte_flow_to_hw(rule):
hw_key.masked_fields = extract_pattern_fields(rule.pattern)
hw_key.values = extract_pattern_values(rule.pattern)
hw_act = encode_actions(rule.actions)
hw_entry = {
key: hw_key,
action_ptr: write_action_ram(hw_act),
priority: rule.priority,
group: rule.group
}
return hw_entry
---
4. 布谷鸟 Hash(Cuckoo Hash)在 FPGA 的设计方案
4.1 为什么选布谷鸟 Hash
在 DPU 流表中,需求是:
• 高吞吐查找(每包都查)
• 高装载率
• 有限延迟
布谷鸟 Hash 相对链地址法的优势:
• 查找固定探测次数(常见 2~4 路),时延可控
• 冲突处理方式适合硬件流水
4.2 硬件结构建议
Ingress key -> Hash0/Hash1 -> Bucket0/Bucket1 parallel read
-> Compare tags/keys
-> Hit ? action_ptr : miss_action
Insert path:
new_key -> try bucket0/bucket1
-> if full: kick-out victim (limited depth)
-> reinsert victim to alternate bucket
-> exceed depth => stash/overflow queue
4.3 表项格式(建议)
• key_tag:缩短比较路径(先比 tag 再比 full key)
• full_key:五元组或策略 key
• action_ptr:动作模板指针
• age/hit:老化与统计
4.4 关键工程参数
• bucket_size:每桶 4 或 8(常见)
• kick_depth_limit:避免插入死循环
• stash_size:处理极端冲突
4.5 布谷鸟插入伪代码(硬件控制逻辑)
function cuckoo_insert(entry):
for depth in [0 .. KICK_LIMIT]:
b0 = hash0(entry.key)
if bucket[b0] has empty slot:
place(entry); return OK
b1 = hash1(entry.key)
if bucket[b1] has empty slot:
place(entry); return OK
victim = select_victim(bucket[b0] or bucket[b1])
swap(entry, victim)
entry = victim
push_to_stash(entry)
return STASHED
4.6 查找伪代码(每包流水)
function cuckoo_lookup(key): b0 = hash0(key) b1 = hash1(key) e0 = read_bucket(b0) e1 = read_bucket(b1) if match(e0, key): return e0.action_ptr if match(e1, key): return e1.action_ptr if stash_match(key): return stash.action_ptr return MISS
---
5. FPGA 通过外围设备和接口控制实现 DPU 功能
5.1 必控外围与接口
2. MAC/PCS/PMA + PHY:网口收发和链路训练
3. DDR/HBM:大容量流表/缓冲
4. MDIO/I2C:PHY 与光模块管理(速率、链路、告警)
5. PTP Timer:时间戳与同步(如需)
5.2 控制路径建议
• 控制面寄存器分组:
• 全局控制
• 队列配置
• 流表管理
• 端口管理
• 统计/告警
• 外设控制状态机建议:
• INIT -> PROBE -> CONFIG -> RUN -> ERROR_RECOVERY
5.3 外设联动示例(链路 down 自动降级)
5.4 业界规范标准(建议纳入的 DPU 设计基线)
> 以下是做“工程级 DPU”时建议对齐的主流规范/标准。
| 类别 | 规范/标准 | 在 DPU 中的落点 |
| ---------- | ------------------------------- | --------------------------- |
| 主机互联 | PCIe(PCI-SIG) | EP、MSI-X、DMA、错误上报 |
| 以太网 | IEEE 802.3 | MAC/PCS/PMA、速率协商 |
| 时间同步 | IEEE 1588 PTP | 时间戳、时钟同步 |
| 虚拟化 | SR-IOV/ACS/IOMMU | 多租户隔离与直通 |
| 软件数据面 | DPDK ethdev/rte_flow | 队列模型与流规则语义 |
| Linux 生态 | tc flower / switchdev / devlink | 内核旁路与硬件 offload 管理 |
| 虚拟设备 | virtio-net / vDPA(可选) | 云原生和虚拟化兼容 |
| 可观测性 | sFlow/IPFIX/Telemetry(可选) | 流量可视化与运维 |
你刚才未明确提到、但业界常加的能力
1. 错误处理规范化:AER/错误码分级 + host 可读日志。
2. 可观测性规范化:统一统计口径(包、字节、丢包原因、时延分位)。
3. 规则事务语义:LOAD/COMMIT/ROLLBACK,保证规则更新原子性。
4. 多租户隔离:队列、流表、计数器、带宽的租户级隔离。
5. 升级回滚机制:bitstream 与规则/驱动版本兼容矩阵。
5.5 规范达标检查清单(设计评审可直接用)
协议与接口
• [ ] PCIe 链路训练、错误恢复、中断路径已验证
• [ ] MAC/PHY 控制路径(MDIO/I2C)支持异常恢复
• [ ] DPDK 基本 API(收发/统计/规则)语义对齐
规则与流表
• [ ] rte_flow 子集映射表完整可追踪
• [ ] 规则更新具备事务语义(commit/rollback)
• [ ] 布谷鸟冲突处理(kick/stash)有边界策略
虚拟化与可观测
• [ ] IOMMU 场景地址翻译路径明确
• [ ] 队列/端口/规则统计可按租户导出
• [ ] 关键告警可上报 host(中断或事件队列)
if PHY link_down detected:
stop TX scheduling
flush unsafe queues (policy-based)
raise event to host
try re-init PHY/PCS
when link_up stable -> resume TX
--- ## 6. 智能网卡“虚拟地址替换(VA rewrite)”落地案例 > 目标:实现“按策略把目标虚拟服务地址替换为真实后端地址”,常见于服务网格旁路加速或负载均衡 offload。 ## 6.1 业务定义 输入包: - `dst_ip = 10.0.0.100`(虚拟地址 VIP) - `dst_port = 443` 规则: - VIP `10.0.0.100:443` 映射到 `192.168.10.21:8443`(后端A) - 也可按哈希分流到后端 B/C 输出包动作: - 改写 `dst_ip/dst_port` - 重新计算 L3/L4 校验和 - 更新 flow 统计 ## 6.2 硬件处理流程图(文本)
RX packet
-> Parser 抽取五元组
-> KeyBuilder 生成查表 key
-> CuckooHash 查询 action_ptr
-> Action RAM 读取动作
if action == VA_REWRITE:
rewrite dst_ip/dst_port
update checksum
select egress queue
-> TX scheduler
-> MAC egress
## 6.3 VA 重写动作模板(建议)
action_type = VA_REWRITE
new_dst_ip = 192.168.10.21
new_dst_port = 8443
checksum_mode = INCR_UPDATE
egress_queue = Q3
stats_counter_id = C17
## 6.4 VA 重写伪代码(数据面)
function process_packet(pkt):
key = extract_5tuple(pkt)
act = flow_lookup(key)
if act.type == VA_REWRITE:
old_ip = pkt.ip.dst
old_port = pkt.l4.dst_port
pkt.ip.dst = act.new_dst_ip
pkt.l4.dst_port = act.new_dst_port
pkt.ip.csum = update_ip_checksum(pkt.ip.csum, old_ip, act.new_dst_ip)
pkt.l4.csum = update_l4_checksum(pkt.l4.csum, old_port, act.new_dst_port)
stats[act.counter_id]++
enqueue(pkt, act.egress_queue)
else:
default_forward_or_drop(pkt)
## 6.5 控制面下发伪代码(DPDK 应用侧)
rule = {
match: dst_ip=10.0.0.100, dst_port=443, proto=TCP,
action: VA_REWRITE(new_dst_ip=192.168.10.21, new_dst_port=8443)
}
rte_flow_create(port_id, rule)
wait hw_ack
## 6.6 验收标准(必须满足) 1. 功能正确:抓包看到地址和端口改写正确。 2. 校验正确:无 checksum 错误丢包。 3. 性能达标:在目标包长下吞吐满足 KPI。 4. 稳定性:长稳运行无规则抖动与内存泄漏。 --- ## 7. 可落地的实现步骤(最短路径) ## 阶段1:最小闭环 - 打通 PCIe BAR + DMA + SQ/CQ - 网口收发直通 - DPDK 能 `rx_burst/tx_burst` ## 阶段2:流表与动作 - 实现 Cuckoo lookup(先不做复杂插入) - 支持静态规则下发 - 实现 `DROP/FWD/VA_REWRITE` 三种动作 ## 阶段3:控制面规范化 - 对接 `rte_flow` 子集 - 增加规则 commit/rollback - 增加错误码与状态回读 ## 阶段4:性能与稳定性 - 中断合并调优 - 队列深度/批处理调优 - 长稳 + 故障注入(链路 flap、规则抖动) --- ## 8. 调试速查(DPDK + Cuckoo + 外设控制) | 现象 | 先看什么 | 常见根因 | | -------------------------------- | ----------------------------------- | ---------------------------------- | | `rte_flow_create` 成功但不生效 | 规则下发表状态、flow_table hit/miss | 规则未 commit;key 提取字段不一致 | | hit 率低于预期 | hash 分布、bucket 冲突、stash 命中 | hash 函数偏斜;桶参数不合理 | | VA 改写后大量丢包 | L3/L4 checksum 统计、drop reason | 校验和更新错误;动作顺序错误 | | 吞吐低 | 队列占用、CQ 回收速率、中断频率 | 批处理太小;中断过密;DMA 深度不足 | | 链路反复 flap | MDIO 读数、PCS 状态、温度 | PHY 配置不稳、光模块兼容或散热问题 | --- ## 9. 项目交付清单(面向落地) 1. 架构文档:数据面/控制面/外设控制图 2. 寄存器文档:地址、位域、时序、错误码 3. 规则文档:`match/action` 字段定义与限制 4. PMD/应用文档:DPDK 调用流程与示例 5. 测试报告:功能、性能、长稳、故障注入 6. 回滚方案:规则回滚、bitstream 回滚 --- ## 10. 一页结论 一个可落地的 DPU FPGA 项目,不是“把包转发出去”这么简单,而是: - 用 DPDK 语义把主机侧和硬件侧统一起来; - 用 Cuckoo Hash 把流表性能做实; - 把 PCIe/PHY/DDR/MDIO/I2C 等外围控制做好闭环; - 用具体业务(如 VA rewrite)验证从规则下发到数据面执行的全链路。 如果这四条都闭环,你的 DPU 项目就具备工程落地能力。