Skip to content

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 实现。已实现产品路径仍是用户态:

text
TCP/UDP socket 或 TUN
  -> nexus-agent classifier and dataplane
  -> RAW / TLS / REALITY / Noise / QUIC path
  -> upstream socket, peer agent, or peer TUN

DCO 不能替代 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-tree ovpn-dco 模块只面向 OpenVPN 2.6.x 和更早版本,仓库处于 maintenance mode,只接受重要 bugfix。
  • OpenVPN 2.7.0 及更新版本使用新的 upstream Linux ovpn kernel module。OpenVPN 的 README.dco.md 说明,ovpn 从 Linux 6.16 开始进入内核;更旧内核应使用 ovpn-backports
  • upstream kernel 文档暴露了 ovpn generic 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 真正有价值的是这个分工:

text
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:

text
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 目标。

参考链接:

为什么这是项目级能力

一个监听端口现在可以做很多事:

  • 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 查表:

text
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.rsudp.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 interfacenexus-agent/src/l3/tun.rs TunDeviceTunRsDeviceDcoTunDeviceAfXdpTunDevice 或 helper-owned TUN adapterInterface 已支持单 packet 和 batch receive/send。
L3 transportnexus-agent/src/l3/transport.rs L3DatagramTransportQuinn REALITY L3 DATAGRAM transport 和 fake test endpointDcoL3Transport 或 helper-ring transport最适合替换 packet movement,同时保留 CONNECT-IP 测试。
L3 dataplane loopnexus-agent/src/l3/dataplane.rs L3Dataplane<Tun, Transport>对 TUN 和 transport generic作为 DCO adapter conformance harness同一个 pump 和 validation 行为可以覆盖 userspace/helper/kernel path。
L3 runtime reconciliationnexus-agent/src/l3/mod.rs L3TunnelManager按 prepared tunnel 启停 TUN + QUIC runtime按 generation 安装/删除 offload entries已有 config apply 和 stale runtime reconciliation。
QUIC socket pathnexus-agent/src/gateway/quic.rs Quinn endpoint setupUDP socket buffers 和 Quinn GSO只做 socket offload/tuning,不 offload QUIC stateQuinn 继续负责 recovery、pacing、loss 和 QUIC crypto。
Network confignexus-agent/src/l3/net_config.rs NetworkConfigPlanLinux route add/delete wrapper为 helper/kernel 生成 route/mark/table对齐 OpenVPN DCO 的经验:routing 应该在 host tables 中可见。
Metricsnexus-agent/src/l3/metrics.rs 和 gateway QUIC metricsIn-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 DCOuserspace-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=ipouter=quicsecurity=reality 的 CONNECT-IP profile。

Kernel 能帮到哪里

区域候选能力适用路径预期效果
Socket buffersSO_RCVBUFSO_SNDBUF、autotuning、busy-pollTCP RAW/TLS/REALITY、UDP RAW/Noise/QUIC提高 burst 容忍度,降低高负载丢包。
TCP tuningTCP_NODELAY、keepalive、TCP_INFO、pacing 相关 sysctl所有 TCP listener 和 upstream connection降低延迟,增强观测,改善故障清理。
UDP GSO/GROUDP segmentation / aggregation offloadQUIC REALITY、UDP DATAGRAM、L3 DATAGRAM减少 syscall,降低大 burst 的 per-packet CPU。
NIC checksum/TSO/LRONIC driver 硬件 offloadTCP 和 UDP outer packets降低 checksum/segmentation CPU 成本。
RSS/RPS/XPSKernel/NIC queue steering高流量 TCP/UDP listener改善多核队列分布。
SO_REUSEPORT + BPF多 worker socket 的 kernel listener selectionlistener family 已确定后的 scale-out增强 accept/recv 并行度;不负责 route 授权。
XDPdriver-ingress eBPFUDP flood、closed ports、粗粒度 allow/drop在 SKB allocation 前丢弃或计数。
tc eBPFSKB ingress/egress hookL3 tunnel mark、redirect、rate/drop policy快速 packet marking 和粗粒度 tunnel policy。
nftables/iptablesNetfilter policyHost firewall、NAT、mark、粗粒度 deny保护 agent socket,不适合协议分类。
TUN/TAP offloadmultiqueue、checksum/GSO flags、batch IOIP over QUIC REALITY DATAGRAM降低 TUN 侧 per-packet overhead。
AF_XDPUserspace packet rings重 UDP 和 L3 dataplane 实验给选定队列做 kernel bypass,必须有明确 helper ownership。
io_uringAsync socket/TUN batchingTCP/UDP relay 和 helper 设计不把协议逻辑放进 kernel,也能降低 syscall overhead。
Kernel module自定义 dataplaneroute 授权后的稳定 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 RAWaccept scaling、socket buffers、TCP_INFO、io_uring relayRule conflict decisionsRAW 没有协议标签,不能无损同端口复用。
TCP TLSSNI 后稳定 relay、socket/TCP tuningTLS accept、cert selection、SNI route policyKernel 可在 TLS accept 后帮忙,不应负责 route policy。
TCP REALITY已接受 stream 的稳定 relayREALITY auth、fallback target probing、short ID policyFallback 是产品语义,必须可审计。
TCP over QUIC REALITYQUIC UDP GSO、buffers、queue steeringQUIC connection state 和 REALITY crypto bridgeQuinn 当前负责 recovery、pacing、loss、crypto integration。
UDP RAWrecv batching、socket buffers、session table accelerationRule conflicts 和 upstream policyRAW route key 只有 client address。
UDP Noisehandshake 后 session fast path首包 key trial、key lifecycle、error logs第一包可能贵,但它是 security-sensitive path。
UDP over QUIC REALITYUDP GSO/GRO、DATAGRAM queue metrics、AF_XDP 实验QUIC connection 和 REALITY authentication用户态 session setup 后是很好的 DCO 候选。
IP over QUIC REALITY DATAGRAMTUN multiqueue、tc marks、AF_XDP/helper ringsTunnel authorization、routes、MTU policy长期最适合 DCO,因为 setup 后 packet 形态统一。
Control plane不适合 dataplane DCOvalidators、credentials、deployment generationKernel 绝不能成为 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 lifecycleKey lookup、rotation、validation、logging 属于 agent/backend。
RAW same-port multiplexingRAW 没有 route discriminator,kernel 不能安全推断 route intent。
QUIC recovery/congestionQuinn 当前负责这些状态;partial offload 不能拆坏语义。
Human-readable diagnosticsOperator 需要日志说明哪个 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:

