UCP 控制协议 简述
摘要
UCP(User-space Control Protocol)是一个运行于 UDP 之上的用户态传输协议,自研设计,未申请 IANA 资源,属于私有协议。其设计目标是在保留 TCP 可靠传输语义(可靠、有序、流控、拥塞控制)的同时,解决 TCP 在三个维度上的结构性缺陷:连接迁移困难 (五元组标识)、恢复路径单一 (丢包检测依赖单一信号)、拥塞控制信号单一(依赖丢包或依赖单一模型)。UCP 以 32 位 Connection ID(CID)替代五元组作为主解复用键,以五路径恢复模型(SACK / DupACK / NAK / FEC / RTO)覆盖从主动纠错到被动兜底的全谱系丢包恢复,以 KCC2.0 模型驱动拥塞控制提供基于三组分 RTT 分解的速率控制。本文从报文格式、连接生命周期、序号语义、流控、确认机制、五路径恢复、拥塞控制、CID 机制、路径 MTU 探测、安全等角度完整解析该协议,所有数值均来自规范文档与参考实现。
1 协议定位与设计目标
1.1 为什么需要一个新的传输协议
UCP 面对的问题是应用层对传输层的能力诉求与传统协议供给之间的错位:
| 诉求 | TCP 的局限 | UCP 的回应 |
|---|---|---|
| 连接迁移 | 五元组标识,IP 变化即断连 | CID 标识,路径无关 |
| 低时延恢复 | 恢复信号单一(ACK 时序),无线/弱网下误判 | 五路径并行恢复 + 前向纠错 |
| 高吞吐拥塞控制 | 丢包式反馈在深缓冲网络无效 | KCC 模型驱动(带宽×时延) |
| 用户态可控 | 内核栈参数不可编程 | 三层实现(C# / C++ / 内核) |
UCP 不是 TCP 的改进,而是按"用户态、可迁移、多信号、模型驱动"四个原则重新设计的数据报传输协议。它在 UDP 之上实现连接语义,因此天然继承了 UDP 的无连接性、可迁移性与用户态可编程性,同时通过自身机制补齐可靠性。
1.2 协议栈位置
#mermaid-svg-PYnnSFbkpivkNSVG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PYnnSFbkpivkNSVG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PYnnSFbkpivkNSVG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PYnnSFbkpivkNSVG .error-icon{fill:#552222;}#mermaid-svg-PYnnSFbkpivkNSVG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PYnnSFbkpivkNSVG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PYnnSFbkpivkNSVG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PYnnSFbkpivkNSVG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PYnnSFbkpivkNSVG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PYnnSFbkpivkNSVG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PYnnSFbkpivkNSVG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PYnnSFbkpivkNSVG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PYnnSFbkpivkNSVG .marker.cross{stroke:#333333;}#mermaid-svg-PYnnSFbkpivkNSVG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PYnnSFbkpivkNSVG p{margin:0;}#mermaid-svg-PYnnSFbkpivkNSVG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PYnnSFbkpivkNSVG .cluster-label text{fill:#333;}#mermaid-svg-PYnnSFbkpivkNSVG .cluster-label span{color:#333;}#mermaid-svg-PYnnSFbkpivkNSVG .cluster-label span p{background-color:transparent;}#mermaid-svg-PYnnSFbkpivkNSVG .label text,#mermaid-svg-PYnnSFbkpivkNSVG span{fill:#333;color:#333;}#mermaid-svg-PYnnSFbkpivkNSVG .node rect,#mermaid-svg-PYnnSFbkpivkNSVG .node circle,#mermaid-svg-PYnnSFbkpivkNSVG .node ellipse,#mermaid-svg-PYnnSFbkpivkNSVG .node polygon,#mermaid-svg-PYnnSFbkpivkNSVG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PYnnSFbkpivkNSVG .rough-node .label text,#mermaid-svg-PYnnSFbkpivkNSVG .node .label text,#mermaid-svg-PYnnSFbkpivkNSVG .image-shape .label,#mermaid-svg-PYnnSFbkpivkNSVG .icon-shape .label{text-anchor:middle;}#mermaid-svg-PYnnSFbkpivkNSVG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PYnnSFbkpivkNSVG .rough-node .label,#mermaid-svg-PYnnSFbkpivkNSVG .node .label,#mermaid-svg-PYnnSFbkpivkNSVG .image-shape .label,#mermaid-svg-PYnnSFbkpivkNSVG .icon-shape .label{text-align:center;}#mermaid-svg-PYnnSFbkpivkNSVG .node.clickable{cursor:pointer;}#mermaid-svg-PYnnSFbkpivkNSVG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PYnnSFbkpivkNSVG .arrowheadPath{fill:#333333;}#mermaid-svg-PYnnSFbkpivkNSVG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PYnnSFbkpivkNSVG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PYnnSFbkpivkNSVG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PYnnSFbkpivkNSVG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PYnnSFbkpivkNSVG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PYnnSFbkpivkNSVG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PYnnSFbkpivkNSVG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PYnnSFbkpivkNSVG .cluster text{fill:#333;}#mermaid-svg-PYnnSFbkpivkNSVG .cluster span{color:#333;}#mermaid-svg-PYnnSFbkpivkNSVG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PYnnSFbkpivkNSVG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PYnnSFbkpivkNSVG rect.text{fill:none;stroke-width:0;}#mermaid-svg-PYnnSFbkpivkNSVG .icon-shape,#mermaid-svg-PYnnSFbkpivkNSVG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PYnnSFbkpivkNSVG .icon-shape p,#mermaid-svg-PYnnSFbkpivkNSVG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PYnnSFbkpivkNSVG .icon-shape .label rect,#mermaid-svg-PYnnSFbkpivkNSVG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PYnnSFbkpivkNSVG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PYnnSFbkpivkNSVG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PYnnSFbkpivkNSVG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用层
UCP 传输层
KCC 拥塞控制
五路径恢复
CID 迁移/轮换
DPLPMTUD
可选 DTLS 加密层
UDP
IP
UCP 自身不加密(所有字段明文),安全性由可选的 DTLS 层(RFC 9147)提供;CID 明文传输,仅作解复用标识,不是凭据。
1.3 三层实现
| 层 | 位置 | 说明 |
|---|---|---|
| 用户态 C# | UcpCongestionControl.cs 等 |
主实现 |
| 用户态 C++ | ucp_cc.cpp 等 |
高吞吐路径 |
| 内核模块 | linux/tcp_kcc.c |
Linux TCP 栈集成(v2.0) |
三套实现共享同一组编译期常量,并有 alignment 测试逐值比对(见第 13 章)。
1.4 六层架构与并发模型
实现侧采用六层架构(architecture.md:41-49):
| 层 | 组件 | 职责 |
|---|---|---|
| 应用层 | UcpServer, UcpConnection |
公共 API:被动接受(fair-queue)、异步收发(背压)、事件、诊断 |
| 协议控制 | UcpPcb |
每连接完整状态机:发送缓冲、接收乱序、ACK/SACK/NAK 管道、定时器、KCC、pacing、FEC |
| 拥塞与 pacing | UcpCongestionControl, PacingController, UcpRtoEstimator |
KCC 计算 pacing 率与 CWND;令牌桶;RTO 估计器 |
| 可靠性引擎 | UcpSackGenerator, NAK 状态机, UcpFecCodec |
SACK 块(最多 2 次)、NAK 三档观测、FEC(预计算 GF(256) 表) |
| 序列化 | UcpPacketCodec |
8 种报文的大端线格式,投递前完整性校验 |
| 网络驱动 | UcpNetwork, UcpDatagramNetwork |
引擎与 socket I/O 解耦:ConnId 解复用、DoEvents 定时分发、公平队列轮次、SerialQueue 协调 |
| 传输 | UdpSocketTransport |
UDP 收发与动态端口绑定;NetworkSimulator 实现同一接口(虚拟逻辑时钟) |
并发模型 :每连接由 SerialQueue(轻量级 strand,UcpPcb.cs:13)串行化全部协议状态访问------同一时刻只有一个执行体运行协议代码,无需细粒度锁。这是"每连接串行化、跨连接并行"的模型:单连接内部免竞争,多连接天然并行。发送路径 FlushSendQueueAsync 按序检查 CWND、pacing、公平队列、编码、发送。
2 报文格式
2.1 通用头(12 字节)
所有 UCP 报文以 12 字节通用头开始,多字节字段大端序:
#mermaid-svg-ZnKwvydpN0FFNaPW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZnKwvydpN0FFNaPW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZnKwvydpN0FFNaPW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZnKwvydpN0FFNaPW .error-icon{fill:#552222;}#mermaid-svg-ZnKwvydpN0FFNaPW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZnKwvydpN0FFNaPW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZnKwvydpN0FFNaPW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZnKwvydpN0FFNaPW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZnKwvydpN0FFNaPW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZnKwvydpN0FFNaPW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZnKwvydpN0FFNaPW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZnKwvydpN0FFNaPW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZnKwvydpN0FFNaPW .marker.cross{stroke:#333333;}#mermaid-svg-ZnKwvydpN0FFNaPW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZnKwvydpN0FFNaPW p{margin:0;}#mermaid-svg-ZnKwvydpN0FFNaPW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZnKwvydpN0FFNaPW .cluster-label text{fill:#333;}#mermaid-svg-ZnKwvydpN0FFNaPW .cluster-label span{color:#333;}#mermaid-svg-ZnKwvydpN0FFNaPW .cluster-label span p{background-color:transparent;}#mermaid-svg-ZnKwvydpN0FFNaPW .label text,#mermaid-svg-ZnKwvydpN0FFNaPW span{fill:#333;color:#333;}#mermaid-svg-ZnKwvydpN0FFNaPW .node rect,#mermaid-svg-ZnKwvydpN0FFNaPW .node circle,#mermaid-svg-ZnKwvydpN0FFNaPW .node ellipse,#mermaid-svg-ZnKwvydpN0FFNaPW .node polygon,#mermaid-svg-ZnKwvydpN0FFNaPW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZnKwvydpN0FFNaPW .rough-node .label text,#mermaid-svg-ZnKwvydpN0FFNaPW .node .label text,#mermaid-svg-ZnKwvydpN0FFNaPW .image-shape .label,#mermaid-svg-ZnKwvydpN0FFNaPW .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZnKwvydpN0FFNaPW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZnKwvydpN0FFNaPW .rough-node .label,#mermaid-svg-ZnKwvydpN0FFNaPW .node .label,#mermaid-svg-ZnKwvydpN0FFNaPW .image-shape .label,#mermaid-svg-ZnKwvydpN0FFNaPW .icon-shape .label{text-align:center;}#mermaid-svg-ZnKwvydpN0FFNaPW .node.clickable{cursor:pointer;}#mermaid-svg-ZnKwvydpN0FFNaPW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZnKwvydpN0FFNaPW .arrowheadPath{fill:#333333;}#mermaid-svg-ZnKwvydpN0FFNaPW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZnKwvydpN0FFNaPW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZnKwvydpN0FFNaPW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZnKwvydpN0FFNaPW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZnKwvydpN0FFNaPW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZnKwvydpN0FFNaPW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZnKwvydpN0FFNaPW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZnKwvydpN0FFNaPW .cluster text{fill:#333;}#mermaid-svg-ZnKwvydpN0FFNaPW .cluster span{color:#333;}#mermaid-svg-ZnKwvydpN0FFNaPW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZnKwvydpN0FFNaPW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZnKwvydpN0FFNaPW rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZnKwvydpN0FFNaPW .icon-shape,#mermaid-svg-ZnKwvydpN0FFNaPW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZnKwvydpN0FFNaPW .icon-shape p,#mermaid-svg-ZnKwvydpN0FFNaPW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZnKwvydpN0FFNaPW .icon-shape .label rect,#mermaid-svg-ZnKwvydpN0FFNaPW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZnKwvydpN0FFNaPW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZnKwvydpN0FFNaPW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZnKwvydpN0FFNaPW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Common Header 12B
Type 1B
Flags 1B
ConnId 4B
Timestamp 6B
| 字段 | 大小 | 说明 |
|---|---|---|
| Type | 1 字节 | 报文类型 |
| Flags | 1 字节 | 位标志(ACK 携带、分类、状态元数据) |
| ConnectionId | 4 字节 | 32 位随机连接标识,UDP 解复用主键 |
| Timestamp | 6 字节 | 48 位发送端本地微秒时间戳,约 8.9 年微秒范围,用于 RTT 测量(回显)与 PAWS |
2.2 报文类型
| 值 | 名称 | 说明 |
|---|---|---|
| 0x01 | SYN | 连接发起请求(16 字节:头 + ISN) |
| 0x02 | SYNACK | 连接接受响应(20 字节,必带 AckNumber=ISN_c+1) |
| 0x03 | ACK | 纯确认报文(28 字节 + SACK 块) |
| 0x04 | NAK | 否定确认(缺失序号显式上报) |
| 0x05 | DATA | 应用数据(20 字节基本头,带捎带 ACK 时 36 字节) |
| 0x06 | FIN | 优雅关闭 |
| 0x07 | RST | 硬复位(仅 12 字节头) |
| 0x08 | FecRepair | Reed-Solomon 前向纠错修复数据 |
保留值 0x00、0x09-0xFF。未知类型必须静默丢弃且不响应(防反射放大)。
2.3 Flags 位布局
| 位 | 掩码 | 名称 | 语义 |
|---|---|---|---|
| 0 | 0x01 | NeedAck | 请求立即 ACK(绕过延迟 ACK 定时器) |
| 1 | 0x02 | Retransmit | 重传标记(Karn 算法:不采样 RTT) |
| 2 | 0x04 | FinAck | 确认对端 FIN |
| 3 | 0x08 | HasAckNumber | 携带捎带 ACK 字段 |
| 4-5 | 0x30 | PriorityMask | 2 位优先级(0=后台/1=普通/2=交互/3=紧急) |
| 6 | 0x40 | MtuProbe | DPLPMTUD 探测(不采样 RTT,正常确认) |
| 7 | 0x80 | PathChallenge | 迁移路径验证(8 字节随机 token) |
HasAckNumber(位 3)是 UCP 最独特的机制:任何报文类型(DATA/NAK/SYNACK/FIN/FecRepair)在置位后追加 AckNumber(4B)+ SackCount(2B)+ SACK 块(N×8B)+ WindowSize(4B)+ EchoTimestamp(6B)。控制报文(SYN/SYNACK/FIN)只追加 AckNumber(紧凑)。捎带开销:纯 DATA 时 16 字节 / MSS 1220 为 1.31%,DATA+3 SACK 为 3.28%。
3 连接生命周期
3.1 状态机(7 态)
#mermaid-svg-0yrDGAavqjMyVZ4V{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0yrDGAavqjMyVZ4V .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0yrDGAavqjMyVZ4V .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0yrDGAavqjMyVZ4V .error-icon{fill:#552222;}#mermaid-svg-0yrDGAavqjMyVZ4V .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0yrDGAavqjMyVZ4V .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0yrDGAavqjMyVZ4V .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0yrDGAavqjMyVZ4V .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0yrDGAavqjMyVZ4V .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0yrDGAavqjMyVZ4V .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0yrDGAavqjMyVZ4V .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0yrDGAavqjMyVZ4V .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0yrDGAavqjMyVZ4V .marker.cross{stroke:#333333;}#mermaid-svg-0yrDGAavqjMyVZ4V svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0yrDGAavqjMyVZ4V p{margin:0;}#mermaid-svg-0yrDGAavqjMyVZ4V defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-0yrDGAavqjMyVZ4V g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-0yrDGAavqjMyVZ4V g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-0yrDGAavqjMyVZ4V g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-0yrDGAavqjMyVZ4V g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-0yrDGAavqjMyVZ4V g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-0yrDGAavqjMyVZ4V .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-0yrDGAavqjMyVZ4V .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-0yrDGAavqjMyVZ4V .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-0yrDGAavqjMyVZ4V .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-0yrDGAavqjMyVZ4V .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-0yrDGAavqjMyVZ4V .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-0yrDGAavqjMyVZ4V .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-0yrDGAavqjMyVZ4V .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0yrDGAavqjMyVZ4V .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0yrDGAavqjMyVZ4V .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0yrDGAavqjMyVZ4V .edgeLabel .label text{fill:#333;}#mermaid-svg-0yrDGAavqjMyVZ4V .label div .edgeLabel{color:#333;}#mermaid-svg-0yrDGAavqjMyVZ4V .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-0yrDGAavqjMyVZ4V .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-0yrDGAavqjMyVZ4V .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-0yrDGAavqjMyVZ4V .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-0yrDGAavqjMyVZ4V .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-0yrDGAavqjMyVZ4V .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0yrDGAavqjMyVZ4V .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0yrDGAavqjMyVZ4V #statediagram-barbEnd{fill:#333333;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0yrDGAavqjMyVZ4V .cluster-label,#mermaid-svg-0yrDGAavqjMyVZ4V .nodeLabel{color:#131300;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-0yrDGAavqjMyVZ4V .note-edge{stroke-dasharray:5;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-note text{fill:black;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram-note .nodeLabel{color:black;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagram .edgeLabel{color:red;}#mermaid-svg-0yrDGAavqjMyVZ4V #dependencyStart,#mermaid-svg-0yrDGAavqjMyVZ4V #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-0yrDGAavqjMyVZ4V .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0yrDGAavqjMyVZ4V :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端发送 SYN
服务端接收 SYN
收到 SYNACK
收到 ACK
发起 FIN
收到 FIN
收到 FIN-ACK
本地 FIN 被确认
RST / 超时 / Dispose
RST / 超时 / Dispose
RST / 超时 / Dispose
RST / 超时 / Dispose
RST / 超时 / Dispose
Init
HandshakeSynSent
HandshakeSynReceived
Established
ClosingFinSent
ClosingFinReceived
Closed
任状态可因三类事件直接进入 Closed:RTO 重传计数超过 MaxRetransmissions(10)、收到有效 RST、应用调用 Dispose()。PCB 资源由后台延迟清理线程释放(绝不在 PCB 自己的工作线程上执行)。
3.2 三次握手
握手使用独立于数据序号空间的控制包序号:
- 客户端以 CSPRNG 生成随机 32 位 ISN_c 与随机 ConnId,发送
SYN(Seq=ISN_c),进入 HandshakeSynSent,启动 connectTimer。 - 服务端校验 ConnId 无冲突、分配 PCB、生成 ISN_s,回复
SYNACK(Seq=ISN_s, Ack=ISN_c+1, EchoTimestamp=T_c1),进入 HandshakeSynReceived。 - 客户端校验 ConnId 与 AckNumber,进入 Established,发送
ACK(Ack=ISN_s+1)或带 HasAckNumber 的 DATA。
ISN 生成 :ISN = low32(SipHash-2-4(remote_address ‖ remote_port ‖ local_port ‖ microsecond_timestamp, secret_key))。secret_key 进程启动时从系统熵初始化。ISN 随机化防止旧连接的陈旧包被误认为新数据。
握手重传参数:MIN_HANDSHAKE_WAIT_MS=100、CONNECT_TIMEOUT_MS=5000、MaxRetransmissions=10。RTO 按 1.2 倍回退。
异常处理:
- SYN 丢失 → 按 RTO 回退重传 SYN;
- SYNACK 丢失 → 重传 SYNACK;
- 重复 SYN(同 ConnId 且处于 HandshakeSynReceived)→ 重发 SYNACK;
- 陈旧 ConnId(SYN 与 Established 状态冲突)→ 发 RST 拒绝;
- 非法字段(ConnId=0 或非法标志组合)→ 静默丢弃,不响应(防放大)。
3.3 优雅关闭(FIN)
UCP 采用两阶段 FIN 握手。因双向独立序号空间,全双工 FIN 确认只需一个往返(TCP 需四次挥手):
主动关闭:应用调用 CloseAsync() → 停止接收 SendData() → 排空阶段(等待发送缓冲所有段被确认)→ 发送带 HasAckNumber 的 FIN → 进入 ClosingFinSent → 收到 FIN-ACK 后进入 Closed。FIN 重传按当前 RTO(1.2 倍回退)间隔。
被动关闭:收到 FIN → 发送 FIN-ACK(FinAck|HasAckNumber)→ 进入 ClosingFinReceived → 应用收到 OnFinReceived 回调后可继续发送剩余数据 → 本地 FIN 被确认后关闭;若超时未完成,通用断连检测(DisconnectTimeoutMicros=4s)兜底判定并关闭(代码中无独立的 500ms disconnectTimer,RFC 声称的"初始 500ms"与实现不符,以代码为准)。
半关闭支持:发送 FIN 后仍正常处理入站 DATA;若 FIN 先于部分 DATA 到达(乱序),接收方不得丢弃后续 DATA------乱序数据插入 recvBuffer 正常投递。
FIN vs RST 选择:正常结束用 FIN;握手态/错误恢复/对端无响应用 RST;保护在途数据投递用 FIN。
3.4 连接复位(RST)
RST 仅 12 字节头,无任何附加字段。触发源:无效 ConnId、状态冲突、握手期意外报文、重传耗尽、Dispose、协议违规。接收 RST 后的处理序列:置停止标志 → 停止全部定时器(connect/disconnect/RTO/keepalive/延迟 ACK)→ 清空发送/接收缓冲 → 取消全部 FEC 解码组 → 强制进入 Closed → 回调 OnDisconnected(ConnectionReset) → 移交后台清理。
陈旧 PCB 处理 :关闭连接上的迟到包静默丢弃,不回复 RST(防反射放大)。
Keepalive 与断连检测 :keepalive 由发送空闲 驱动(基于 _lastAckSentMicros,KeepAliveIntervalMicros = 1s)------发送方在空闲期周期发送 keepalive 兼作路径探测。两个关键语义(UcpPcb.cs:187, 981-982, 3804-3808):(1) keepalive、数据、ACK、NAK 的接收都不得刷新 对端活跃时间戳------否则空闲连接到死对端会自我刷新、永不超时;(2) 出站发送也不计入对端活跃------否则 keepalive 会自我延续断连期限。断连判定:_lastPeerAliveMicros 超过 DisconnectTimeoutMicros = 4s 即判死。零窗口期间 keepalive 保持活跃,防止对端窗口恢复后本端仍挂起。
4 序号语义
4.1 32 位序号与比较谓词
UCP 使用 32 位无符号序号,采用 TCP 式圆形比较:
seq_a > seq_b iff (uint32_t)(seq_a - seq_b) < 2^31
seq_a < seq_b iff (uint32_t)(seq_b - seq_a) < 2^31
2^31 窗口覆盖约 21 亿个在途序号,远超任何实际发送缓冲容量。每个方向独立序号空间。
特殊值:0xFFFFFFFF(CID_ROTATE_SEQUENCE_MARKER)保留给 CID 轮换 DATA 报文。
4.2 回绕处理
32 位序号在 10 Gbps 链路(2^32 × 1200B / 1.25GB/s)上约 4123 秒回绕一次。回绕安全性依赖两个机制:
- 有符号差值比较 :
(int32_t)(a - b) < 0判定先后; - 接收窗口上限:接收窗口封顶 4096 包(≈4.9MB @ 1200B MSS),所有在途序号必然落在安全 2^31 窗口内------从结构上保证回绕不会产生歧义。
4.3 PAWS 保护
每个报文携带 48 位微秒时间戳。PAWS 检查:若 T < largest_timestamp_seen - 60s(MaxTimestampAgeMicros),判定为旧序号周期的陈旧重复,静默丢弃。60 秒阈值的选择依据:最大合理网络时延(卫星 RTT 约 600ms,含重试与缓冲)远小于 60 秒,任何延迟超过 60 秒的包要么是陈旧重复、要么是恶意注入。
特殊情况:初始状态(largest_timestamp_seen==0)首包必过;检测到时钟回退超阈值时应重置该记录;PAWS 适用于所有报文类型(含 ACK)。
5 分片与重组
应用消息超过 MSS 时拆分为多个 DATA 报文。每个分片携带 FragmentTotal 与 FragmentIndex:
- FragmentTotal=1 表示未分片(常见情况);
- 同一消息的分片间不得改变 FragmentTotal;
- 每个分片有独立序号,受全部可靠性机制独立保护;
- 分片可乱序到达,recvBuffer 按分片缓存;
- 完整消息(位图满)才拼接投递,部分消息不投递;
- 乱序投递被推迟到所有前序序号已投递(保持有序语义)。
分片元数据随累计 ACK 前进而清理,无独立重组超时;部分分片计入 queuedReceiveBytes,按比例缩减广告的 WindowSize。
6 流控
UCP 采用类 TCP 接收窗口流控:
WindowSize = RecvWindowPackets(4096) × MSS - queuedReceiveBytes
发送约束(双上界):
flightBytes + next_packet_size ≤ remoteWindowBytes
flightBytes + next_packet_size ≤ CWND
发送上限为 min(CWND, remoteWindowBytes)------标准 TCP/QUIC 流控界。
初始发送不受固定包数上限限制 :KCC2.0 从 BDP 目标计算初始 cwnd(见第 8 章),有数据即可发到 min(cwnd, 对端窗口)。
紧急重传豁免窗口约束(它们只是替换已在途计数的段,不增加总在途载荷)。
零窗口处理:WindowSize=0 时发送方挂起新 DATA、紧急重传继续、keepalive 定时器保持活跃。窗口从零转非零时接收方在出站报文上置 NeedAck,加速窗口重开检测。
缓冲参数 :接收窗口精确值 DEFAULT_RECV_WINDOW_BYTES = 4,997,120(4096×1220 ≈ 5MB);发送缓冲 DEFAULT_SEND_BUFFER_BYTES = 33,554,432(32MB)。部分分片计入 queuedReceiveBytes 缩减广告窗口。
公平队列 :发送路径经公平队列轮次(fair-queue rounds,UcpNetwork.cs:12)调度,Flags 中 2 位 PriorityMask(后台/普通/交互/紧急)映射调度权重;紧急重传绕过公平队列门(见 9.5)。
7 确认机制
7.1 捎带 ACK(Piggybacked ACK)
UCP 最具辨识度的机制。通过 HasAckNumber 标志,任何报文类型可同时携带数据与确认信息。语义与独立 ACK 完全相同:累计确认 + SACK 块 + 窗口 + 时间戳回显。
各类型规则:SYN 必须为 0(无对端数据可确认);SYNACK 必须为 1;ACK 隐含;NAK 建议为 1;DATA 在 m_ackPiggybackQueue 非空时置位(最常见路径);FIN 建议为 1;RST 通常为 0;FecRepair 可选。
收益量化:双向流中纯 ACK 报文占比通常低于 1%。单向流中 ACK 约每 100 微秒一个,提供高频 RTT 采样且开销低。
7.2 延迟 ACK 定时器(自适应)
接收有序 DATA → 置 pending ACK → 启动 100us 定时器 → 不立即回 ACK
定时器到期 → 有出站数据则捎带;否则发独立 ACK
提前触发: NeedAck 置位 / 乱序缓冲达 4 包 / 乱序 ACK 间隔 ≥ 250us(防洪泛)
延迟期间若收到对端捎带 ACK,可能已隐式确认本端数据,无需再回。
7.3 SACK 块
接收方在乱序 DATA 到达时生成 SACK 块(Start 含/End 含,8 字节)。编码前必须合并相邻/重叠块:
[100,200]+[200,300] → [100,300](相邻)
[100,200]+[150,250] → [100,250](重叠)
[100,200]+[201,300] → 不合并(间隔 1 序号)
SACK 抑制:每个块最多传输 MAX_SACK_SEND_COUNT=2 次,防止持续膨胀(潜在放大向量);2 次后缺口移交 NAK 路径。若两次 SACK 都丢失(5% 丢包率下概率 < 0.25%),NAK 兜底恢复,发送方终将得知缺口。
7.4 RTT 测量
rtt_micros = nowMicros() - ack.echo_timestamp
RTT 样本馈送两个消费者:KCC 拥塞控制(更新 MinRtt、BottleneckBandwidth、计算 pacing 增益)与 RTO 估计器(SRTT/RTTVAR)。SYNACK 的 EchoTimestamp 提供首个连接 RTT(SYN→SYNACK 往返)。
8 拥塞控制:KCC2.0
KCC(Kernel Congestion Control)是 UCP 的拥塞控制核心,一个模型驱动算法,以管道模型 BottleneckBandwidth × MinRtt 为基准。KCC 只是 UCP 的一个子系统------它消费第 7 章的 RTT 采样与第 9 章的丢失/递送事件,输出 pacing 速率与 cwnd 上限,约束第 6 章的发送路径。
8.1 三组分 RTT 模型(核心哲学)
物理上 RTT 由四组分构成:T_prop + T_trans + T_queue + T_proc。其中 T_trans 与 T_proc 端到端不可分离辨识,故 KCC 采用三组分行为模型:
| 组分 | 角色 | 处理 |
|---|---|---|
T_prop |
传播时延(锚点),仅路径改变时变化 | Geodesic 估计器估计 |
T_queue |
排队时延(信号),唯一拥塞信息 | 驱动 ECN 回退与 LT-BW 门控 |
T_noise |
噪声(干扰),零拥塞信息 | 结构性隔离,禁止直接触发降速 |
核心设计规则:T_prop 锚定、T_queue 信号、T_noise 隔离。噪声隔离不靠离群值丢弃(显式滤波),而靠 Geodesic 更新的结构性不对称------G1 瞬时吸收下行噪声、G2 以 12.2%/RTT 有界速率吸收上行噪声。
8.2 状态机(三态)
#mermaid-svg-YMuqbkMyuLACqlUx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YMuqbkMyuLACqlUx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YMuqbkMyuLACqlUx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YMuqbkMyuLACqlUx .error-icon{fill:#552222;}#mermaid-svg-YMuqbkMyuLACqlUx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YMuqbkMyuLACqlUx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YMuqbkMyuLACqlUx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YMuqbkMyuLACqlUx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YMuqbkMyuLACqlUx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YMuqbkMyuLACqlUx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YMuqbkMyuLACqlUx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YMuqbkMyuLACqlUx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YMuqbkMyuLACqlUx .marker.cross{stroke:#333333;}#mermaid-svg-YMuqbkMyuLACqlUx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YMuqbkMyuLACqlUx p{margin:0;}#mermaid-svg-YMuqbkMyuLACqlUx defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-YMuqbkMyuLACqlUx g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-YMuqbkMyuLACqlUx g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-YMuqbkMyuLACqlUx g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-YMuqbkMyuLACqlUx g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-YMuqbkMyuLACqlUx g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-YMuqbkMyuLACqlUx .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-YMuqbkMyuLACqlUx .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-YMuqbkMyuLACqlUx .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-YMuqbkMyuLACqlUx .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-YMuqbkMyuLACqlUx .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-YMuqbkMyuLACqlUx .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-YMuqbkMyuLACqlUx .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-YMuqbkMyuLACqlUx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YMuqbkMyuLACqlUx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YMuqbkMyuLACqlUx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YMuqbkMyuLACqlUx .edgeLabel .label text{fill:#333;}#mermaid-svg-YMuqbkMyuLACqlUx .label div .edgeLabel{color:#333;}#mermaid-svg-YMuqbkMyuLACqlUx .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-YMuqbkMyuLACqlUx .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-YMuqbkMyuLACqlUx .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-YMuqbkMyuLACqlUx .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-YMuqbkMyuLACqlUx .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-YMuqbkMyuLACqlUx .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YMuqbkMyuLACqlUx .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YMuqbkMyuLACqlUx #statediagram-barbEnd{fill:#333333;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YMuqbkMyuLACqlUx .cluster-label,#mermaid-svg-YMuqbkMyuLACqlUx .nodeLabel{color:#131300;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-YMuqbkMyuLACqlUx .note-edge{stroke-dasharray:5;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-note text{fill:black;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram-note .nodeLabel{color:black;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagram .edgeLabel{color:red;}#mermaid-svg-YMuqbkMyuLACqlUx #dependencyStart,#mermaid-svg-YMuqbkMyuLACqlUx #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-YMuqbkMyuLACqlUx .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YMuqbkMyuLACqlUx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 连接建立
full_bw_reached(连续 3 轮增长 < 1.25×)
在途 ≤ BDP 且计时器 ≥ 4×min_rtt(AND 门)
容量显著下降(LT-BW 触发)
8 相循环 {1.25, 0.75, 1.0×6}
STARTUP
DRAIN
PROBE_BW
- STARTUP :
KCC_HIGH_GAIN=739(≈2.887×)+KCC_CWND_GAIN=512(2.0×)探索带宽。退出判定KCC_FULL_BW_THRESH=320(= 1.25×,即BBR_UNIT×5/4):连续 3 轮递送率增长不足 1.25×(增长 < 25%)即置位full_bw_reached。置位后进入 DRAIN,pacing 保持退出前速率不再增长;另有 10 包闩锁------即使已达 BDP 目标仍继续增长到 10 包交付(镜像 tcp_kcc.c),防过早判定。 - DRAIN :
KCC_DRAIN_GAIN=88(≈0.344×)排空 STARTUP 积压队列。退出用 AND 门 (在途 ≤ BDP 且计时器 ≥ 4×min_rtt 同时满足)而非 BBR 的 OR 门:4-RTT 恰好覆盖最坏情况(1 BDP 积压)的排空时间t_drain = T_prop/0.25 = 4×T_prop,既保证排空又保证有界。 - PROBE_BW :8 相循环
{320,192,256×6}(1.25/0.75/1.0)。1.25× 探测产生 0.25×BDP 超额,0.75× 排空与之精确抵消(二次型意义);每相至少 1 RTT(dwell-time);进入时相位随机偏移防多流共振。 - 无 PROBE_RTT:BBR 每 10 秒主动收缩 cwnd 采 min_rtt;KCC 由 Geodesic 连续维护,无需打断发送。
8.3 Geodesic 传播时延估计器(G1/G2/G3)
KCC 的核心创新。与 Kalman 滤波的本质差异:无协方差、无过程模型/预测、无自适应增益------没有任何需调参的统计假设,噪声抑制来自更新规则本身的不对称:
| 特性 | 经典 Kalman | Geodesic |
|---|---|---|
| 协方差传播 | P 矩阵 | 无(标量) |
| 预测 | 状态转移+观测模型 | 无(纯观测驱动) |
| 增益 | 自适应 | 固定结构 |
状态 :x_est(T_prop 估计,10 位定点 z<<10)、p_est(置信代理,1000 满刻度,仅作门控不参与动态)、jitter_avg/qdelay_avg(EWMA 7/8)、sample_cnt。
更新规则(每 RTT 样本 z):
z < x_est(负创新): x_est = min(x_est, z) [G1]
z ≥ x_est(正创新): x_est = min(x_est + x_est×122/1000, z) [G2]
- G1 下行瞬时吸收:负创新(RTT 低于估计)立即收敛------下行噪声被瞬时吸收,路径缩短 1 RTT 内被跟踪。
- G2 上行有界增长:正创新(RTT 高于估计)最多 12.2%/RTT 几何增长且以观测值 z 封顶。持续队列最多使估计每 RTT 膨胀 12.2%(有界),且估计永不超过实测 RTT;对持续队列呈保守偏置(低估 T_prop → 低估 BDP → 不超发),这是安全性方向。
- 陈旧回拉 :128 轮(替代 BBR 的 10s 窗口)无 G3 触发且
x_est ≤ 1.10×min_rtt时,x_est 拉回 95%×min_rtt------防 G2 在长窗口内累积虚假越限。 - G3 路径增大检测 :双阈值------快速路径
x_est ≥ 1.10×min_rtt连续 6 次,慢速路径1.05~1.10×连续 7 次。分级锁定:min_rtt<5ms 仅快速路径;5-7.5ms 快速路径锁 6 次;≥7.5ms 双路径可用(低时延路径噪声占比大,需更高阈值)。G3 锁:计数器非零期间 min_rtt 追踪的窗口/SRTT 守卫/下拉全部锁住,防路径增大被误判为噪声吸收。G3 是唯一允许 T_prop 上升的通道(v2.0 将 fast 从 4 提到 6、slow 从累计 5 改连续 7,是 20% 仿真下的对抗误报调参)。
min_rtt 追踪体系(四层,配合 G3 参照与 model_rtt):
- 粘性阈值 75%:样本 < 75%×min_rtt 需连续 5 个合格样本才吸收;
- 快速回落:样本 < min_rtt/4 立即吸收;
- SRTT 守卫:SRTT ≥ 90%×min_rtt 时拒绝(链路仍在排队);
- Geodesic 下拉:sample_cnt≥5 且 x_est 连续 5 次 < 95%×min_rtt → min_rtt = x_est>>10;窗口 4 轮无更新按 25% 递减,无墙钟过期。
冷启动 :首样本 x_est=z<<10、p_est=1000、jitter=max(z>>2,1);第二样本钳制到 min_rtt<<10;前 5 样本 ECN/LT-BW 旁路。最坏误差 0.76×T_prop,期望约 0.38×T_prop。
8.4 BDP 目标与 cwnd
model_rtt = min(x_est >> 10, min_rtt_us) (sample_cnt≥5 后启用)
bdp = ceil(bw × model_rtt × gain >> 8 >> 24)
model_rtt 取 Geodesic 估计与追踪 min_rtt 的较小值(G4 规则)------既利用 Geodesic 噪声免疫,又保留 min_rtt 历史下限。无模型时回退初始 cwnd=10 包。
量化预算:BDP 加 3×tso_segs_goal 余量、取偶数段、PROBE_UP 相位加 2 段。
每 ACK 更新:STARTUP 期 cwnd += acked(slow-start 式);巡航期 cwnd = min(cwnd+acked, target)(上界收敛,不强制收缩)。丢包时 cwnd -= lost(下限 1),恢复期开启 packet conservation(cwnd = inflight + acked)。发送上限恒为 min(cwnd, 对端窗口)。
8.5 LT-BW 长期带宽
max-filter 在容量暂时下降(射频干扰、共享瓶颈)时被陈旧高值污染。LT-BW 专治长期低带宽:
- 触发:
loss/delivered > 50/256 ≈ 20%(KCC_LT_LOSS_THRESH,代码权威值;linux/README 中"25/256≈9.77%"与代码不符,以 tcp_kcc.c 为准); - 采样窗口 4, 16 RTT,EMA 更新(num=1/den=2);
- 双阈值拥塞门控:
qdelay_avg超动态阈值 且srtt - min_rtt > 5000us才生效; - 生效后
lt_use_bw=1强制 pacing 增益 1.0×(降级为保守模式,不再注入探测超额);48 RTT 无触发则过期。
8.6 ACK 聚合补偿
TSO 批量发送与 ACK 压缩使递送率采样失真。KCC 显式测量聚合量并补偿:
- 测量:epoch 内
extra_acked = 实际送达 - 速率×时间,双窗口 5-RTT 轮换,上限bw×100ms,每 epoch ≤ 0x100000; - 补偿:
cwnd += 256×extra_acked(1.0× 增益); - 门控:min_rtt ≥ 7.5ms 才启用(低时延路径聚合误差占比大,补偿可能放大噪声);
- 历史教训:早期"置信 FSM 双层补偿"导致 cwnd 膨胀触发丢包,v2.0 已移除,保持单一补偿层。
8.7 ECN(默认关闭)
kcc_ecn_enable=0。动机:Geodesic 方向门控已分离 T_queue 与 T_noise,RTT 增长本身即保守信号;ECN 在无 AQM 路径不出现,在有 AQM 路径提供相同排队信息,故默认不依赖。启用需 5 条件全满足(enable=1、路径协商、p_est 置信、采样≥5、非冷启动)。
回退规则:cwnd_gain' = cwnd_gain × (1 - backoff_frac),backoff_frac ≤ 20/100;探测相(pacing_gain>1.0)按 1/pacing_gain 缩放抑制;触发阈值 qdelay_avg > max(25%×min_rtt, 500us)。回退从不改 T_prop 估计(T_queue 驱动速率决策、T_noise 被隔离的贯彻)。
8.8 与 BBRv1 的差异
| 机制 | BBRv1 | KCC2.0 |
|---|---|---|
| 传播时延估计 | 10s 窗口化 min_rtt + PROBE_RTT | Geodesic G1/G2/G3 连续估计,无 PROBE_RTT |
| DRAIN 退出 | OR 门 | AND 门 + 4×min_rtt 安全超时 |
| ECN 响应 | 逐包 cwnd 减半 | EWMA 聚合 + 20% 上界 + 探测相抑制 |
| 带宽估计 | 仅 max-filter | max-filter + LT-BW(20% 丢包触发) |
| ACK 聚合 | 桶模型 | 显式测量补偿(min_rtt≥7.5ms 门控) |
8.9 KF:跨连接带宽共享(可选特性)
KF(Cross-Connection Kalman Filter)让同一主机上的多条 KCC 连接共享带宽观测,多流场景下新流可借用存量流的带宽知识快速启动(RFC 13.6e):
- 开关 :
kcc_kf_enable = 0(默认关闭,运行时 opt-in);模式kcc_kf_mode(0=峰值跟踪,1=瞬时)。 - 滤波结构 :标量估计器。过程噪声
P += 1<<20(Q_SHIFT=20);观测噪声R = (z × r_pct/100)²,r_pct 启动期 15%、稳态 5%;创新经 chi2 门控(KCC_KF_CHI2 = 384/100)------异常观测被衰减而非吸收;P+R溢出守卫1<<31。 - 快速启动 :折扣公平份额(
kcc_kf_discount 50/100)初始化 pacing 率,并把初始 cwnd 钳制到[max(cwnd, 10), KCC_KF_CWND_SEGS_MAX=20000]段。 - 边界:KF 只影响带宽域(初始 pacing 与 cwnd 上限),从不写 T_prop 域------与 Geodesic 的职责边界清晰;KF 状态在用户空间保持休眠,不参与默认路径。
8.10 TSO 段数自适应
pacing 与 TSO(TCP Segmentation Offload)的交互需要动态调整批大小(kcc_min_tso_segs(),linux/README.md:2555-2560):
- 速率阈值切换:
KCC_MIN_TSO_RATE = 1,200,000(1.2 Mbps),默认 TSO 除数KCC_MIN_TSO_RATE_DIV = 8; - 收敛且
jitter_ewma < 1000us:除数减半(8→4),允许更大 TSO 突发(低噪声路径); jitter_ewma > 4000us:除数加倍(8→16),缩小突发抑制抖动(高噪声路径)。
TSO 批大小与量化预算(3×tso_segs_goal 余量、偶数段)共同构成 cwnd 目标的发送整形。
9 五路径恢复
9.1 恢复模型
UCP 的五条独立恢复路径,是协议的另一个核心特色:
#mermaid-svg-PcRAB7Arb7hlC2PV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PcRAB7Arb7hlC2PV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PcRAB7Arb7hlC2PV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PcRAB7Arb7hlC2PV .error-icon{fill:#552222;}#mermaid-svg-PcRAB7Arb7hlC2PV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PcRAB7Arb7hlC2PV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PcRAB7Arb7hlC2PV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PcRAB7Arb7hlC2PV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PcRAB7Arb7hlC2PV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PcRAB7Arb7hlC2PV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PcRAB7Arb7hlC2PV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PcRAB7Arb7hlC2PV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PcRAB7Arb7hlC2PV .marker.cross{stroke:#333333;}#mermaid-svg-PcRAB7Arb7hlC2PV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PcRAB7Arb7hlC2PV p{margin:0;}#mermaid-svg-PcRAB7Arb7hlC2PV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PcRAB7Arb7hlC2PV .cluster-label text{fill:#333;}#mermaid-svg-PcRAB7Arb7hlC2PV .cluster-label span{color:#333;}#mermaid-svg-PcRAB7Arb7hlC2PV .cluster-label span p{background-color:transparent;}#mermaid-svg-PcRAB7Arb7hlC2PV .label text,#mermaid-svg-PcRAB7Arb7hlC2PV span{fill:#333;color:#333;}#mermaid-svg-PcRAB7Arb7hlC2PV .node rect,#mermaid-svg-PcRAB7Arb7hlC2PV .node circle,#mermaid-svg-PcRAB7Arb7hlC2PV .node ellipse,#mermaid-svg-PcRAB7Arb7hlC2PV .node polygon,#mermaid-svg-PcRAB7Arb7hlC2PV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PcRAB7Arb7hlC2PV .rough-node .label text,#mermaid-svg-PcRAB7Arb7hlC2PV .node .label text,#mermaid-svg-PcRAB7Arb7hlC2PV .image-shape .label,#mermaid-svg-PcRAB7Arb7hlC2PV .icon-shape .label{text-anchor:middle;}#mermaid-svg-PcRAB7Arb7hlC2PV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PcRAB7Arb7hlC2PV .rough-node .label,#mermaid-svg-PcRAB7Arb7hlC2PV .node .label,#mermaid-svg-PcRAB7Arb7hlC2PV .image-shape .label,#mermaid-svg-PcRAB7Arb7hlC2PV .icon-shape .label{text-align:center;}#mermaid-svg-PcRAB7Arb7hlC2PV .node.clickable{cursor:pointer;}#mermaid-svg-PcRAB7Arb7hlC2PV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PcRAB7Arb7hlC2PV .arrowheadPath{fill:#333333;}#mermaid-svg-PcRAB7Arb7hlC2PV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PcRAB7Arb7hlC2PV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PcRAB7Arb7hlC2PV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PcRAB7Arb7hlC2PV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PcRAB7Arb7hlC2PV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PcRAB7Arb7hlC2PV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PcRAB7Arb7hlC2PV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PcRAB7Arb7hlC2PV .cluster text{fill:#333;}#mermaid-svg-PcRAB7Arb7hlC2PV .cluster span{color:#333;}#mermaid-svg-PcRAB7Arb7hlC2PV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PcRAB7Arb7hlC2PV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PcRAB7Arb7hlC2PV rect.text{fill:none;stroke-width:0;}#mermaid-svg-PcRAB7Arb7hlC2PV .icon-shape,#mermaid-svg-PcRAB7Arb7hlC2PV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PcRAB7Arb7hlC2PV .icon-shape p,#mermaid-svg-PcRAB7Arb7hlC2PV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PcRAB7Arb7hlC2PV .icon-shape .label rect,#mermaid-svg-PcRAB7Arb7hlC2PV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PcRAB7Arb7hlC2PV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PcRAB7Arb7hlC2PV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PcRAB7Arb7hlC2PV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
是
否
是
否
数据包丢失
SACK 2 观测 + 乱序宽限过期?
SACK 快速重传: 宽限 max5ms,SRTT
DupACK ≥ 3?
重复 ACK 快速重传
NAK 分档置信?
NAK 重传: 1-31 / 32-127 / ≥128 观测三档
FEC 组可解码?
FEC 前向纠错: RS-GF256 零时延
RTO 兜底: RFC6298 + 1.2x 回退
每丢失仅一路径: m_sackFastRetransmitNotified 去重
| 路径 | 触发 | 方向 | 角色 |
|---|---|---|---|
| SACK | 2 观测 + 乱序宽限过期 | 发送端 | 基于接收端报告的快速重传 |
| DupACK | 3 个相同累计 ACK | 发送端 | 无 SACK 时的快速重传 |
| NAK | 分档置信阈值 | 接收端 | 显式缺口上报,守卫递进 |
| FEC | 组收集完成 | 主动 | 零时延恢复(RS 纠错) |
| RTO | 超时 | 发送端 | 最终兜底 |
两条原则:
- 每丢失仅一路径 :
m_sackFastRetransmitNotified集合去重------首个标记重传的路径获胜,后续路径激活被抑制(防恢复竞争); - 优先级排序:RTO > SACK > NAK,全部紧急重传共享每 RTT 8192 包预算(UrgentRetransmitBudget)。
9.2 SACK 快速重传
- 阈值:2 个 SACK 观测;
- 乱序宽限:段龄 > max(5ms, RTT)(基于 SRTT);
- 距离阈值 48:最高 SACK 块之外超过 48 序号的额外缺口也可重传;
- 命中即标记紧急重传并加入去重集合。
9.3 NAK 分档置信
接收端驱动,三档递进守卫:
| 档 | 观测数 | 守卫公式 |
|---|---|---|
| 低 | 1-31 | max(2ms, min(RTT/2, MinRto))------缺口可能是乱序 |
| 中 | 32-127 | max(低档/2, 1ms)------证据积累,可能是真丢失 |
| 高 | 128+ | max(低档/2, 1ms)------压倒性,最快恢复 |
100ms RTT 跨洋链路低档守卫 50ms。重置条件:缺口被正常 DATA 填补、FEC 解码恢复、累计 ACK 越过、连接关闭。每序列每观测最多报告一次(防重复);NAK 频率受 SRTT 窗口限速(每 SRTT 最多 1024 个 NAK 包,每包最多 256 个缺失序号)。触发门槛:缺失序列达 NAK_MISSING_THRESHOLD=2 才进入上报路径(防单包乱序触发 NAK)。
9.4 RTO
RFC 6298 算法 + UCP 调整:SRTT EWMA α=1/8、RTTVAR β=1/4、RTO = SRTT + max(1ms, 4×RTTVAR)。超时后 RTO ×= 1.2,发送最老未确认段。200ms SRTT 起始回退序列:200→240→288→346→415→498→598→717→861→1033→1239ms。ACK 前进即重置 RTO 与计数器。边界:MIN_RTO=50ms、DEFAULT_MAX_RTO=15s、绝对上限 MAX_RTO=60s 。MaxRetransmissions=10 次后 RST 终止连接。RTO 批控:每 tick 最多 4 个 RTO 重传(防风暴)。
9.5 紧急重传机制
SACK/NAK 确认丢失后标记紧急重传:绕过正常 pacing 公平队列门,从令牌桶直接 ForceConsume(清零正令牌,不产生债务)。每 RTT 预算 8192 包,随 KCC 的新 RTT 样本重置。
9.6 FEC 前向纠错
Reed-Solomon over GF(256),主动零时延恢复:
- 组大小 N=8(可配置),修复冗余比例默认 0(关闭);
- 组内所有 DATA 必须等长 L(不同长度开新组);
- 编码用 Vandermonde 矩阵:修复值 = 各数据字节按 α^(i×k) 加权的 GF(256) 异或和(α=0x02 本原元);
- 解码用高斯消元:任意 N 个独立实体(DATA+修复混合)可唯一重建全部 N 字节,复杂度 O(N²×L);
- 本原多项式 P(x)=x⁸+x⁴+x³+x²+1(0x11D),与 AES 相同;预计算对数/反对数表实现 O(1) 乘除。
9.7 自适应 FEC
FEC 不是静态配置:FEC_ADAPTIVE_MIN_LOSS_PERCENT = 2%(UcpConstants.cs:764)作为自适应开关------当 KCC 估计丢失率 ≥ 2% 时,首发传输即附带修复包;低于 2% 不发修复(重传更便宜)。冗余比例与组大小范围(0.0-1.0 / 2-64)仍可配置,但不按丢失分档。这一设计使 FEC 开销只在值得时付出:低丢失网络零 FEC 开销,高丢失网络(无线/弱网)主动纠错生效。
9.8 TLP 与早期重传(辅助恢复路径)
五条主路径之外,UCP 还有两条针对"尾部丢失"的辅助机制(RFC.txt:213-214, 13.7):
- TLP(Tail Loss Probe) :发送队列已空且 in-flight 低(
TLP_MAX_INFLIGHT_SEGMENTS=2)时,主动多发一个数据段探测尾部丢失,超时TLP_TIMEOUT_RTT_RATIO=1.5 × SRTT(_tailLossProbePending,UcpPcb.cs:304)。尾部丢失是 RTO 误判的重灾区(发送方无后续 ACK 触发快速重传),TLP 用廉价探测把尾部丢失提前暴露为快速重传,避免整窗 RTO 等待。 - EARLY_RETRANSMIT(RFC 5827 早期重传) :in-flight ≤
EARLY_RETRANSMIT_MAX_INFLIGHT=4段时允许提前重传,配合 TLP 覆盖低 in-flight 场景。
10 CID 机制
10.1 生成
CID 是 32 位随机值,客户端以 CSPRNG 生成(独立于 ISN),随 SYN 发送;服务端提取后用于双向全部报文。CID 明文传输于每个包头------纯解复用标识,非安全凭据,安全由上层 DTLS 负责。
10.2 连接迁移
因连接以 CID 而非 IP/端口元组标识,端点可变更 IP/端口而不中断连接。m_remote 更新为每个接收包的源地址。全部协议状态跨迁移保留:序号、KCC 参数、pacing 令牌、FEC 组。
PATH_CHALLENGE 迁移验证(防劫持,类似 QUIC RFC9000 但适配 DATA 帧):
- 服务端收到新源地址 → 记录到 m_pendingRemote,不立即接受;
- 生成 8 字节随机 token,以 DATA(负载 8B,NeedAck)发往新地址;
- 客户端须在 3×RTO 内回显 token(PATH_RESPONSE,负载 8B,NeedAck);
- 收到期望 token → 接受新地址为 m_remote,清 pending;
- 超时 → 拒绝新地址,1 秒冷却后仍从其到达的包静默丢弃,连接继续用原地址。
安全性质:离路攻击者收不到 token 无法完成验证;在路攻击者能观察 token 可重定向------由 DTLS 加密全部内容(含 token)防护。
10.3 动态 CID 轮换
每 60 秒轮换 CID 防长期连接可链接性与离路 RST 注入:
CID_ROTATE_INTERVAL_MICROS = 60,000,000(60s)
CID_RETIRE_AGE_MICROS = 120,000,000(旧 CID 存活 120s)
CID_ROTATE_SEQUENCE_MARKER = 0xFFFFFFFF(轮换 DATA 报文保留序号)
发送方每 60s 生成新 CID,以 Seq=0xFFFFFFFF + 新 CID(4 字节负载)的 DATA 报文通告;120s 重叠期内新旧 CID 均有效(在途旧 CID 包安全到达)。接收方识别 marker、加入新 CID、移除旧 CID。轮换包必须经握手认证(仅接受完成三次握手且证明持有正确 ISN 与 CID 的对端),未认证源的 marker 包静默丢弃------防离路攻击者注入恶意轮换。轮换前应先用 PATH_CHALLENGE 验证当前路径可达。
10.4 CID 冲突处理
两个客户端独立选中相同 32 位 CID 连接同一服务端时冲突。碰撞概率:100 万并发连接下期望碰撞对 ~116;单连接碰撞概率 ~0.5% 时连接数须 << 6000。处理:服务端发现 CID 已占用(Established 或握手态)→ 向新 SYN 源发 RST(现有连接不受影响)→ 客户端换新 CID 重试。
11 DPLPMTUD
11.1 概述
UCP 实现 RFC 8899 式 DPLPMTUD,发现不触发 IP 分片的路径最大包长。不依赖 ICMP PTB(防火墙常过滤)。对 FEC 组编码是刚需:组内全部 DATA 必须等长。
11.2 探测与搜索
探测 = 特殊 DATA 报文(填充到目标尺寸、置 NeedAck、清 Retransmit)。确认判定:3×SRTT 内收到 ACK 视为有效。防误判超时用复合超时:
probe_timeout = max(3 × SRTT, MinRtt × 5)
二分搜索 1200, 1500:
lo=1200, hi=1500;探 mid=(lo+hi)/2
ACK → pmtu=mid, lo=mid+1;10s 超时 → hi=mid-1
终止: lo>hi 或 hi-lo≤8;周期重探 600s 检测 MTU 增大
每 RTT 限 1 个探测包
11.3 黑洞处理
探测超时即缩小上界继续二分------无独立黑洞冷却计时器或 PMTU 历史,收敛靠二分本身。防中间盒静默丢弃大包(IPv6-in-IPv4 隧道、老固件路由器的常见行为)。
12 安全
12.1 加密模型
UCP 明文,无加密/认证/完整性。安全依赖两层:
- DTLS(RFC 9147):应用以 ITransport 包装 UCP 数据报。激活后包头(含 ConnId)与负载一并加密,防被动连接跟踪;RST 注入因认证失败被阻止。
- 协议层防御(无 DTLS 时的纵深防御):CID 轮换(攻击窗口缩至 60s)、ISN 随机化(SipHash-2-4 密钥化)、PATH_CHALLENGE 验证。
12.2 威胁模型与缓解
| 攻击 | 风险 | 缓解 |
|---|---|---|
| RST 伪造 | 需知 32 位 CID(暴力空间 4.29e9)+ 可伪造源地址 | CID 轮换限窗口 60s;DTLS 完全阻止 |
| CID 预测 | 预知未来 CID 劫持/终止 | CSPRNG 生成,不可预测;轮换降低学习价值 |
| 反射放大 | 无效握手放大响应 | 非法包静默丢弃不响应;RST 绝不响应 RST;SYNACK≈SYN 尺寸(20 vs 16B)无放大;陈旧 PCB 全静默 |
| 连接劫持 | 伪造源地址迁移 | PATH_CHALLENGE token 验证可达性;DTLS 加密 token |
13 数学性质与验证
13.1 可靠性上界
- SACK 双次传输丢失概率 < 0.25%(5% 丢包率),NAK 兜底保证发送方终将得知缺口;
- 五路径覆盖从主动(FEC)到被动(SACK/DupACK/NAK)到兜底(RTO)的全谱系,且每丢失仅一路径(去重)消除恢复竞争。
13.2 拥塞控制性质(kcc-proofs 摘要)
注:以下为简化解析模型(AIMD 流体近似)论证,实际实现是 BBR 式 pacing 状态机,文档明确标注此建模注记。
- 稳定性:Lyapunov
V=(cwnd-cwnd*)²指数收缩;流体模型dc/dt = α(1-p)/RTT - β·p·c稳定点c* = α(1-p*)/(β·p*·RTT),Jacobian-β·p*<0; - 物理上界:吞吐 ≤
D/(D/B+τ),理论利用率 99.8%+(95% 概率界,与 Cardwell 的 BBR inflight 界兼容且更紧); - 队列界:
Q ≤ (δ-1)×BDP(探测增益 δ);8 相循环中 DRAIN 相保证每循环至少一个干净样本(p_clean>0 是设计推论); - 公平性:Nash 均衡下无单流占优策略,与 Reno 共存按 RTT 比例分享;
- 诚实性:工程类比(Lyapunov 界)用于设计论证,不等同微分几何最优性证明。
13.3 性能基准(模拟器)
基准框架(docs/performance.md)覆盖全目标工作域:100 Mbps-10 Gbps、1-300 ms RTT、0%-10% 丢包 。模拟器用令牌桶做带宽整形,串行化时延 = ceil(packetLength×1e6/bandwidthBps) 微秒/包,逻辑时钟(LogicalThroughputBytesPerSecond)排除主机调度噪声;物理吞吐与 KCC pacing 速率独立计量。
关键场景结果(模拟器, docs/performance.md:113-125):
| 场景 | 目标 | 吞吐利用 | 说明 |
|---|---|---|---|
| DataCenter | 10 Gbps / 2ms | 100.00% | 无丢失 |
| Benchmark10G | 10 Gbps / 2ms | 85.28% | 10MB 载荷自动探测 |
| LongFatPipe | 100 Mbps / 102ms | 64.35% | 长肥管道 |
| Gigabit_Loss1 | 1 Gbps / 1% 丢失 | 28.80% | 丢包场景 |
| Gigabit_Loss5 | 1 Gbps / 5% 丢失 | 20.05% | 丢包场景 |
验收规则(strict):吞吐 ≤ 目标×1.01(防物理不可能值)、无丢失利用 ≥ 70%、丢包场景利用 ≥ 45%、Loss%(网络观测)与 Retrans%(发送方计数)相互独立。测试规模:C++ 729/729、C# 644/644、DPLPMTUD 4/4。所有结果来自模拟器与回环测试,真实网络/AQM 交互/多流公平属边界验证范畴------结论是"实现与设计一致",而非"任意网络下最优"。
14 参数总表(关键常量)
| 分类 | 常量 | 值 |
|---|---|---|
| 报文 | MSS / 头 / 负载 | 1220 / 12 / 1200B |
| 握手 | 超时 / 最大重传 | 5000ms / 10 |
| 序号 | 回绕 / 窗口上限 | 4123s@10Gbps / 4096 包(4,997,120B) |
| PAWS | 最大时间戳年龄 | 60s |
| 缓冲 | 发送缓冲 / 接收窗口 | 32MB / ~5MB |
| 保活 | keepalive / 断连检测 | 1s / 4s |
| ACK | 延迟 ACK 定时器 | 100us |
| SACK | 阈值 / 每块传输 | 2 观测 / 2 次 |
| NAK | 触发 / 每包 / 每 RTT | 缺失≥2 / 256 序 / 1024 包 |
| RTO | 回退 / min / 默认 max / 绝对 max / 预算 | 1.2× / 50ms / 15s / 60s / 4 包每 tick |
| TLP | in-flight 触发 / 超时 | 2 段 / 1.5×SRTT |
| 早期重传 | in-flight 触发 | 4 段 |
| FEC | 组大小 / 本原多项式 / 自适应阈值 | 8 / 0x11D / 2% 丢失 |
| 迁移 | PATH_CHALLENGE | 8B token / 3×RTO / 1s 冷却 |
| CID | 轮换 / 退役 | 60s / 120s |
| PMTU | 范围 / 探测超时 / 重探 | 1200,1500 / 10s / 600s |
| KCC | HIGH_GAIN / DRAIN_GAIN / CWND_GAIN | 739 / 88 / 512 |
| KCC | 满带宽阈值 / G2 增长 / G3 阈值 | 1.25×3 轮 / 12.2%/RTT / 1.10×6·1.05×7 |
| KCC | LT-BW / 聚合 / ECN | 50/256 触发 / ≥7.5ms 门控 / 默认关 |
| KCC | TSO 除数 / KF | 8→4/16 自适应 / 默认关 |
15 局限与结论
15.1 局限
- 私有协议,无 IANA 注册(未申请端口/协议号),生态隔离;
- 明文传输,未用 DTLS 时面临 RST 伪造与连接跟踪(纵深防御仅缓解);
- CID 仅 32 位,极高并发(>6k 连接)碰撞概率上升,依赖 RST 重试路径;
- KCC 算法常量(增益/阈值/EWMA 权重)编译期固定,无运行时调节(增益衰减规划中);但内核模块的开关类参数 运行时可调------
kcc_kf_enable、kcc_kf_mode、kcc_kf_discount、kcc_probe_bw_up_limit、kcc_drain_and_or_mode(DRAIN 退出 AND/OR 门切换)、kcc_extra_acked_gain、kcc_ecn_enable、kcc_ecn_backoff共 18 个 module_param(tcp_kcc.c:3348-3357),经/sys/module/tcp_kcc/parameters/与/proc/sys/net/kcc/写入; - 理论结论在理想化假设下成立,实网验证范围有限;
- FEC 默认关闭,修复冗余需应用显式配置。
15.2 结论
UCP 的核心设计判断是:连接标识、恢复机制、拥塞信号这三件事不必沿用 TCP 的固定形态 。以 CID 换取迁移性与防跟踪性,以五路径恢复换取从毫秒级(FEC/SACK)到秒级(RTO)的全谱系丢包应对,以三组分 RTT 模型换取结构性的噪声隔离与保守性。其可靠性设计(捎带 ACK、延迟 ACK、SACK 抑制、NAK 分档、每丢失仅一路径)体现了一致的工程原则:信号要廉价(捎带/聚合)、证据要递进(NAK 分档)、路径要互斥(去重)、兜底要有界(RTO 批控与预算)。KCC 作为其拥塞控制子系统,同样贯彻"结构的保守性优先于统计的最优性"。
参考文献
- UCP RFC.txt(报文格式、连接管理、数据转移、确认、五路径恢复、KCC2.0、CID、DPLPMTUD、安全、常量表)
linux/README.md(三组分 RTT 模型、KCC vs BBR 差异、ISS 证明框架、TSO 自适应)linux/tcp_kcc.c(v2.0 内核实现,编译期常量权威来源)docs/architecture.md(六层架构、SerialQueue 并发模型)、docs/performance.md(基准框架与结果)、docs/constants.md(常量与自适应 FEC 阈值)、docs/kcc-proofs.md(稳定性/公平性/物理上界证明,含建模注记)- RFC 5827(早期重传)、RFC 6298(RTO 计算)、RFC 8899(DPLPMTUD)、RFC 9000(QUIC PATH_CHALLENGE)、RFC 9147(DTLS 1.3)
- Cardwell et al., "BBR: Congestion-Based Congestion Control", SIGCOMM 2018