DragonOS/docs/kernel/net/napi_and_netns_poll.md

111 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DragonOS NAPI 与 NetNamespace Poll 机制设计说明
本文档对 DragonOS 当前网络子系统中的 NAPINew API机制与 NetNamespace 轮询调度机制的设计与实现进行说明。
## 1. 机制概览
DragonOS 的网络包处理采用 **"事件驱动 (Event-Driven) + 精确定时 (Precise Timing)"** 的混合驱动模型。系统通过独立的内核线程来分别处理"硬件中断触发的收包任务"和"协议栈定时任务",实现了对网络流量的高效响应与 CPU 资源的合理调度。
核心设计包含两个主要部分:
1. **NAPI 子系统**:负责高吞吐量的网络包收发处理,采用"有界轮询 (Bounded Polling)" 机制。
2. **NetNamespace 调度器**:负责管理协议栈的时间事件(如 TCP 重传),充当精确定时器。
## 2. 核心组件设计
### 2.1 NAPI 子系统 (`kernel/src/driver/net/napi.rs`)
NAPI 是 DragonOS 网络驱动层的核心收包机制。
* **NapiStruct**:
每个支持 NAPI 的网卡接口(`Iface`)都绑定一个 `NapiStruct` 结构体。它维护了 NAPI 实例的状态(如 `SCHED` 调度位)和权重(`weight`)。
* **Weight (权重)**: 定义了单次调度周期内该接口允许处理的最大数据包数量Budget防止单网卡独占 CPU。
* **全局 NAPI 管理器 (Global NapiManager)**:
* 目前实现为单例(`GLOBAL_NAPI_MANAGER`)。
* 维护一个全局的 `napi_list` 待处理队列。
* 提供 `napi_schedule()` 接口:供网卡中断处理函数调用,将 NAPI 实例加入队列并唤醒处理线程。
* **NAPI 处理线程 (`napi_handler`)**:
* 这是一个专用的内核线程,并在系统启动时初始化。
* **工作逻辑**:不断从 `napi_list` 取出被调度的 NAPI 实例,调用其 `poll()` 方法。
* **循环调度**:如果 `poll()` 返回 `true`(表示 Budget 用尽但仍有数据),线程会将该实例重新放回队列尾部,等待下一轮调度。
### 2.2 NetNamespace 调度器 (`kernel/src/process/namespace/net_namespace.rs`)
每个网络命名空间NetNamespace拥有一个独立的轮询线程`netns_poll`),在当前设计中,它主要承担 **"定时器"** 和 **"兜底调度器"** 的角色。
* **精确定时**:
该线程维护了命名空间内所有网卡的 `poll_at_us`下一次需要处理的时间点。它会计算出最近的截止时间Deadline并进行精确休眠`wait_event_timeout`)。
* **超时触发**:
当休眠超时(即协议栈定时事件到达,如 TCP RTO该线程**不会**直接处理数据包,而是调用 `napi_schedule()`,将任务分发给 NAPI 线程执行。这保证了繁重的协议栈处理逻辑统一由 NAPI 线程承担。
### 2.3 有界轮询 (Bounded Polling)
`kernel/src/driver/net/mod.rs` 中实现了适配 NAPI 的轮询接口 `poll_napi(budget)`
* **逻辑**
1. 调用 `smoltcp``poll_ingress_single` 处理接收队列,循环次数受 `budget` 限制。
2. 执行一次 `poll_egress` 推进发送队列。
3. 更新 `poll_at_us` 时间戳,供 NetNamespace 调度器参考。
* **特性**:保证了每次调度的执行时间是可控的,避免了长时关中断或线程饿死。
## 3. 工作流程图解
当前系统的网络处理数据流与控制流如下:
```mermaid
flowchart TD
%% 硬件层与驱动层
subgraph Hardware_Driver [硬件与驱动层]
NIC[物理网卡]
IRQ_Handler[中断处理函数]
NIC -->|数据包到达| IRQ_Handler
end
%% NAPI 子系统
subgraph NAPI_System [NAPI 子系统]
NapiManager[NapiManager 全局队列]
NapiThread[NapiHandler 线程]
IRQ_Handler -->|1. napi_schedule| NapiManager
NapiManager -->|2. 唤醒| NapiThread
NapiThread -->|3. 取出 NapiStruct| NapiThread
end
%% 协议栈与定时器
subgraph Network_Stack [协议栈与定时器]
Smoltcp[smoltcp 协议栈]
NetnsThread[Netns 调度线程]
NapiThread -->|4. poll_napi budget| Smoltcp
Smoltcp -->|5. 处理 Ingress/Egress| Smoltcp
Smoltcp -->|6. 更新 poll_at_us| NetnsThread
NetnsThread -.->|7. 休眠等待 poll_at| NetnsThread
NetnsThread -->|8. 超时触发 napi_schedule| NapiManager
end
%% 循环反馈
Smoltcp -.->|9. 数据未处理完 Budget耗尽| NapiManager
```
## 4. 当前实现现状
截至当前版本DragonOS 的网络机制具有以下实现特征:
1. **单队列 NAPI 管理**
* 目前的 `NapiManager` 是全局唯一的,所有 CPU 共享同一个待处理队列。
* 尚未实现 Linux 风格的 Per-CPU NAPI 队列(代码中留有 TODO
2. **线程模型**
* `napi_handler`:负责具体的包处理和协议栈推进,是计算密集型线程。
* `netns_poll`:负责时间管理和事件分发,是 IO/Sleep 密集型线程。
3. **驱动支持**
* Virtio-Net、Veth、Loopback 等驱动已接入此机制,在中断或发包时主动调用 `napi_schedule`
4. **Smoltcp 适配**
* 通过 `IfaceCommon``smoltcp` 进行了封装,将无界的 `poll()` 转化为适配 NAPI 的有界 `poll_napi()`