text
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:

text
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 时删除。
PeerEndpointRemote tuple 和可选 floating state。Peer 已知后由 agent 安装。Endpoint 过期或变化时由 agent/helper/kernel 删除。
CryptoMaterial可选的未来 key material。Negotiation 成功后由 agent 安装。Key rotation 或 generation teardown 时删除。
CounterSnapshotPackets、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_familytcpudpip 或未来显式值。
  • local_tuplepeer_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 和 hard expires_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:

text
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:

text
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 programsEarly drop、mark、coarse counters。不足以完成完整 tunnel/session offload。
Kernel module完整 custom dataplane。性能潜力最高,compatibility/safety 负担也最高。

推荐验证路径:

text
userspace baseline
  -> io_uring or ring helper
  -> AF_XDP where the environment supports it
  -> kernel module only after ABI and tests stabilize

端口复用边界

DCO 必须尊重和 agent 一致的优先级:

text
REALITY > TLS > Noise > RAW

推荐 ownership:

阶段Owner说明
Config validationBackend验证 credentials、route uniqueness 和 impossible combinations。
Listener conflict resolutionBackend + agent决定同端口哪些 route 可以共存,并记录 rejected 或不可分流重复项。
首个 connection/datagram classificationAgent 用户态解析 ClientHello、REALITY auth 或 Noise first datagram。
Fallback/reject decisionAgent 用户态REALITY camouflage 和 operator diagnostics 都依赖这里。
Stable session fast pathKernel/helper optional只在 route selection 和 authorization 后启用。
Counters and teardownAgent + helper/kernelCounters 必须能汇总,entry 必须按 config generation 过期。

Capability detection

Agent 应该在 startup 和 apply config 时检测 offload capabilities。检测结果应该进入结构化 status,而不是只写 log。

CapabilityDetection sourceStatus field idea
Linux TUN offloadTUN adapter creation 和 feature flags。tun_offload_availabletun_offload_enabled
TUN multiqueueTUN adapter creation result。tun_multiqueue_availablequeue_count
QUIC UDP GSOQuinn/socket setup 和 runtime send behavior。quic_gso_requestedquic_gso_active
Socket buffer tuningsetsockopt result 和可读情况下的 effective socket buffer。socket_buffer_requestedsocket_buffer_effective
XDP/tc program supportLoader capability check。prefilter_availableprefilter_program_id
AF_XDPNIC/driver/queue support check。afxdp_availableafxdp_queue_count
Helper daemonVersion handshake。helper_versionhelper_capabilities
Kernel modulenetlink family 或 device capability probe。kernel_dco_availablekernel_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_identry_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 conformanceCONNECT-IP encode/decode、context id、IP version、MTU、payload length。
Source policyAllowed source prefixes、host peer addresses、reject counters。
Multicast/broadcast policyallow_multicastallow_broadcast 行为一致。
KeepaliveKeepalive frames 不变成 user packets,错误 context id 被计数。
Batch behaviorBatched send/receive 保持 packet boundaries 和 partial-send accounting。
Generation teardownConfig update 后 old entries 停止接受 packets。
Counter reconciliationNormal drain 和 forced teardown 下 userspace/offload counters 对齐。
FallbackUnsupported capability、missing helper、helper crash 都能回到 userspace path。
Restart cleanupAgent restart 能发现或清除 stale helper/kernel entries。
Route visibilityHost 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” 数字会误导。

最小矩阵:

DimensionValues
TUN offloadoff, on
TUN multiqueueoff, on, queue count where supported
QUIC GSOoff, on
Batch size1, 32, 128, 512, 1024
MTU1280, 1500, 4096, 9000
Transport pathuserspace Quinn, helper ring, AF_XDP where supported, future kernel module
Directionconnector to listener, listener to connector, bidirectional
Traffic shapesingle flow, parallel flows, small packets, MTU-sized packets, mixed packets
Failure modeclean 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。规划

NexusNet documentation