NexusNet Kernel DCO 路线图
状态:Roadmap
最后核对:2026-05-15
目标
Kernel DCO 是 NexusNet 的项目级 dataplane offload 路线图。它不是只给 QUIC REALITY 用,而是覆盖所有可以借助 Linux kernel、eBPF、socket offload、TUN/TAP 能力,或者 privileged helper 降低 agent CPU 成本、改善 packet handling 的地方。
当前仓库没有自定义 DCO 实现。已实现产品路径仍是用户态:
TCP/UDP socket 或 TUN
-> nexus-agent classifier and dataplane
-> RAW / TLS / REALITY / Noise / QUIC path
-> upstream socket, peer agent, or peer TUNDCO 不能替代 agent 的 policy brain。backend 和 agent 仍然负责 rule validation、credential lookup、listener conflict resolution、TLS/REALITY/Noise handshake、fallback decision,以及人类可读日志。DCO 应该只在用户态已经选中并授权 route 或 session 后成为 fast path。
外部参考:OpenVPN DCO 和 ovpn
真正值得参考的是 OpenVPN data-channel offload 的架构,而不是 OpenVPN 协议本身。
截至本次核对:
https://github.com/OpenVPN/ovpn-dco已不再是新 OpenVPN 版本的推荐路径。它的 README 明确说明,该 out-of-treeovpn-dco模块只面向 OpenVPN 2.6.x 和更早版本,仓库处于 maintenance mode,只接受重要 bugfix。- OpenVPN 2.7.0 及更新版本使用新的 upstream Linux
ovpnkernel module。OpenVPN 的README.dco.md说明,ovpn从 Linux 6.16 开始进入内核;更旧内核应使用ovpn-backports。 - upstream kernel 文档暴露了
ovpngeneric netlink family,用于控制 OpenVPN network devices。操作包括 peer create、update、get、delete、key create、key get、key swap、key delete,以及 peer deletion、peer floating、key swap 等通知。
对 NexusNet 真正有价值的是这个分工:
OpenVPN userspace
-> authenticates peer, negotiates cipher, owns config and logs
-> installs peer/key/socket/VPN-IP state through netlink
-> kernel ovpn module encrypts/decrypts and forwards data packets
-> userspace keeps control-plane authority and can disable/fallback DCO这个 control/data split 可以映射到 NexusNet:
NexusNet backend + agent userspace
-> validates config, resolves listener priority, authenticates REALITY/TLS/Noise/QUIC
-> installs a generated, already-authorized fast-path entry
-> helper/kernel handles repetitive packet movement and counters
-> userspace keeps fallback, teardown, logging, and config-generation authority这并不意味着 NexusNet 应该直接把 OpenVPN ovpn 模块当作通用 tunnel engine。ovpn 是 OpenVPN-specific:它预期 OpenVPN peer/key/cipher/session 语义,并暴露 OpenVPN control ABI。NexusNet 当前使用 REALITY、Noise、Quinn QUIC、QUIC DATAGRAM,以及 CONNECT-IP over QUIC DATAGRAM framing。直接集成会迫使项目引入一个并行的 OpenVPN-compatible mode,或者让 NexusNet tunnel 语义依赖外部协议。这不应该是第一个 DCO 目标。
参考链接:
- OpenVPN obsolete out-of-tree DCO module:https://github.com/OpenVPN/ovpn-dco
- OpenVPN DCO user documentation:https://github.com/OpenVPN/openvpn/blob/master/README.dco.md
- Linux
ovpnnetlink specification:https://docs.kernel.org/netlink/specs/ovpn.html - 当前
ovpndevelopment tree:https://github.com/OpenVPN/ovpn-net-next
为什么这是项目级能力
一个监听端口现在可以做很多事:
- TCP RAW:普通 stream relay,没有 route discriminator。
- TCP TLS:TLS accept,按 SNI 分流,可选 upstream TLS。
- TCP REALITY:按 SNI + short ID 做 ClientHello classification、X25519 authentication、target probing 和 deliberate fallback。
- TCP over QUIC REALITY:TCP payload 通过认证后的 QUIC path 承载。
- UDP RAW:按 client address 做 session relay。
- UDP Noise:第一个 datagram 选中本地 X25519 identity;后续 datagram 固定到该 UDP session。
- UDP over QUIC REALITY:UDP payload 作为 QUIC DATAGRAM frames 承载。
- IP over QUIC REALITY DATAGRAM:L3 tunnel packet 由 agent framing。
所以 DCO 是分层问题,不是一个 ip:port 查表:
incoming packet / connection
-> socket namespace: TCP, UDP, TUN, or helper ring
-> port/rule priority: REALITY > TLS > Noise > RAW
-> protocol classifier in user-space
-> route / fallback / reject
-> optional kernel/helper fast path for stable sessions功能状态
| 功能 | 状态 | 证据 |
|---|---|---|
| 用户态 TCP/UDP gateway | 完成 | nexus-agent/src/gateway/mod.rs 和 udp.rs。 |
| 用户态 TLS/REALITY/Noise classification | 完成 | Gateway TLS、REALITY、UDP Noise 路径。 |
| 用户态 QUIC REALITY 和 DATAGRAM | 完成 | nexus-agent/src/gateway/quic.rs。 |
| 用户态 CONNECT-IP dataplane | 完成 | nexus-agent/src/l3/*。 |
| QUIC GSO 调优 | 完成 | Agent 和 L3 config 暴露 GSO 开关。 |
| Kernel/eBPF/helper DCO implementation | 规划 | 当前仓库没有项目级 DCO 代码。 |
| Kernel/user ABI for DCO | 规划 | 尚未定义。 |
| DCO conformance vectors | 规划 | 尚未定义。 |
| 替代用户态 route classification | 拒绝 | 太多 policy、fallback、credential 行为属于用户态。 |
当前 NexusNet 可接入 fast path 的 seam
当前代码已经有几个适合未来 offload adapter 的 seam。这些 seam 比直接引入 kernel code 更适合作为起点。
| Seam | 当前 interface | 当前 adapter | 未来 offload adapter 方向 | 说明 |
|---|---|---|---|---|
| L3 host interface | nexus-agent/src/l3/tun.rs TunDevice | TunRsDevice | DcoTunDevice、AfXdpTunDevice 或 helper-owned TUN adapter | Interface 已支持单 packet 和 batch receive/send。 |
| L3 transport | nexus-agent/src/l3/transport.rs L3DatagramTransport | Quinn REALITY L3 DATAGRAM transport 和 fake test endpoint | DcoL3Transport 或 helper-ring transport | 最适合替换 packet movement,同时保留 CONNECT-IP 测试。 |
| L3 dataplane loop | nexus-agent/src/l3/dataplane.rs L3Dataplane<Tun, Transport> | 对 TUN 和 transport generic | 作为 DCO adapter conformance harness | 同一个 pump 和 validation 行为可以覆盖 userspace/helper/kernel path。 |
| L3 runtime reconciliation | nexus-agent/src/l3/mod.rs L3TunnelManager | 按 prepared tunnel 启停 TUN + QUIC runtime | 按 generation 安装/删除 offload entries | 已有 config apply 和 stale runtime reconciliation。 |
| QUIC socket path | nexus-agent/src/gateway/quic.rs Quinn endpoint setup | UDP socket buffers 和 Quinn GSO | 只做 socket offload/tuning,不 offload QUIC state | Quinn 继续负责 recovery、pacing、loss 和 QUIC crypto。 |
| Network config | nexus-agent/src/l3/net_config.rs NetworkConfigPlan | Linux route add/delete wrapper | 为 helper/kernel 生成 route/mark/table | 对齐 OpenVPN DCO 的经验:routing 应该在 host tables 中可见。 |
| Metrics | nexus-agent/src/l3/metrics.rs 和 gateway QUIC metrics | In-process atomic counters | 从 helper/kernel reconcile counters | 真正 offload 前需要 generation-aware snapshots。 |
这些 seam 也定义了未来测试表面。任何 offload adapter 都必须通过和 userspace adapter 一致的 L3 packet、source-prefix、MTU、multicast、broadcast、keepalive、counter、teardown 测试。
OpenVPN DCO 对 NexusNet 的启发
OpenVPN DCO 有参考价值,是因为它清楚地区分了 control-plane authority 和重复性 packet processing。以下经验可以直接应用到 NexusNet:
OpenVPN DCO / ovpn 经验 | NexusNet 解释 |
|---|---|
| Userspace 仍是 control plane。 | Backend 和 agent 继续负责 rule validation、credential selection、首包分类、peer authentication 和 operator logs。 |
| Kernel state 在 negotiation 后显式安装。 | NexusNet 只应在 REALITY/TLS/Noise/QUIC/L3 route authorization 完成后安装 fast-path entry。 |
| Peer lifecycle 和 key lifecycle 是分离操作。 | 如果未来 offload crypto,ABI 应该区分 tunnel/session 创建和 crypto/session material。 |
| Key swap 是显式操作,并有通知。 | 未来 key 或 session rotation 必须 generation-aware、可观测,不能藏在 packet loss 后面。 |
| Peer deletion 和 peer floating 是显式通知。 | Helper/kernel path 必须把 teardown、endpoint change、expiry、error reason 报回 agent。 |
| 转发决策使用主机 kernel routing tables。 | NexusNet L3 routes 应该通过普通 host route tables 或显式 routing tables 可见,而不是全部藏进 DCO。 |
| Unsupported features 会禁用 DCO 并 fallback 到 userspace。 | NexusNet control plane 不能依赖 DCO;每条 offload path 都需要 userspace fallback 和清晰禁用原因。 |
| DCO 有意拒绝 compression、packet manipulation 等复杂 legacy feature。 | NexusNet DCO 应该拒绝不支持的 protocol mix,而不是把 policy、fallback 或 transformation logic 放进 kernel/helper。 |
最重要的反向经验是:DCO 不是保留所有功能的地方。一个 deep fast-path module 只有在 interface 足够小、invariant 足够严格时才值得存在。
直接集成 ovpn 的评估
直接使用 Linux ovpn 作为 NexusNet kernel path 不是推荐默认路线。它只可能作为独立 compatibility mode。
| 选项 | 适配度 | 原因 |
|---|---|---|
用 ovpn 直接承载当前 QUIC L3 | 差 | 当前 NexusNet packet 是 CONNECT-IP-framed IP over QUIC DATAGRAM,security 为 REALITY。ovpn 预期 OpenVPN data-channel semantics、peer IDs、keys、ciphers 和自己的 netlink ABI。 |
| 增加独立 OpenVPN-compatible product mode | 可行但独立 | 这是 OpenVPN interoperability feature,不是当前 NexusNet REALITY/QUIC dataplane 的加速。 |
借鉴 ovpn 架构做 NexusNet helper/kernel DCO | 强 | userspace-control/kernel-fast-path split 符合当前 roadmap,并保留 NexusNet protocol semantics。 |
| 立即构建 custom kernel module | 过早 | ABI、counter、generation model、fallback semantics、benchmark baseline 都还没验证。 |
| 先构建 privileged helper | 强 | 能以更低 kernel compatibility 和 crash 风险验证大部分 ABI 与 lifecycle。 |
如果未来增加 OpenVPN-compatible mode,它应被建模为独立 transport profile 或 compatibility product mode,不应混入现有 payload=ip、outer=quic、security=reality 的 CONNECT-IP profile。
Kernel 能帮到哪里
| 区域 | 候选能力 | 适用路径 | 预期效果 |
|---|---|---|---|
| Socket buffers | SO_RCVBUF、SO_SNDBUF、autotuning、busy-poll | TCP RAW/TLS/REALITY、UDP RAW/Noise/QUIC | 提高 burst 容忍度,降低高负载丢包。 |
| TCP tuning | TCP_NODELAY、keepalive、TCP_INFO、pacing 相关 sysctl | 所有 TCP listener 和 upstream connection | 降低延迟,增强观测,改善故障清理。 |
| UDP GSO/GRO | UDP segmentation / aggregation offload | QUIC REALITY、UDP DATAGRAM、L3 DATAGRAM | 减少 syscall,降低大 burst 的 per-packet CPU。 |
| NIC checksum/TSO/LRO | NIC driver 硬件 offload | TCP 和 UDP outer packets | 降低 checksum/segmentation CPU 成本。 |
| RSS/RPS/XPS | Kernel/NIC queue steering | 高流量 TCP/UDP listener | 改善多核队列分布。 |
SO_REUSEPORT + BPF | 多 worker socket 的 kernel listener selection | listener family 已确定后的 scale-out | 增强 accept/recv 并行度;不负责 route 授权。 |
| XDP | driver-ingress eBPF | UDP flood、closed ports、粗粒度 allow/drop | 在 SKB allocation 前丢弃或计数。 |
| tc eBPF | SKB ingress/egress hook | L3 tunnel mark、redirect、rate/drop policy | 快速 packet marking 和粗粒度 tunnel policy。 |
| nftables/iptables | Netfilter policy | Host firewall、NAT、mark、粗粒度 deny | 保护 agent socket,不适合协议分类。 |
| TUN/TAP offload | multiqueue、checksum/GSO flags、batch IO | IP over QUIC REALITY DATAGRAM | 降低 TUN 侧 per-packet overhead。 |
| AF_XDP | Userspace packet rings | 重 UDP 和 L3 dataplane 实验 | 给选定队列做 kernel bypass,必须有明确 helper ownership。 |
| io_uring | Async socket/TUN batching | TCP/UDP relay 和 helper 设计 | 不把协议逻辑放进 kernel,也能降低 syscall overhead。 |
| Kernel module | 自定义 dataplane | route 授权后的稳定 L3/UDP fast path | 吞吐潜力最高,维护风险最高。 |
应优先交给 kernel/helper 的具体职责
这些职责适合 offload,因为 interface 小、失败模式清楚,并且不要求 kernel/helper 做产品级协议决策:
- 分配、配置并暴露 packet device 或 queue。
- 批量化 TUN、UDP socket、AF_XDP ring 或 shared memory ring 的 packet receive/send。
- 在 packet format 已经稳定后应用 GSO/GRO/checksum metadata。
- 在流量进入 agent 前,丢弃 disabled listener port 或明显错误的 transport family。
- 统计 packets、bytes、drops、malformed frames、queue depth 和 per-entry expiry。
- 在 userspace 已经生成粗粒度 policy 后,为 routing、QoS 或 debug 做 packet mark。
- 为已经授权的 L3 tunnel 执行 allowed source prefixes。
- 当 config generation 不再是 current 时让 fast-path entry 过期。
- 当 offloaded peer/session 被删除、过期、迁移或遇到 unsupported packet condition 时通知 userspace。
应避免交给 kernel/helper 的职责
这些职责刻意留在 fast path 外:
- 解析 ClientHello 并决定产品路由。
- 执行 REALITY X25519 authentication、short ID selection、target probing 或 camouflage fallback。
- 选择 TLS certificates 或决定 SNI policy。
- 在 UDP Noise 首包里尝试多个 identity。
- 在 Quinn 仍是 runtime 时,拥有 QUIC loss recovery、congestion control、stream state 或 DATAGRAM semantics。
- 创建 hidden ports、hidden listeners 或 hidden fallback routes。
- 成为 backend config validity 的事实来源。
- 当 operator 需要产品级解释时,只返回 opaque kernel errors。
边界很简单:kernel/helper 可以加速一个已经完成的决定,但不能成为 NexusNet route 被选择的地方。
按协议看适配度
| 协议路径 | 适合 DCO 的点 | 必须留在用户态的点 | 说明 |
|---|---|---|---|
| TCP RAW | accept scaling、socket buffers、TCP_INFO、io_uring relay | Rule conflict decisions | RAW 没有协议标签,不能无损同端口复用。 |
| TCP TLS | SNI 后稳定 relay、socket/TCP tuning | TLS accept、cert selection、SNI route policy | Kernel 可在 TLS accept 后帮忙,不应负责 route policy。 |
| TCP REALITY | 已接受 stream 的稳定 relay | REALITY auth、fallback target probing、short ID policy | Fallback 是产品语义,必须可审计。 |
| TCP over QUIC REALITY | QUIC UDP GSO、buffers、queue steering | QUIC connection state 和 REALITY crypto bridge | Quinn 当前负责 recovery、pacing、loss、crypto integration。 |
| UDP RAW | recv batching、socket buffers、session table acceleration | Rule conflicts 和 upstream policy | RAW route key 只有 client address。 |
| UDP Noise | handshake 后 session fast path | 首包 key trial、key lifecycle、error logs | 第一包可能贵,但它是 security-sensitive path。 |
| UDP over QUIC REALITY | UDP GSO/GRO、DATAGRAM queue metrics、AF_XDP 实验 | QUIC connection 和 REALITY authentication | 用户态 session setup 后是很好的 DCO 候选。 |
| IP over QUIC REALITY DATAGRAM | TUN multiqueue、tc marks、AF_XDP/helper rings | Tunnel authorization、routes、MTU policy | 长期最适合 DCO,因为 setup 后 packet 形态统一。 |
| Control plane | 不适合 dataplane DCO | validators、credentials、deployment generation | Kernel 绝不能成为 config validity 的事实来源。 |
DCO 不能负责什么
| 行为 | 原因 |
|---|---|
| Listener conflict resolution | 同端口 route 合并是产品规则,依赖 SNI、REALITY short ID、UDP Noise key、QUIC Initial 检测和 RAW fallback 数量限制。 |
| Hidden fallback port allocation | 显式 listener 冲突必须可见失败,或者可见地丢弃不可分流重复项。 |
| TLS certificate selection and accept policy | 依赖 control-plane credential state 和清晰的 operator error。 |
| REALITY authentication and fallback | 包含 X25519 auth、SNI、short ID、target probing 和 camouflage fallback。 |
| UDP Noise key lifecycle | Key lookup、rotation、validation、logging 属于 agent/backend。 |
| RAW same-port multiplexing | RAW 没有 route discriminator,kernel 不能安全推断 route intent。 |
| QUIC recovery/congestion | Quinn 当前负责这些状态;partial offload 不能拆坏语义。 |
| Human-readable diagnostics | Operator 需要日志说明哪个 rule 被保留、丢弃或拒绝,以及原因。 |
实用 DCO 形态
Stage 0:调优当前用户态
先用 kernel-assisted primitives,不引入新的 DCO ABI:
- 在 benchmark 证明有收益的路径保持 QUIC UDP GSO。
- 按 listener class 调 TCP/UDP socket buffers。
- 保持 TCP_INFO 和 route-level metrics 可见。
- 批量化 TUN 和 UDP read/write。
- 只在确实改善 CPU 分布时启用 multiqueue。
预期效果:不增加部署依赖的情况下提升吞吐、降低丢包。
Stage 1:eBPF prefilter 和 counters
用 XDP/tc/eBPF 只做简单判断:
- 丢弃 closed 或 disabled listener port 的流量。
- 按 listener address 和 protocol family 统计 packets、bytes、drops。
- 给 routing、QoS 或 debug 做 packet mark。
- 执行 control plane 生成的粗粒度 deny rules。
预期效果:扫描、洪泛或高流量 DATAGRAM 下减轻用户态压力。此阶段仍不分类 TLS/REALITY/Noise route。
Stage 2:Helper fast path
引入可选 privileged helper,使用 AF_XDP、io_uring 或 shared memory rings:
agent config generation
-> helper route table
-> packet rings / batched sockets
-> agent-owned session setup and teardown预期效果:获得大部分 batching 收益,回滚风险比 kernel module 低。它应该作为自定义 kernel code 前的验证场。
Stage 3:Stable session offload
用户态接受 route/session 后,可以安装带 generation 的 fast-path entry:
generation + listener id + protocol family
-> peer tuple / session id / tunnel id
-> allowed prefixes or client address
-> MTU, marks, queues
-> counters and expiry适合候选:
- Tunnel setup 后的 L3 DATAGRAM packets。
- REALITY auth 后的 UDP over QUIC DATAGRAM sessions。
- 第一个 datagram 选中 key 后的 UDP Noise sessions。
- TLS/REALITY handshake 和 route selection 后的 TCP relay,前提是 helper 能干净保持 stream semantics。
预期效果:降低长连接/高流量 session 的 per-packet CPU。代价是 config generation、counter reconciliation 和 failure cleanup。
Stage 4:Kernel module
只有当 helper benchmark 证明 ABI 和语义正确后,才考虑 kernel module。它吞吐潜力最高,但 compatibility、packaging、safety 和 support burden 也最大。
Fast-path ABI 草案
这不是实现承诺,而是未来 ADR 应该从这里开始的最小模型。
Control objects
| Object | 目的 | 安装方 | 删除方 |
|---|---|---|---|
Generation | 命名一次已部署 config snapshot。 | Agent 接受 backend config 后。 | 新 generation active 且旧 counters reconcile 后由 agent 删除。 |
ListenerFastPath | 粗粒度 listener/socket namespace entry。 | Agent 完成 listener priority resolution 后。 | Config change 或 listener shutdown 时由 agent 删除。 |
TunnelFastPath | 按 network/tunnel/context key 的 L3 tunnel entry。 | Agent 完成 L3 tunnel authorization 和 runtime start 后。 | Config change、tunnel disable 或 peer loss 时由 agent 删除。 |
SessionFastPath | 按 session tuple/id key 的 UDP/TCP session entry。 | 首包/handshake 完成 route selection 后由 agent 安装。 | Idle timeout、error、FIN/RST 或 config change 时删除。 |
PeerEndpoint | Remote tuple 和可选 floating state。 | Peer 已知后由 agent 安装。 | Endpoint 过期或变化时由 agent/helper/kernel 删除。 |
CryptoMaterial | 可选的未来 key material。 | Negotiation 成功后由 agent 安装。 | Key rotation 或 generation teardown 时删除。 |
CounterSnapshot | Packets、bytes、drops、errors、queue state。 | Helper/kernel 产生,agent 消费。 | 只有 agent ack 后才能清空或 rollover。 |
Common entry fields
每个 offloaded entry 都应该携带:
generation_id:单调递增 config generation。entry_id:用于 logs 和 counter reconciliation 的稳定 id。network_id或适用的 listener id。protocol_family:tcp、udp、ip或未来显式值。local_tuple和peer_tuple,用于 socket traffic。- CONNECT-IP entry 使用
datagram_context_id。 mtu和 maximum outer payload size。- L3 使用
allowed_source_prefixes。 - 当 host routing policy 需要时使用
mark、queue id 或 routing table id。 idle_timeout和 hardexpires_at,或 generation expiry rule。capability_mask:helper/kernel 实际接受的能力。fallback_reason:entry 无法 offload 时填充。
Lifecycle operations
OpenVPN ovpn netlink operations 提供了有用形状,但 NexusNet 应按自己的概念命名:
| Operation | 含义 |
|---|---|
generation.new | 开始新的 config generation,并声明 feature/capability expectations。 |
generation.commit | 所有 required entries 安装完成后,将 generation 标记 active。 |
generation.retire | 停止旧 generation 接收新流量,并准备 counter drain。 |
listener.new / listener.del | 安装或删除粗粒度 listener fast-path。 |
tunnel.new / tunnel.set / tunnel.del | 安装、更新或删除 L3 tunnel fast-path。 |
session.new / session.set / session.del | 安装、刷新或删除稳定 L4 session fast-path。 |
key.new / key.swap / key.del | 如果未来有 crypto 离开 userspace,用于可选 crypto lifecycle。 |
counters.get | 读取并 acknowledge generation/entry counters。 |
entry.flush | 删除匹配 generation、listener、tunnel、peer 或 protocol 的 entries。 |
events.subscribe | 接收 delete、expiry、error、endpoint-change 和 capability-change events。 |
Required events
Agent 必须能用产品语言解释每个 offload state transition。Helper/kernel path 应报告:
- entry installed;
- entry rejected,并带明确 unsupported capability;
- entry idle timeout expired;
- entry 因 generation retirement 删除;
- peer endpoint changed 或 unreachable;
- packet 被 source-prefix policy drop;
- packet 被 MTU/oversize policy drop;
- malformed frame 或 unsupported IP version;
- queue overflow 或 backpressure;
- counter rollover 或 counter read failure;
- helper/kernel capability after startup changed。
Generation rules
Stale fast-path state 是最大的正确性风险。Generation model 应比当前 userspace runtime 更严格:
- 新 generation 可以先 prepare,再 activation。
- 只有 agent commit 后 generation 才是 active。
- 非 active generation 的 entries 不能接受新 sessions。
- 旧 generation 的 existing sessions 只有在 agent 显式允许 drain 时才能继续。
- L3 entries 通常应原子切换,因为 route 和 MTU 变化可能静默误投递 packet。
generation.retire必须返回足够 counters,让 agent 报告最终 bytes/drops。- Agent restart 必须能发现并 retire stale entries,或者创建 process-owned lifetime 的 entries,避免 stale entries 意外存活。
Fallback rules
Fallback 必须显式:
- 如果 helper/kernel support 缺失,agent 记录一个清晰原因,并运行 userspace dataplane。
- 如果某个 entry 被拒绝,只 fallback 该 entry,除非被拒绝的 capability 是 generation-wide。
- 如果 counters 无法 reconcile,traffic 可以继续,但 status 必须显示 observability degraded。
- 如果 helper/kernel errors 重复出现,agent 应触发 circuit breaker,并停止为该 generation 安装新的 offload entries。
- Backend config validity 不能依赖 DCO availability。
第一个候选目标:L3 DATAGRAM offload
第一个严肃 offload 目标应该是 IP over QUIC REALITY DATAGRAM,或者该路径的 helper-backed 变体,因为 setup 后 packet 形态最干净。
当前 userspace path:
TUN packet
-> TunDevice::recv_packets
-> L3Dataplane::encode_tun_packet
-> CONNECT-IP payload with Context ID
-> L3DatagramTransport::send_frames
-> Quinn QUIC REALITY DATAGRAM
-> peer L3DatagramTransport::recv_datagrams
-> L3Dataplane::decode_transport_datagram
-> TunDevice::send_packets可能的 helper/kernel split:
Agent userspace
-> creates TUN, applies routes, performs QUIC REALITY auth
-> installs TunnelFastPath(generation, context_id, mtu, allowed_sources)
-> keeps fallback userspace dataplane ready
Helper/kernel
-> batches TUN packets
-> validates IP version, MTU, context id, and source prefix
-> moves frames through rings or sockets
-> reports counters and drops by entry id如果走真正 kernel module,最难的问题是 QUIC 是否仍留在 module 外。保留 Quinn 管 QUIC,只加速 TUN/ring movement,风险远低于拆分 QUIC recovery 或 DATAGRAM semantics。一个试图拥有 QUIC 的 custom module 会变成新的 transport runtime,而不是小步 DCO。
可能的 helper 形态
| Helper shape | 适用场景 | 风险 |
|---|---|---|
| io_uring helper | 使用普通 fd 做 socket/TUN batching。 | 风险较低,但仍经过 kernel/userspace 边界 copy。 |
| AF_XDP helper | 重 UDP ingress/egress 实验和 queue ownership。 | 依赖 NIC/driver support,并且需要谨慎 queue isolation。 |
| Shared-memory ring helper | 在 agent 和 privileged process 间传稳定 L3 frames。 | 需要自定义 flow control 和 crash cleanup。 |
| tc/XDP-only programs | Early drop、mark、coarse counters。 | 不足以完成完整 tunnel/session offload。 |
| Kernel module | 完整 custom dataplane。 | 性能潜力最高,compatibility/safety 负担也最高。 |
推荐验证路径:
userspace baseline
-> io_uring or ring helper
-> AF_XDP where the environment supports it
-> kernel module only after ABI and tests stabilize端口复用边界
DCO 必须尊重和 agent 一致的优先级:
REALITY > TLS > Noise > RAW推荐 ownership:
| 阶段 | Owner | 说明 |
|---|---|---|
| Config validation | Backend | 验证 credentials、route uniqueness 和 impossible combinations。 |
| Listener conflict resolution | Backend + agent | 决定同端口哪些 route 可以共存,并记录 rejected 或不可分流重复项。 |
| 首个 connection/datagram classification | Agent 用户态 | 解析 ClientHello、REALITY auth 或 Noise first datagram。 |
| Fallback/reject decision | Agent 用户态 | REALITY camouflage 和 operator diagnostics 都依赖这里。 |
| Stable session fast path | Kernel/helper optional | 只在 route selection 和 authorization 后启用。 |
| Counters and teardown | Agent + helper/kernel | Counters 必须能汇总,entry 必须按 config generation 过期。 |
Capability detection
Agent 应该在 startup 和 apply config 时检测 offload capabilities。检测结果应该进入结构化 status,而不是只写 log。
| Capability | Detection source | Status field idea |
|---|---|---|
| Linux TUN offload | TUN adapter creation 和 feature flags。 | tun_offload_available、tun_offload_enabled。 |
| TUN multiqueue | TUN adapter creation result。 | tun_multiqueue_available、queue_count。 |
| QUIC UDP GSO | Quinn/socket setup 和 runtime send behavior。 | quic_gso_requested、quic_gso_active。 |
| Socket buffer tuning | setsockopt result 和可读情况下的 effective socket buffer。 | socket_buffer_requested、socket_buffer_effective。 |
| XDP/tc program support | Loader capability check。 | prefilter_available、prefilter_program_id。 |
| AF_XDP | NIC/driver/queue support check。 | afxdp_available、afxdp_queue_count。 |
| Helper daemon | Version handshake。 | helper_version、helper_capabilities。 |
| Kernel module | netlink family 或 device capability probe。 | kernel_dco_available、kernel_dco_capabilities。 |
Frontend 未来应该区分:
- requested but unavailable;
- available but disabled by policy;
- enabled and active;
- enabled but degraded;
- 因 profile 使用 unsupported features 而 disabled。
Metrics 和 counter reconciliation
没有可观测性,offload 就不完整。Counters 至少要保留当前 L3 语义:
- packets 和 bytes from TUN;
- packets 和 bytes to TUN;
- datagram/frame transmit 和 receive counts;
- malformed packets;
- unsupported IP version;
- source-prefix rejects;
- oversized packets;
- TUN write errors;
- datagram/helper/kernel send errors。
额外 offload counters 应包括:
- helper/kernel accepted entries;
- helper/kernel rejected entries by reason;
- active entries by generation;
- retired entries awaiting counter drain;
- queue depth 和 high-water mark;
- ring drops 和 backpressure events;
- kernel/helper packet drops by policy;
- fallback count 和 fallback reason;
- counter read failures;
- stale generation flush count。
Counter reconciliation rules:
- Counters 以
generation_id和entry_id为 key。 - Helper/kernel 可以使用 monotonic counters;agent 计算 deltas。
- Agent 必须容忍 counter rollover。
- Entry 被遗忘前必须读取 final counters,除非 entry 因 crash 或 forced flush 丢失。
- Counter snapshot 应包含 helper/kernel boot id 或 instance id,让 agent 能检测 helper restart。
Security model
DCO 会改变 dataplane bug 的影响面。引入 kernel-facing code 前应该先写 security model。
必需性质:
- Backend 仍是 desired config 的事实来源。
- Agent 仍是决定安装哪些 entries 的权威。
- Helper/kernel code 只能接受来自本地 agent 的 generated entries。
- 使用 helper process 时,entry ids 和 generation ids 必须不可猜,或限定在 authenticated local control channel 内。
- Offload entries 必须 least-privilege:一个 tunnel entry 只能转发自己的 allowed prefixes、MTU、context id 和 peer tuple。
- 所有 unsupported protocol features 必须 fail closed 到 userspace fallback。
- Kernel/helper crash 不能静默绕过 policy。
- Sensitive key material 应留在 userspace,直到有具体理由 offload crypto。
- 如果未来 offload crypto material,key lifecycle 必须支持显式 install、swap、delete、zeroization 和 event reporting。
Test strategy
DCO tests 必须先证明和当前 userspace dataplane 等价,再证明速度。
| Test group | 证明内容 |
|---|---|
| L3 frame conformance | CONNECT-IP encode/decode、context id、IP version、MTU、payload length。 |
| Source policy | Allowed source prefixes、host peer addresses、reject counters。 |
| Multicast/broadcast policy | allow_multicast 和 allow_broadcast 行为一致。 |
| Keepalive | Keepalive frames 不变成 user packets,错误 context id 被计数。 |
| Batch behavior | Batched send/receive 保持 packet boundaries 和 partial-send accounting。 |
| Generation teardown | Config update 后 old entries 停止接受 packets。 |
| Counter reconciliation | Normal drain 和 forced teardown 下 userspace/offload counters 对齐。 |
| Fallback | Unsupported capability、missing helper、helper crash 都能回到 userspace path。 |
| Restart cleanup | Agent restart 能发现或清除 stale helper/kernel entries。 |
| Route visibility | Host routes 和 marks 可用标准 Linux tools 检查。 |
现有 generic L3Dataplane<Tun, Transport> 设计应保留为主 conformance harness。新 adapter 应跑同一组 fake 和 real-path cases,再和 local namespace integration tests 对比。
Benchmark strategy
Benchmark 必须隔离每个 offload layer 的影响。单一 “DCO on/off” 数字会误导。
最小矩阵:
| Dimension | Values |
|---|---|
| TUN offload | off, on |
| TUN multiqueue | off, on, queue count where supported |
| QUIC GSO | off, on |
| Batch size | 1, 32, 128, 512, 1024 |
| MTU | 1280, 1500, 4096, 9000 |
| Transport path | userspace Quinn, helper ring, AF_XDP where supported, future kernel module |
| Direction | connector to listener, listener to connector, bidirectional |
| Traffic shape | single flow, parallel flows, small packets, MTU-sized packets, mixed packets |
| Failure mode | clean run, peer restart, config update during load, helper restart |
必须输出:
- sender 和 receiver throughput;
- packet rate;
- p50/p95/p99 latency where applicable;
- CPU per process 和 per core;
- context switches;
- 可测情况下的 syscalls;
- drops 和 retransmission symptoms;
- queue high-water marks;
- memory high-water marks;
- final reconciled counters。
现有 nexus-agent/scripts/l3_offload_matrix.sh 是正确的 baseline script family。未来 scripts 应扩展它,而不是创建无关 benchmark format。
设计约束
- 保持 REALITY authentication 语义。
- 保持 TLS 和 Noise credential boundaries。
- 保持 QUIC DATAGRAM packet boundaries。
- L3 MTU 行为必须显式。
- 用户态 fallback 必须保留。
- Control plane 不能依赖 DCO 是否可用。
- 显式 listener 被占用时,不能静默创建另一个端口。
- 日志必须足够人类可读,能解释保留、丢弃和拒绝的规则。
开放决策
| 决策 | 状态 |
|---|---|
| eBPF/XDP、helper 或 kernel module。 | 规划 |
是否未来增加一个使用 Linux ovpn 的 OpenVPN-compatible mode。 | 规划 |
| session、route state、counter、config generation 的 user/kernel ABI。 | 规划 |
| 第一个有价值的 DCO 目标应该是 L3 DATAGRAM、UDP relay 还是 TCP relay。 | 规划 |
| 未来 crypto material 是否 ever offload,还是全部留在 userspace。 | 规划 |
| L3 offload 只加速 TUN/ring movement,还是引入非 QUIC transport mode。 | 规划 |
helper/kernel counters 如何合并进 agent MetricsReport。 | 规划 |
| 如何把 offload 和当前 Quinn GSO、用户态 batching 做公平 benchmark。 | 规划 |
| 如何保证 config update 后不可能残留 stale fast-path entry。 | 规划 |
| helper/kernel status 如何展示在 backend API 和 frontend tunnel status 中。 | 规划 |
下一步
| 项目 | 状态 |
|---|---|
记录一个 ADR:ovpn 是参考架构,不是 NexusNet 默认 DCO 依赖。 | 规划 |
| 在定义 offload counters 前,先稳定用户态 L3/L4 route logs。 | 规划 |
| 引入 kernel-facing code 前先写 ADR。 | 规划 |
实现 helper 前,先定义 DcoCapabilityReport 的 agent status 形状。 | 规划 |
| 构建 user-space、helper 和未来 DCO 可复用的 conformance tests。 | 规划 |
| 增加 benchmark scripts,对比 no-offload、GSO、TUN batch、io_uring、AF_XDP/helper 和未来自定义 DCO。 | 规划 |
| 定义 fast-path install/teardown 的最小 config generation 模型。 | 规划 |
| 只有当 userspace L3 metrics 已通过 control plane 上报后,再 prototype helper-backed L3 adapter。 | 规划 |