|
| 1 | +# 01 需求规格 —— ff_rss_check 三项优化 |
| 2 | + |
| 3 | +> 范围:F-Stack `lib/ff_dpdk_if.c` 的 RSS(Receive Side Scaling)相关能力三项优化。 |
| 4 | +> 基线 commit:`2422d12eb`(feature/1.26)。 |
| 5 | +> 原则:所有结论以实际代码/头文件为准,给出 `文件:行号` 证据;不确定项标注「待确认」。 |
| 6 | +> 本文档仅描述「做什么 / 为什么 / 验收标准」,方案设计见 04。 |
| 7 | +
|
| 8 | +--- |
| 9 | + |
| 10 | +## 0. 背景:RSS 选源端口机制概述 |
| 11 | + |
| 12 | +F-Stack 在多队列(multi-queue / 多进程)部署下,为保证「主动发起连接(connect)」时选出的本地源端口能让该四元组的报文经网卡 RSS 哈希后回到**本进程对应的接收队列**,引入了一套 RSS 端口选择机制: |
| 13 | + |
| 14 | +- 用户态(`lib/ff_dpdk_if.c`):软算 Toeplitz hash(`toeplitz_hash` L2547)模拟网卡 RSS,判定某四元组是否命中本队列(`ff_rss_check` L2851);并预先构建静态表 `ff_rss_tbl`(L172)缓存「对给定 saddr/daddr/sport,哪些 dport 落本队列」,由 `ff_rss_tbl_get_portrange`(L2796)在选端口时查询。 |
| 15 | +- 内核态(`freebsd/netinet/in_pcb.c`):在选本地端口的 `in_pcb_lport_dest` 中,对带 `INPLOOKUP_LPORT_RSS_CHECK` 标志的请求,调用上述用户态接口,只从「落本队列的端口集」中选出源端口。 |
| 16 | + |
| 17 | +该机制在 13.0 基线中内核侧对接完整(仅 IPv4),但在 13.0→15.0 升级后内核侧对接缺失(详见 02)。三项优化即围绕「补全/扩展/优化」此机制展开。 |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## 1. 需求 0.1:`ff_rss_tbl_get_portrange` 内核对接回迁至 15.0 |
| 22 | + |
| 23 | +### 1.1 背景 |
| 24 | +- 用户态接口 `ff_rss_tbl_get_portrange`(`lib/ff_dpdk_if.c:2796`)、`ff_rss_tbl_set_portrange`(L2737)、`ff_rss_tbl_init`(L2598)、`ff_rss_check`(L2851)、`ff_in_pcbladdr`(L2571)在 15.0 **仍存在且完整保留**。 |
| 25 | +- 但内核侧(`freebsd/netinet/in_pcb.c`)消费这些接口的 `#ifdef FSTACK` RSS 钩子在 13.0→15.0 升级中**未移植**:当前 15.0 的 `in_pcb.c` 对 `FSTACK / ff_rss_* / ff_in_pcbladdr / INPLOOKUP_LPORT_RSS_CHECK` 的 grep 命中数为 0;仅 `in_pcb.h:624` 保留了 `INPLOOKUP_LPORT_RSS_CHECK` 的 `#define`。 |
| 26 | +- 结果:`INPLOOKUP_LPORT_RSS_CHECK` 宏虽在,但**无任何代码消费**,RSS 选端口机制在 15.0 内核侧实际**完全失效**。 |
| 27 | + |
| 28 | +### 1.2 目标 |
| 29 | +在当前 15.0 内核 `in_pcb.c` 中,按 15.0 的代码结构重新对接(回迁)13.0 的 FSTACK RSS 选端口逻辑,使 connect 主动连接时能复用用户态 `ff_rss_tbl_get_portrange` / `ff_rss_check` 选出落本队列的源端口,并完成迁移后的功能测试。 |
| 30 | + |
| 31 | +### 1.3 范围(In Scope) |
| 32 | +- `in_pcb.c` 中 `in_pcb_lport_dest`(15.0 L756)的 RSS portrange 选端口逻辑。 |
| 33 | +- `in_pcb.c` 中本地地址选择处对 `ff_in_pcbladdr` 的对接(13.0 在 `in_pcbconnect_setup`,15.0 对应函数为 `in_pcbconnect`,见 02)。 |
| 34 | +- 选端口调用处传入 `INPLOOKUP_LPORT_RSS_CHECK` 标志。 |
| 35 | +- 全部以 `#ifdef FSTACK` 门控,最小侵入。 |
| 36 | +- 回迁后的功能/回归测试(IPv4)。 |
| 37 | + |
| 38 | +### 1.4 非目标(Out of Scope) |
| 39 | +- 不在本需求内做 IPv6(属 0.2)。 |
| 40 | +- 不在本需求内引入 `rte_thash_*`(属 0.3)。 |
| 41 | +- 不改用户态 `ff_rss_*` 接口签名(其已存在且保留)。 |
| 42 | + |
| 43 | +### 1.5 验收标准 |
| 44 | +- 15.0 `in_pcb.c` 重新出现 `#ifdef FSTACK` RSS 钩子,且能编译通过(开启 FSTACK)。 |
| 45 | +- 开启 `rss_check`(config.ini `[dpdk]`)多队列场景下,connect 选出的源端口经 `ff_rss_check` 校验落本队列(与 13.0 行为一致)。 |
| 46 | +- 关闭 `rss_check`(enable=0)或单队列时,行为退回原生 FreeBSD 选端口(无回归)。 |
| 47 | +- 原有单测(`tests/unit/test_ff_dpdk_if.c` L358-455 的 set/get_portrange 用例)仍通过。 |
| 48 | + |
| 49 | +--- |
| 50 | + |
| 51 | +## 2. 需求 0.2:`ff_rss_check` / `ff_rss_tbl_get_portrange` 支持 IPv6 hash |
| 52 | + |
| 53 | +### 2.1 背景 |
| 54 | +- 当前用户态 RSS 全链路**仅支持 IPv4**: |
| 55 | + - `ff_rss_check`(L2851)入参 `uint32_t saddr/daddr`,hash 输入布局为 `saddr(4)+daddr(4)+sport(2)+dport(2)`(L2865-2880),无 16 字节 v6 地址路径。 |
| 56 | + - `ff_rss_tbl_get_portrange`(L2796)/`ff_rss_tbl_set_portrange`(L2737)/`ff_rss_tbl_init`(L2598)键均为 `uint32_t saddr/daddr`。 |
| 57 | + - 静态表结构 `struct ff_rss_tbl_type` / `ff_rss_tbl_dip_type`(L155-172)字段 `uint32_t saddr/daddr`。 |
| 58 | +- 内核侧:13.0 基线 `netinet6/in6_pcb.c` 对 `FSTACK / ff_rss / INPLOOKUP_LPORT_RSS_CHECK` grep 命中数为 0;15.0 同样为 0。**即 RSS 选端口在 13.0 本身就是 IPv4-only**。 |
| 59 | + |
| 60 | +### 2.2 目标 |
| 61 | +扩展 `ff_rss_check` / `ff_rss_tbl_get_portrange`(及相关静态表与 init/set)支持 IPv6 地址(16 字节)的 RSS hash 计算与端口选择;并在内核 `in6_pcb` 选端口流程新建对接。 |
| 62 | + |
| 63 | +### 2.3 范围(In Scope) |
| 64 | +- 用户态 hash 输入布局支持 IPv6(16+16+2+2),RSS hash field 配置含 IPv6/TCP_IPV6(待确认网卡/DPDK 配置项,见 02/04)。 |
| 65 | +- 静态表 `ff_rss_tbl` 与 portrange 结构的 IPv6 化(新增 v6 表 vs 联合体的权衡留待 04)。 |
| 66 | +- `ff_rss_check` / `ff_rss_tbl_get_portrange` 的 family/IPv6 重载或新增函数。 |
| 67 | +- 内核 `netinet6/in6_pcb.c` 选端口流程对接(**全新建,13.0 也无**)。 |
| 68 | + |
| 69 | +### 2.4 非目标(Out of Scope) |
| 70 | +- 不影响、不回归现有 IPv4 快路径与静态表布局。 |
| 71 | +- 0.2 是「全新增能力」,非「从 13.0 回迁」(与 0.1 性质不同)。 |
| 72 | + |
| 73 | +### 2.5 验收标准 |
| 74 | +- 多队列 IPv6 connect 选出的源端口经 IPv6 RSS hash 校验落本队列。 |
| 75 | +- IPv4 路径功能/性能无回归。 |
| 76 | +- 新增 IPv6 单测/集成测试通过(真机口径见 M4 spec)。 |
| 77 | + |
| 78 | +--- |
| 79 | + |
| 80 | +## 3. 需求 0.3:用 `rte_thash_adjust_tuple()` 优化动态计算 `ff_rss_check()` |
| 81 | + |
| 82 | +### 3.1 背景 |
| 83 | +- 当前 `ff_rss_check`(L2851)对每个候选 dport 都软算一次 `toeplitz_hash`(L2883)来判定是否落本队列;`ff_rss_tbl_init`(L2598)更是对全部 65536 个 dport 逐个调用 `ff_rss_check`(L2690-2700)预构建静态表,开销较大。 |
| 84 | +- 静态表 `ff_rss_tbl` 命中时为快路径(性能更优,需**保留**);但**未命中静态表**的动态场景仍走逐端口软算,效率低。 |
| 85 | +- DPDK 24.11.6 已提供 `rte_thash_*` 反向调整元组的能力:`rte_thash_init_ctx`(`dpdk/lib/hash/rte_thash.h:303`)、`rte_thash_complete_matrix`(L256)、`rte_thash_get_complement`(L380)、`rte_thash_adjust_tuple`(L456)。`lib/ff_dpdk_if.c:51` 已 `#include <rte_thash.h>` 但未使用任何 `rte_thash_*` 符号。 |
| 86 | + |
| 87 | +### 3.2 目标 |
| 88 | +在**保留静态 `ff_rss_tbl` 快路径**的前提下,对未命中静态表的动态计算场景,用 `rte_thash_adjust_tuple()`(按目标队列直接反算出满足约束的元组/端口)替代/补充逐端口扫描软算,并与 FreeBSD 选源端口流程兼容对接,保证选出端口仍满足 RSS 落队列约束。 |
| 89 | + |
| 90 | +### 3.3 范围(In Scope) |
| 91 | +- 动态路径引入 `rte_thash_init_ctx` + `rte_thash_adjust_tuple`(reta_sz 对齐 `rss_reta_size` L133;key 对齐 `rsskey`/`default_rsskey_40bytes` L92-121)。 |
| 92 | +- 与 `in_pcb_lport_dest` 选端口语义兼容对接(选出端口经校验确实落本队列)。 |
| 93 | +- 保留 `ff_rss_tbl` 静态表与 `ff_rss_check` 软算作为快路径/回退。 |
| 94 | + |
| 95 | +### 3.4 非目标(Out of Scope) |
| 96 | +- 不删除静态表(静态表性能更优,明确保留)。 |
| 97 | +- 不改变 RSS key / reta_size 的外部配置语义。 |
| 98 | + |
| 99 | +### 3.5 验收标准与约束 |
| 100 | +- 动态路径选出的源端口经独立 `ff_rss_check`(软算)复核仍落本队列(**不得选错队列**)。 |
| 101 | +- 静态表命中路径行为/性能不退化。 |
| 102 | +- `rte_thash_adjust_tuple` 使用的 key 与 reta_sz 与现网卡 RSS 配置严格对齐(对称 key / reta_size,详见 04)。 |
| 103 | +- 与 0.1 回迁后的 `in_pcb_lport_dest` 选端口流程协同正确。 |
| 104 | + |
| 105 | +--- |
| 106 | + |
| 107 | +## 4. 三项需求关系小结 |
| 108 | + |
| 109 | +| 需求 | 性质 | 用户态改动 | 内核态改动 | IPv6 | |
| 110 | +|------|------|------------|------------|------| |
| 111 | +| 0.1 | 回迁(13.0 已有、15.0 缺失) | 无(接口已存在保留) | `in_pcb.c` 回迁 FSTACK RSS 钩子 | 否(IPv4) | |
| 112 | +| 0.2 | 全新增(13.0 也无) | hash/表结构/接口 IPv6 化 | `in6_pcb.c` 新建对接 | 是 | |
| 113 | +| 0.3 | 优化(动态路径) | `ff_rss_check` 动态路径引入 `rte_thash` | 与 0.1 对接协同 | 随 0.2 扩展 | |
| 114 | + |
| 115 | +--- |
| 116 | + |
| 117 | +## 5. 待确认项(需后续 M2/编码阶段核实) |
| 118 | + |
| 119 | +- 【待确认】15.0 `in_pcbconnect`(L1083)合并了 13.0 `in_pcbconnect_setup` 后,`ff_in_pcbladdr` 的对接插入点与原生 `in_pcbladdr`(L1129)的先后/条件关系。 |
| 120 | +- 【待确认】IPv6 RSS hash 在 DPDK/网卡侧需开启的 RSS offload field(`RTE_ETH_RSS_IPV6` / `RTE_ETH_RSS_NONFRAG_IPV4_TCP` 等)与现有 port 配置的对齐。 |
| 121 | +- 【待确认】0.3 `rte_thash_adjust_tuple` 所需的对称 RSS key 假设是否与现网卡 `default_rsskey_40bytes`(L92)一致;非对称 key 下反算可行性。 |
0 commit comments