NNSR Internal Compact Header 路线图
状态:规划
最后核对:2026-06-22
目标
SD-WAN 内部转发格式是 4 字节 MPLS 风格 compact label,名称为 NNSR-C。它是内部 header: label 放在逐跳 WireGuard 或 QUIC underlay 保护的 payload 里。Transit agent 只有 在完成本跳 underlay 认证和解密后才能读取它,然后再加密发送到下一跳。
本文不定义公网明文 label SD-WAN core。NexusNet 选择信任 WireGuard/BoringTun 和 QUIC/TLS 1.3/REALITY 的密码学安全,不再额外设计自研端到端 AEAD 层。
图的名字
下面这种 ASCII 盒图通常叫 RFC-style packet layout diagram、RFC-style bit diagram,或者 packet header bit-field diagram。中文可以叫 RFC 风格协议头部位图 或协议位字段图。
设计依据
最接近的 wire-format 参考是 MPLS label switching:
- RFC 3032 定义了 4-octet label stack entry,包含 20-bit label、3-bit traffic class、1-bit bottom-of-stack flag 和 8-bit TTL。
- 转发动作是查 label、按需替换或 pop label、更新 TTL、转发到下一跳。
- 这正好匹配 underlay decapsulation 之后的 SD-WAN transit:transit 节点不应该 重新跑策略匹配,也不拥有路径计算。
其他 RFC 形状不适合作为默认 NNSR header:
| 候选 | Header 成本 | 适配度 |
|---|---|---|
| MPLS 风格 label shim,RFC 3032 模型 | 每个 label 4 字节 | 最适合 compact label-swap。 |
| Geneve,RFC 8926 | 8 字节加 options | 灵活,但比当前需求更大、更通用。 |
| IPv6 SRH / SRv6,RFC 8754 | 8 字节 base 加每段 16 字节 | 对紧凑公网 SD-WAN 路径太重。 |
MTU 约束也要求内部 shim 尽量小:
- IPv6 Internet link 至少要支持 1280-octet MTU。
- UDP 应用应避免发送超过 path MTU 的 datagram。
- QUIC endpoint 必须能处理至少 1200-byte UDP datagram,所以 1200 bytes 是 QUIC 路径上保守规划的基线。
4 字节 NNSR-C Header
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Label / SID | TC |S| TTL |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+字段:
| 字段 | Bits | 含义 |
|---|---|---|
Label / SID | 20 | 当前 route generation 内 node-local forwarding label。 |
TC | 3 | Traffic class。初始为 0,保留给 QoS、OAM、fallback class 或 drop class。 |
S | 1 | Bottom-of-stack flag。初始 single-label 格式固定为 1。 |
TTL | 8 | Hop limit。每跳递减,到 0 丢包。 |
编码规则:
- 4 字节 compact label 使用 network byte order。
Label / SID占 32-bit word 的 bit 31 到 bit 12。TC占 bit 11 到 bit 9。S占 bit 8。TTL占 bit 7 到 bit 0。
Octet 编码:
| Octet | Bits | Encoding |
|---|---|---|
| 0 | 7..0 | Label[19:12] |
| 1 | 7..0 | Label[11:4] |
| 2 | 7..4 | Label[3:0] |
| 2 | 3..1 | TC[2:0] |
| 2 | 0 | S |
| 3 | 7..0 | TTL |
初始格式只使用一个 label。Label stack 保留给未来 service chaining 或嵌套 overlay, 但默认 SD-WAN 路径应保持 single-label。
WG NNSR Packet Layout
WG NNSR 表示 NNSR-C 是解密后的 WireGuard tunnel payload 的前 4 字节。公网 wire 上 compact label 被逐跳 WireGuard session 加密和认证。
公网 underlay packet:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ Outer IPv4 Header or Outer IPv6 Header ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UDP Source Port | UDP Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UDP Length | UDP Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| WireGuard Message Type = Data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| WireGuard Receiver Index |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ WireGuard Counter +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ AEAD ciphertext of: NNSR-C Label + Inner IPv4/IPv6 ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ WireGuard AEAD Tag (16 octets) ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Agent 做 WireGuard decapsulation 后可见的 payload:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Label / SID | TC |S| TTL |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver| |
+---+ +
| |
~ Inner IPv4 or IPv6 Packet ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+WG NNSR decrypted payload offsets:
| Offset | Length | Field |
|---|---|---|
| 0 | 4 | NNSR-C compact label。 |
| 4 | variable | Inner IPv4 或 IPv6 packet。第一个 nibble 是 4 或 6。 |
WG NNSR 到 inner IP packet 前的 overhead:
| Layer | Bytes |
|---|---|
| Outer IPv4 header | 20 |
| Outer IPv6 header | 40 |
| UDP header | 8 |
| WireGuard data header | 16 |
| WireGuard AEAD tag | 16 |
| NNSR-C label | 4 |
IPv4 underlay 到 inner IP 前是 64 字节,IPv6 underlay 到 inner IP 前是 84 字节。 链路层 overhead 不计入这里。
QUIC Tunnel NNSR Packet Layout
QUIC Tunnel NNSR 表示 NNSR-C 位于 QUIC DATAGRAM 内,在 QUIC packet protection 认证和解密之后可见。公网 wire 上外部观察者看不到 compact label。
公网 underlay packet:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ Outer IPv4 Header or Outer IPv6 Header ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UDP Source Port | UDP Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UDP Length | UDP Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ QUIC Header (long or short, variable) ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ QUIC packet-protected payload, including DATAGRAM frame ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+移除 QUIC packet protection 后的 QUIC DATAGRAM frame:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DATAGRAM Frame Type (QUIC varint, usually 1B) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Optional DATAGRAM Length (QUIC varint, if present) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ DATAGRAM Application Data ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+推荐的 Nexus QUIC Tunnel NNSR application data,QUIC decapsulation 后可见:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Label / SID | TC |S| TTL |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver| |
+---+ +
| |
~ Inner IPv4 or IPv6 Packet ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+推荐 QUIC Tunnel NNSR application-data offsets:
| Offset | Length | Field |
|---|---|---|
| 0 | 4 | NNSR-C compact label。 |
| 4 | variable | Inner IPv4 或 IPv6 packet。第一个 nibble 是 4 或 6。 |
兼容 HTTP/3 DATAGRAM 的 application data 可以保留现有 context prefix:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Quarter Stream ID / Context ID (QUIC varint, 4B) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Label / SID | TC |S| TTL |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver| |
+---+ +
| |
~ Inner IPv4 or IPv6 Packet ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+为了让 NNSR-C 保持 32-bit 对齐,SD-WAN QUIC context 应从固定编码为 4 字节的 QUIC varint 范围分配:
16384 <= context_id <= 1073741823HTTP/3-compatible offsets:
| Offset | Length | Field |
|---|---|---|
| 0 | 4 | Quarter Stream ID / Context ID,编码为 4-byte QUIC varint。 |
| 4 | 4 | NNSR-C compact label。 |
| 8 | variable | Inner IPv4 或 IPv6 packet。第一个 nibble 是 4 或 6。 |
转发语义
Transit lookup key:
(route_generation, local_label)Transit lookup value:
action: swap | pop | drop
next_label
next_node_short_id
underlay_profile_id
mtu
counter ids
egress_action_id, only for pop entriesTransit 行为:
decrypt/authenticate local WG or QUIC underlay
parse 4-byte NNSR-C label
if TTL <= 1: drop and count ttl_expired
lookup (generation, label)
if miss: drop and count missing_forward_entry
if action = swap:
replace label with next_label
decrement TTL
send via next hop WG or QUIC underlay
if action = pop:
strip 4-byte header
execute egress actionIngress 行为:
match packet against SD-WAN policy
select active path and first local label from runtime table
prepend NNSR-C label with configured TTL
send via first hop WG or QUIC underlayEgress 行为:
decrypt/authenticate local WG or QUIC underlay
pop label
execute NAT, remote_tun, local_route, service_upstream, or drop为什么删除 18 字节
当前 18 字节 header 里的多个字段对 fast path 是冗余的:
| 当前字段 | Compact 替代 |
|---|---|
path_id | Label table entry metadata。 |
hop_index | 由 local label progression 表达。 |
path_len | Transit 不需要;TTL 负责防环路。 |
ip_version | pop 后读 inner packet 第一个 nibble。 |
flow_hash | Underlay session、UDP source port、QUIC connection routing 或 table metadata。 |
payload_len | 来自 QUIC DATAGRAM、WG packet 或 packet buffer length。 |
每包省 14 字节不是 MTU 的全部问题,但和 QUIC、WireGuard、NAT、保守 MSS 规划叠加后 很有价值。继续保留双格式还会分裂 runtime negotiation、测试、UI 命名和运维诊断, 所以旧 codec 应删除,不设置保留路径。
公网封装位置
公网 wire format 不是:
Outer IP / UDP
NNSR-C clear label
Inner IPv4/IPv6 packet生产公网 wire format 是:
Outer IP / UDP
WG or QUIC protected packet
encrypted/authenticated payload:
NNSR-C compact label
Inner IPv4/IPv6 packet这意味着:
- 公网观察者看不到 NNSR label。
- Transit 节点只有在解密本地 underlay session 后才能读取 NNSR。
- 下一跳能解密,是因为上一跳会把 NNSR payload 重新加密进下一跳的 WG 或 QUIC session。
- 加密成本是逐跳的,随路径里的 underlay 链路数量增长。
eBPF 和用户态适配
NNSR-C 足够小,适合用户态 fast path;但它不承诺公网 pre-decrypt tc/XDP 转发。
允许的优化路线:
- 用户态解析、递减 TTL、替换 20-bit label,并通过选定 WG/QUIC adapter 转发。
- QUIC 和 WG worker 可以批量 decrypt、lookup、enqueue next-hop send。
- 未来 post-decap helper 可以在 underlay protection 移除后优化 label lookup。
- 明文 label tc/eBPF 模式只能作为非默认、受控环境 profile。
近期非目标:
- NIC 级 eBPF 直接从公网 packet 读取 NNSR-C。
- 公网明文 label swap 作为普通 SD-WAN 模式。
实施计划
- 新增 versioned NNSR-C codec。
- 后端 runtime generation 增加 per-hop local label 和 action type:
swap、pop或drop。 - 增加用户态 compact transit 测试,覆盖 ingress、swap、pop、TTL expiry、 missing label 和 route generation replacement。
- 增加 runtime feature negotiation:
nnsr_compact_label_v1。 - 将 NNSR-C 接入 QUIC REALITY 和 BoringTun WG adapter。
- 前端 path inspector 同时展示 logical path 和 compact label entries。
- 所有新 route generation 切换到 compact labels。
- 增加回归测试,确保新 runtime config 只生成 NNSR-C over protected underlay sessions。
待定决策
| 决策 | 当前方向 |
|---|---|
| Label scope | 每个 route generation 内 node-local。 |
| Underlay security | 逐跳 WG 或 QUIC/TLS 1.3;无自研 NNSR AEAD。 |
| Stack support | 保留 S;默认 single-label。 |
| TC 语义 | 初始为 0;保留给 OAM/fallback/QoS class。 |
| 认证 | Underlay authentication 加 generation-scoped labels。 |
| Replay handling | 由 underlay 负责;compact label 本身不解决 replay。 |
| Fragmentation | 通过 MTU/MSS planning 和 PLPMTUD 风格 probing 避免 fragmentation。 |
参考
- RFC 3032: MPLS Label Stack Encoding.
- RFC 2784: Generic Routing Encapsulation.
- RFC 7348: Virtual eXtensible Local Area Network.
- RFC 8754: IPv6 Segment Routing Header.
- RFC 8926: Geneve.
- RFC 8085: UDP Usage Guidelines.
- RFC 8200: IPv6 Specification.
- RFC 9000: QUIC.