Buck Blog · 博客正文

返回技术分享首页
DPU智能网卡FPGA落地方案

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 项目就具备工程落地能力。