|
| 1 | +# 根因分析与修复方案 |
| 2 | + |
| 3 | +## 一、根因分析 |
| 4 | + |
| 5 | +### 问题本质 |
| 6 | +F-Stack 的 config.ini 不支持任意 DPDK EAL 启动参数透传。用户想传递 devargs(如 `scalar_enable=1`),但: |
| 7 | + |
| 8 | +1. `allow` 配置项用逗号分隔多个 PCI 设备(`lib/ff_config.c:1191`),无法附加 devargs。 |
| 9 | +2. 没有通用的 EAL 参数透传机制,只能修改 `lib/ff_config.c` 源码手动添加。 |
| 10 | + |
| 11 | +### 代码追踪 |
| 12 | +- `lib/ff_config.c:1151-1308`:`dpdk_args_setup()` 按固定顺序构建 EAL 参数,无扩展点。 |
| 13 | +- `lib/ff_config.h:35`:`DPDK_CONFIG_NUM 16`,dpdk_argv 数组上限,固定参数已占用较多槽位。 |
| 14 | + |
| 15 | +## 二、修复方案 |
| 16 | + |
| 17 | +### 新增 `extra_eal_args` 配置项 |
| 18 | + |
| 19 | +在 `[dpdk]` 段新增 `extra_eal_args`,空格分隔多个 EAL 参数,原样追加到 `dpdk_argv[]` 末尾。 |
| 20 | + |
| 21 | +### 修改详情 |
| 22 | + |
| 23 | +#### 1. `lib/ff_config.h:34-35` — 提升 DPDK_CONFIG_NUM |
| 24 | +```c |
| 25 | +// dpdk argc, argv, max argc: 32, member of dpdk_config |
| 26 | +#define DPDK_CONFIG_NUM 32 |
| 27 | +``` |
| 28 | +从 16 提升到 32,为用户自定义参数预留空间。M1 子 agent 确认无硬编码 16 依赖,所有引用通过宏自动跟随(含测试桩文件)。 |
| 29 | +
|
| 30 | +#### 2. `lib/ff_config.h:285-288` — 新增字段 |
| 31 | +```c |
| 32 | + /* pci whiltelist */ |
| 33 | + char *allow; |
| 34 | +
|
| 35 | + /* extra DPDK EAL args, appended to rte_eal_init argv */ |
| 36 | + char *extra_eal_args; |
| 37 | +
|
| 38 | + int nb_channel; |
| 39 | +``` |
| 40 | + |
| 41 | +#### 3. `lib/ff_config.c:1044-1047` — 新增解析 |
| 42 | +```c |
| 43 | + } else if (MATCH("dpdk", "allow")) { |
| 44 | + pconfig->dpdk.allow = strdup(value); |
| 45 | + } else if (MATCH("dpdk", "extra_eal_args")) { |
| 46 | + pconfig->dpdk.extra_eal_args = strdup(value); |
| 47 | + } else if (MATCH("dpdk", "port_list")) { |
| 48 | +``` |
| 49 | +
|
| 50 | +#### 4. `lib/ff_config.c:1284-1298` — dpdk_args_setup 末尾追加 |
| 51 | +```c |
| 52 | + } |
| 53 | +
|
| 54 | + if (cfg->dpdk.extra_eal_args) { |
| 55 | + char* token; |
| 56 | + char* rest = cfg->dpdk.extra_eal_args; |
| 57 | +
|
| 58 | + while ((token = strtok_r(rest, " ", &rest))) { |
| 59 | + if (n >= DPDK_CONFIG_NUM) { |
| 60 | + printf("extra_eal_args exceed DPDK_CONFIG_NUM, truncated\n"); |
| 61 | + break; |
| 62 | + } |
| 63 | + dpdk_argv[n++] = strdup(token); |
| 64 | + } |
| 65 | + } |
| 66 | +
|
| 67 | + dpdk_argc = n; |
| 68 | +``` |
| 69 | + |
| 70 | +#### 5. `lib/ff_config.c:1764-1766` — 释放逻辑 |
| 71 | +```c |
| 72 | + if (ff_global_cfg.dpdk.extra_eal_args) { |
| 73 | + free(ff_global_cfg.dpdk.extra_eal_args); |
| 74 | + ff_global_cfg.dpdk.extra_eal_args = NULL; |
| 75 | + } |
| 76 | +``` |
| 77 | +
|
| 78 | +#### 6. `config.ini:74-78` — 配置项注释 |
| 79 | +```ini |
| 80 | +#allow=02:00.0,03:00.0 |
| 81 | +
|
| 82 | +# Extra DPDK EAL args, space-separated, appended to rte_eal_init() argv. |
| 83 | +# e.g. extra_eal_args=--allow=02:00.0,scalar_enable=1 |
| 84 | +# e.g. extra_eal_args=--log-level=pmd:8 --iova-mode=pa |
| 85 | +#extra_eal_args= |
| 86 | +``` |
| 87 | + |
| 88 | +## 三、向后兼容性 |
| 89 | + |
| 90 | +| 场景 | 行为 | |
| 91 | +|------|------| |
| 92 | +| 不配置 extra_eal_args | 无影响(NULL,不追加任何参数) | |
| 93 | +| 配置 extra_eal_args | 参数追加到 dpdk_argv 末尾 | |
| 94 | +| 参数与 F-Stack 自动构建同名 | DPDK EAL 后者覆盖前者(预期行为) | |
| 95 | +| 参数超过 DPDK_CONFIG_NUM | 打印警告并截断(防越界) | |
| 96 | + |
| 97 | +## 四、安全边界 |
| 98 | + |
| 99 | +1. **纯透传**:extra_eal_args 不参与 F-Stack 内部逻辑解析,只透传给 DPDK。 |
| 100 | +2. **用户责任**:用户需确保参数格式正确(如 `--device` 不是 DPDK EAL 参数,应用 `--allow`)。F-Stack 不做白名单限制,与 DPDK 原生行为一致。 |
| 101 | +3. **上界保护**:`n >= DPDK_CONFIG_NUM` 检查防止数组越界。 |
0 commit comments