XTCP简述
本文描述 XTCP 的实际构造:分层、线程、数据路径、状态机、插件接口与加锁
规则。文中每一条陈述都对应 src/ 与 include/xtcp/ 中的代码;凡设计选择
有代价之处,代价一并写明。
1. 简述
XTCP 是进程内库,不是守护进程。一个 XtcpStack 实例持有一组固定分片;
每个分片独占哈希到它的全部流的可变状态。数据路径上没有共享连接表,也没有
共享锁。
#mermaid-svg-iTPWCklpow6pF8Zl{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-iTPWCklpow6pF8Zl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iTPWCklpow6pF8Zl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iTPWCklpow6pF8Zl .error-icon{fill:#552222;}#mermaid-svg-iTPWCklpow6pF8Zl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iTPWCklpow6pF8Zl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iTPWCklpow6pF8Zl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iTPWCklpow6pF8Zl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iTPWCklpow6pF8Zl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iTPWCklpow6pF8Zl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iTPWCklpow6pF8Zl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iTPWCklpow6pF8Zl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iTPWCklpow6pF8Zl .marker.cross{stroke:#333333;}#mermaid-svg-iTPWCklpow6pF8Zl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iTPWCklpow6pF8Zl p{margin:0;}#mermaid-svg-iTPWCklpow6pF8Zl .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iTPWCklpow6pF8Zl .cluster-label text{fill:#333;}#mermaid-svg-iTPWCklpow6pF8Zl .cluster-label span{color:#333;}#mermaid-svg-iTPWCklpow6pF8Zl .cluster-label span p{background-color:transparent;}#mermaid-svg-iTPWCklpow6pF8Zl .label text,#mermaid-svg-iTPWCklpow6pF8Zl span{fill:#333;color:#333;}#mermaid-svg-iTPWCklpow6pF8Zl .node rect,#mermaid-svg-iTPWCklpow6pF8Zl .node circle,#mermaid-svg-iTPWCklpow6pF8Zl .node ellipse,#mermaid-svg-iTPWCklpow6pF8Zl .node polygon,#mermaid-svg-iTPWCklpow6pF8Zl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iTPWCklpow6pF8Zl .rough-node .label text,#mermaid-svg-iTPWCklpow6pF8Zl .node .label text,#mermaid-svg-iTPWCklpow6pF8Zl .image-shape .label,#mermaid-svg-iTPWCklpow6pF8Zl .icon-shape .label{text-anchor:middle;}#mermaid-svg-iTPWCklpow6pF8Zl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iTPWCklpow6pF8Zl .rough-node .label,#mermaid-svg-iTPWCklpow6pF8Zl .node .label,#mermaid-svg-iTPWCklpow6pF8Zl .image-shape .label,#mermaid-svg-iTPWCklpow6pF8Zl .icon-shape .label{text-align:center;}#mermaid-svg-iTPWCklpow6pF8Zl .node.clickable{cursor:pointer;}#mermaid-svg-iTPWCklpow6pF8Zl .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iTPWCklpow6pF8Zl .arrowheadPath{fill:#333333;}#mermaid-svg-iTPWCklpow6pF8Zl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iTPWCklpow6pF8Zl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iTPWCklpow6pF8Zl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iTPWCklpow6pF8Zl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iTPWCklpow6pF8Zl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iTPWCklpow6pF8Zl .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iTPWCklpow6pF8Zl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iTPWCklpow6pF8Zl .cluster text{fill:#333;}#mermaid-svg-iTPWCklpow6pF8Zl .cluster span{color:#333;}#mermaid-svg-iTPWCklpow6pF8Zl 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-iTPWCklpow6pF8Zl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iTPWCklpow6pF8Zl rect.text{fill:none;stroke-width:0;}#mermaid-svg-iTPWCklpow6pF8Zl .icon-shape,#mermaid-svg-iTPWCklpow6pF8Zl .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iTPWCklpow6pF8Zl .icon-shape p,#mermaid-svg-iTPWCklpow6pF8Zl .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iTPWCklpow6pF8Zl .icon-shape .label rect,#mermaid-svg-iTPWCklpow6pF8Zl .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iTPWCklpow6pF8Zl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iTPWCklpow6pF8Zl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iTPWCklpow6pF8Zl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用进程
XtcpStack
OnPacket
回调 + 调用
分片 0
流表 · 定时器 · 内存池 · 1 把锁
IP 层 v4 / v6
分片重组 · 路由钩子
分片 1
流表 · 定时器 · 内存池 · 1 把锁
...
共 kShardCount = 8 个
qdisc 层
FQ(默认)· fq_codel · cake · TBF
NDI 后端
manual(进程内)· TUN · TAP
应用线程
Connect / Send / Close / 回调
各层职责边界:
| 层 | 拥有 | 不拥有 |
|---|---|---|
| NDI 后端 | 与外部世界的报文收发 | 任何协议状态 |
| qdisc | 出向排序、pacing 速率、AQM 丢弃 | 流控制块 |
| IP | 地址、分片/重组、TTL、校验和 | TCP 状态 |
| 分片 | 其流的流表、定时器、缓冲池 | 其他分片的流 |
| TCP 连接 | 序号空间、窗口、重传队列、CC 状态 | 相邻连接 |
2. 线程模型
默认配置下 XTCP 不自行产生数据面线程。应用以一或多个线程驱动栈:
- 调用线程 执行
Connect、Send、Close、Listen。这些调用可并发;
每次调用获取目标分片的锁。 - 泵线程 经
OnPacket送入报文,并调用PollAckTimers推进时间
(延迟 ACK、RTO、persist、keepalive)。单线程即可泵全部;多线程可并发
泵不同分片,因为分片之间不共享锁。 - 异步 API(
include/xtcp/async.h)为每个栈增加一个事件循环,用
async_mutex串行化完成事件;它是可选的。
必须言明的推论:吞吐取决于调用方的泵送。PERFORMANCE.md 的基准都在紧循环
中驱动栈------那些数字背后没有任何隐藏的工作线程。
3. 分片与连接标识
连接在创建时定一次位,之后永不迁移:
#mermaid-svg-3gjVBcm35S3HuXT3{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-3gjVBcm35S3HuXT3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3gjVBcm35S3HuXT3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3gjVBcm35S3HuXT3 .error-icon{fill:#552222;}#mermaid-svg-3gjVBcm35S3HuXT3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3gjVBcm35S3HuXT3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3gjVBcm35S3HuXT3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3gjVBcm35S3HuXT3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3gjVBcm35S3HuXT3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3gjVBcm35S3HuXT3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3gjVBcm35S3HuXT3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3gjVBcm35S3HuXT3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3gjVBcm35S3HuXT3 .marker.cross{stroke:#333333;}#mermaid-svg-3gjVBcm35S3HuXT3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3gjVBcm35S3HuXT3 p{margin:0;}#mermaid-svg-3gjVBcm35S3HuXT3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-3gjVBcm35S3HuXT3 .cluster-label text{fill:#333;}#mermaid-svg-3gjVBcm35S3HuXT3 .cluster-label span{color:#333;}#mermaid-svg-3gjVBcm35S3HuXT3 .cluster-label span p{background-color:transparent;}#mermaid-svg-3gjVBcm35S3HuXT3 .label text,#mermaid-svg-3gjVBcm35S3HuXT3 span{fill:#333;color:#333;}#mermaid-svg-3gjVBcm35S3HuXT3 .node rect,#mermaid-svg-3gjVBcm35S3HuXT3 .node circle,#mermaid-svg-3gjVBcm35S3HuXT3 .node ellipse,#mermaid-svg-3gjVBcm35S3HuXT3 .node polygon,#mermaid-svg-3gjVBcm35S3HuXT3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3gjVBcm35S3HuXT3 .rough-node .label text,#mermaid-svg-3gjVBcm35S3HuXT3 .node .label text,#mermaid-svg-3gjVBcm35S3HuXT3 .image-shape .label,#mermaid-svg-3gjVBcm35S3HuXT3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-3gjVBcm35S3HuXT3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3gjVBcm35S3HuXT3 .rough-node .label,#mermaid-svg-3gjVBcm35S3HuXT3 .node .label,#mermaid-svg-3gjVBcm35S3HuXT3 .image-shape .label,#mermaid-svg-3gjVBcm35S3HuXT3 .icon-shape .label{text-align:center;}#mermaid-svg-3gjVBcm35S3HuXT3 .node.clickable{cursor:pointer;}#mermaid-svg-3gjVBcm35S3HuXT3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3gjVBcm35S3HuXT3 .arrowheadPath{fill:#333333;}#mermaid-svg-3gjVBcm35S3HuXT3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3gjVBcm35S3HuXT3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3gjVBcm35S3HuXT3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3gjVBcm35S3HuXT3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3gjVBcm35S3HuXT3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3gjVBcm35S3HuXT3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3gjVBcm35S3HuXT3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3gjVBcm35S3HuXT3 .cluster text{fill:#333;}#mermaid-svg-3gjVBcm35S3HuXT3 .cluster span{color:#333;}#mermaid-svg-3gjVBcm35S3HuXT3 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-3gjVBcm35S3HuXT3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3gjVBcm35S3HuXT3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-3gjVBcm35S3HuXT3 .icon-shape,#mermaid-svg-3gjVBcm35S3HuXT3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3gjVBcm35S3HuXT3 .icon-shape p,#mermaid-svg-3gjVBcm35S3HuXT3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3gjVBcm35S3HuXT3 .icon-shape .label rect,#mermaid-svg-3gjVBcm35S3HuXT3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3gjVBcm35S3HuXT3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3gjVBcm35S3HuXT3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3gjVBcm35S3HuXT3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 流键
(src ip, src port, dst ip, dst port)
scheduler_hash::HashFlowKey
MurmurHash3 fmix64 终结器
(雪崩化,避免连续端口
塌缩到同一分片)
% kShardCount (= 8)
分片索引
Connect 返回的 64 位连接 id 在最高字节编码了分片号:
(conn_id >> 56) % kShardCount 无需任何查找即可还原分片。这使得回调分发
为 O(1),也让多线程应用仅凭 id 就能路由工作。
哈希终结器为何必要:顺序分配的临时端口产生的键只在低位不同。不做雪崩
混合时,这些位在 % 8 下消失,几乎所有流都会落到分片 0。fmix64 终结器
把它们打散;tests/test_scale_shard_balance.cpp 断言顺序端口扰动下的分布
保持在界内。
4. 接收路径
应用回调 TcpConn 分片(按哈希) IP 层 XtcpStack NDI 后端 应用回调 TcpConn 分片(按哈希) IP 层 XtcpStack NDI 后端 #mermaid-svg-yfJ0sjnZWFwMNA16{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-yfJ0sjnZWFwMNA16 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yfJ0sjnZWFwMNA16 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yfJ0sjnZWFwMNA16 .error-icon{fill:#552222;}#mermaid-svg-yfJ0sjnZWFwMNA16 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yfJ0sjnZWFwMNA16 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yfJ0sjnZWFwMNA16 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yfJ0sjnZWFwMNA16 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yfJ0sjnZWFwMNA16 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yfJ0sjnZWFwMNA16 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yfJ0sjnZWFwMNA16 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yfJ0sjnZWFwMNA16 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yfJ0sjnZWFwMNA16 .marker.cross{stroke:#333333;}#mermaid-svg-yfJ0sjnZWFwMNA16 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yfJ0sjnZWFwMNA16 p{margin:0;}#mermaid-svg-yfJ0sjnZWFwMNA16 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-yfJ0sjnZWFwMNA16 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-yfJ0sjnZWFwMNA16 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-yfJ0sjnZWFwMNA16 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-yfJ0sjnZWFwMNA16 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-yfJ0sjnZWFwMNA16 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-yfJ0sjnZWFwMNA16 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-yfJ0sjnZWFwMNA16 .sequenceNumber{fill:white;}#mermaid-svg-yfJ0sjnZWFwMNA16 #sequencenumber{fill:#333;}#mermaid-svg-yfJ0sjnZWFwMNA16 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-yfJ0sjnZWFwMNA16 .messageText{fill:#333;stroke:none;}#mermaid-svg-yfJ0sjnZWFwMNA16 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-yfJ0sjnZWFwMNA16 .labelText,#mermaid-svg-yfJ0sjnZWFwMNA16 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-yfJ0sjnZWFwMNA16 .loopText,#mermaid-svg-yfJ0sjnZWFwMNA16 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-yfJ0sjnZWFwMNA16 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-yfJ0sjnZWFwMNA16 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-yfJ0sjnZWFwMNA16 .noteText,#mermaid-svg-yfJ0sjnZWFwMNA16 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-yfJ0sjnZWFwMNA16 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-yfJ0sjnZWFwMNA16 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-yfJ0sjnZWFwMNA16 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-yfJ0sjnZWFwMNA16 .actorPopupMenu{position:absolute;}#mermaid-svg-yfJ0sjnZWFwMNA16 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-yfJ0sjnZWFwMNA16 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-yfJ0sjnZWFwMNA16 .actor-man circle,#mermaid-svg-yfJ0sjnZWFwMNA16 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-yfJ0sjnZWFwMNA16 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} alt流存在无流 OnPacket(BufRef)解码链路/Ethertype,长度校验IPv4/IPv6 输入头部检查,必要时分片重组按四元组哈希分流查流表(单把分片锁)RFC 793 段处理:序号检查、PAWS、ACK 处理、乱序入队或按序交付RecvHandler(id, data, len)ACK / dupack 决策监听套接字匹配、SYN cookie 检查、或 RST 策略出向入队(见 §5)
由该结构直接得到的性质:
- 一个报文恰好触碰一把分片锁,一次。
- 乱序段缓存在接收配额内(每连接默认 64 KiB),按序交付;超限即丢弃,
由重传恢复,绝不无界增长。 - 校验和按需验证:
XTCP_CHECKSUM_VALIDATE=ON时启用 SIMD 加速
(x86 用 SSSE3/AVX2,ARM64 用 NEON,运行时探测);后端已保证完整性时
(manual 后端)跳过。
5. 发送路径
NDI 后端 qdisc(按监听器) TcpConn 应用线程 NDI 后端 qdisc(按监听器) TcpConn 应用线程 #mermaid-svg-xZYQxaeJTx9SQAPI{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-xZYQxaeJTx9SQAPI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xZYQxaeJTx9SQAPI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xZYQxaeJTx9SQAPI .error-icon{fill:#552222;}#mermaid-svg-xZYQxaeJTx9SQAPI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xZYQxaeJTx9SQAPI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xZYQxaeJTx9SQAPI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xZYQxaeJTx9SQAPI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xZYQxaeJTx9SQAPI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xZYQxaeJTx9SQAPI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xZYQxaeJTx9SQAPI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xZYQxaeJTx9SQAPI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xZYQxaeJTx9SQAPI .marker.cross{stroke:#333333;}#mermaid-svg-xZYQxaeJTx9SQAPI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xZYQxaeJTx9SQAPI p{margin:0;}#mermaid-svg-xZYQxaeJTx9SQAPI .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xZYQxaeJTx9SQAPI text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-xZYQxaeJTx9SQAPI .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-xZYQxaeJTx9SQAPI .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-xZYQxaeJTx9SQAPI .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-xZYQxaeJTx9SQAPI .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-xZYQxaeJTx9SQAPI #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-xZYQxaeJTx9SQAPI .sequenceNumber{fill:white;}#mermaid-svg-xZYQxaeJTx9SQAPI #sequencenumber{fill:#333;}#mermaid-svg-xZYQxaeJTx9SQAPI #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-xZYQxaeJTx9SQAPI .messageText{fill:#333;stroke:none;}#mermaid-svg-xZYQxaeJTx9SQAPI .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xZYQxaeJTx9SQAPI .labelText,#mermaid-svg-xZYQxaeJTx9SQAPI .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-xZYQxaeJTx9SQAPI .loopText,#mermaid-svg-xZYQxaeJTx9SQAPI .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-xZYQxaeJTx9SQAPI .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-xZYQxaeJTx9SQAPI .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-xZYQxaeJTx9SQAPI .noteText,#mermaid-svg-xZYQxaeJTx9SQAPI .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-xZYQxaeJTx9SQAPI .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xZYQxaeJTx9SQAPI .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xZYQxaeJTx9SQAPI .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-xZYQxaeJTx9SQAPI .actorPopupMenu{position:absolute;}#mermaid-svg-xZYQxaeJTx9SQAPI .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-xZYQxaeJTx9SQAPI .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-xZYQxaeJTx9SQAPI .actor-man circle,#mermaid-svg-xZYQxaeJTx9SQAPI line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-xZYQxaeJTx9SQAPI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} loop到期的 paced 报文 pacing 速率来自 CC;qdisc 按流强制执行 Send(id, data, len)按 MSS 分段(或 GSO 大段),拷入池化缓冲,追加重传队列enqueue(packet, flow_id)FQ 记账:每流队列、丢弃策略dequeue(now) ->> next_pacing 截止时间BufRef packetTx 下沉(后端写 TUN / 对端 Inject)
设计要点:
- 分段发生在入队之前,因此重传队列保存的正是需要重发的内容。GSO 风格的
大块发送按 MSS 边界切分;TSO 路径在后端可卸载时推迟切分。 - qdisc 属于监听器且可热切换:fq → cake 的切换立即作用于新流量,旧队列
自然排空而非丢弃存量流。 - 每流 pacing 速率由拥塞控制写入,由 qdisc 的
dequeue(now, next_pacing)契约强制执行;栈从不空转等待 pacing 截止。
6. 缓冲管理
所有载荷以 BufRef 句柄移动:指向池化 slab 的引用计数视图。拷贝只发生
在定义好的边界上(后端入口、用户 Send),内部阶段之间零拷贝。
#mermaid-svg-SGQwnG82nIujbpdl{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-SGQwnG82nIujbpdl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SGQwnG82nIujbpdl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SGQwnG82nIujbpdl .error-icon{fill:#552222;}#mermaid-svg-SGQwnG82nIujbpdl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SGQwnG82nIujbpdl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SGQwnG82nIujbpdl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SGQwnG82nIujbpdl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SGQwnG82nIujbpdl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SGQwnG82nIujbpdl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SGQwnG82nIujbpdl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SGQwnG82nIujbpdl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SGQwnG82nIujbpdl .marker.cross{stroke:#333333;}#mermaid-svg-SGQwnG82nIujbpdl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SGQwnG82nIujbpdl p{margin:0;}#mermaid-svg-SGQwnG82nIujbpdl defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-SGQwnG82nIujbpdl g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-SGQwnG82nIujbpdl g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-SGQwnG82nIujbpdl g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-SGQwnG82nIujbpdl g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-SGQwnG82nIujbpdl g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-SGQwnG82nIujbpdl .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-SGQwnG82nIujbpdl .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-SGQwnG82nIujbpdl .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-SGQwnG82nIujbpdl .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-SGQwnG82nIujbpdl .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-SGQwnG82nIujbpdl .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-SGQwnG82nIujbpdl .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-SGQwnG82nIujbpdl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SGQwnG82nIujbpdl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SGQwnG82nIujbpdl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SGQwnG82nIujbpdl .edgeLabel .label text{fill:#333;}#mermaid-svg-SGQwnG82nIujbpdl .label div .edgeLabel{color:#333;}#mermaid-svg-SGQwnG82nIujbpdl .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-SGQwnG82nIujbpdl .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-SGQwnG82nIujbpdl .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-SGQwnG82nIujbpdl .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-SGQwnG82nIujbpdl .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-SGQwnG82nIujbpdl .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SGQwnG82nIujbpdl .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SGQwnG82nIujbpdl #statediagram-barbEnd{fill:#333333;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SGQwnG82nIujbpdl .cluster-label,#mermaid-svg-SGQwnG82nIujbpdl .nodeLabel{color:#131300;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-SGQwnG82nIujbpdl .note-edge{stroke-dasharray:5;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-note text{fill:black;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram-note .nodeLabel{color:black;}#mermaid-svg-SGQwnG82nIujbpdl .statediagram .edgeLabel{color:red;}#mermaid-svg-SGQwnG82nIujbpdl #dependencyStart,#mermaid-svg-SGQwnG82nIujbpdl #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-SGQwnG82nIujbpdl .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SGQwnG82nIujbpdl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} slab 分配
BufRef Acquire(len)
Clone() 引用计数+1
释放一个引用
最后一次 Release()
归还分片池
ShutdownPools()
Pooled
Acquired
Cloned
Released
实现强制的规则:
- 每个分片从自己的池分配;跨分片交接传递句柄,缓冲可以比来源分片活得久,
但始终记在持有它的连接账上。 - 每连接配额限定内存:默认发送缓冲 64 KiB、乱序缓冲 64 KiB
(kDefaultSndBuf = 65536),即每条存活连接最坏约 129 KiB 加固定块开销。 - 池耗尽是硬信号:
Acquire返回空句柄,报文被丢弃。栈宁可丢包也不扩容,
这正是洪泛下内存上限依然成立的原因。
7. TCP 状态机
#mermaid-svg-7hS5HITqwml3a67U{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-7hS5HITqwml3a67U .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7hS5HITqwml3a67U .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7hS5HITqwml3a67U .error-icon{fill:#552222;}#mermaid-svg-7hS5HITqwml3a67U .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7hS5HITqwml3a67U .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7hS5HITqwml3a67U .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7hS5HITqwml3a67U .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7hS5HITqwml3a67U .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7hS5HITqwml3a67U .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7hS5HITqwml3a67U .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7hS5HITqwml3a67U .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7hS5HITqwml3a67U .marker.cross{stroke:#333333;}#mermaid-svg-7hS5HITqwml3a67U svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7hS5HITqwml3a67U p{margin:0;}#mermaid-svg-7hS5HITqwml3a67U defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-7hS5HITqwml3a67U g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-7hS5HITqwml3a67U g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-7hS5HITqwml3a67U g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-7hS5HITqwml3a67U g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-7hS5HITqwml3a67U g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-7hS5HITqwml3a67U .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-7hS5HITqwml3a67U .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-7hS5HITqwml3a67U .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-7hS5HITqwml3a67U .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-7hS5HITqwml3a67U .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-7hS5HITqwml3a67U .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-7hS5HITqwml3a67U .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-7hS5HITqwml3a67U .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7hS5HITqwml3a67U .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7hS5HITqwml3a67U .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7hS5HITqwml3a67U .edgeLabel .label text{fill:#333;}#mermaid-svg-7hS5HITqwml3a67U .label div .edgeLabel{color:#333;}#mermaid-svg-7hS5HITqwml3a67U .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-7hS5HITqwml3a67U .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-7hS5HITqwml3a67U .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-7hS5HITqwml3a67U .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-7hS5HITqwml3a67U .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-7hS5HITqwml3a67U .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7hS5HITqwml3a67U .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7hS5HITqwml3a67U #statediagram-barbEnd{fill:#333333;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7hS5HITqwml3a67U .cluster-label,#mermaid-svg-7hS5HITqwml3a67U .nodeLabel{color:#131300;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-7hS5HITqwml3a67U .note-edge{stroke-dasharray:5;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-note text{fill:black;}#mermaid-svg-7hS5HITqwml3a67U .statediagram-note .nodeLabel{color:black;}#mermaid-svg-7hS5HITqwml3a67U .statediagram .edgeLabel{color:red;}#mermaid-svg-7hS5HITqwml3a67U #dependencyStart,#mermaid-svg-7hS5HITqwml3a67U #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-7hS5HITqwml3a67U .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7hS5HITqwml3a67U :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Listen()
SYN -> SYN-ACK
ACK
洪泛时签发 SYN cookie
Connect()
SYN-ACK -> ACK
RST / 重试耗尽
主动 Close()(FIN)
FIN 的 ACK
收到 FIN
收到 FIN
FIN 的 ACK
2MSL 定时器
被动关闭(收到 FIN)
Close()(发出 FIN)
FIN 的 ACK
任一侧 RST
Listen
SynRcvd
Established
SynSent
Closed
FinWait1
FinWait2
Closing
TimeWait
CloseWait
LastAck
教科书状态机之外的健壮性:
- RFC 5961 对盲 RST/SYN 攻击回应 challenge ACK;窗口外的 RST 被应答而
不是被执行。 - SYN-RCVD 上捎带的数据被接受;客户端侧在
Established之前排队的数据
在握手完成后立即发出(完整客户端语义)。 - 序号回绕全程用串行算术处理;数据与 RST 边界的回绕均有专项测试。
8. 丢包恢复流水线
每个 ACK 之后按固定次序运行丢包判定:
#mermaid-svg-veAj2s5FqoLKCDOZ{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-veAj2s5FqoLKCDOZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-veAj2s5FqoLKCDOZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-veAj2s5FqoLKCDOZ .error-icon{fill:#552222;}#mermaid-svg-veAj2s5FqoLKCDOZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-veAj2s5FqoLKCDOZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-veAj2s5FqoLKCDOZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-veAj2s5FqoLKCDOZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-veAj2s5FqoLKCDOZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-veAj2s5FqoLKCDOZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-veAj2s5FqoLKCDOZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-veAj2s5FqoLKCDOZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-veAj2s5FqoLKCDOZ .marker.cross{stroke:#333333;}#mermaid-svg-veAj2s5FqoLKCDOZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-veAj2s5FqoLKCDOZ p{margin:0;}#mermaid-svg-veAj2s5FqoLKCDOZ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-veAj2s5FqoLKCDOZ .cluster-label text{fill:#333;}#mermaid-svg-veAj2s5FqoLKCDOZ .cluster-label span{color:#333;}#mermaid-svg-veAj2s5FqoLKCDOZ .cluster-label span p{background-color:transparent;}#mermaid-svg-veAj2s5FqoLKCDOZ .label text,#mermaid-svg-veAj2s5FqoLKCDOZ span{fill:#333;color:#333;}#mermaid-svg-veAj2s5FqoLKCDOZ .node rect,#mermaid-svg-veAj2s5FqoLKCDOZ .node circle,#mermaid-svg-veAj2s5FqoLKCDOZ .node ellipse,#mermaid-svg-veAj2s5FqoLKCDOZ .node polygon,#mermaid-svg-veAj2s5FqoLKCDOZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-veAj2s5FqoLKCDOZ .rough-node .label text,#mermaid-svg-veAj2s5FqoLKCDOZ .node .label text,#mermaid-svg-veAj2s5FqoLKCDOZ .image-shape .label,#mermaid-svg-veAj2s5FqoLKCDOZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-veAj2s5FqoLKCDOZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-veAj2s5FqoLKCDOZ .rough-node .label,#mermaid-svg-veAj2s5FqoLKCDOZ .node .label,#mermaid-svg-veAj2s5FqoLKCDOZ .image-shape .label,#mermaid-svg-veAj2s5FqoLKCDOZ .icon-shape .label{text-align:center;}#mermaid-svg-veAj2s5FqoLKCDOZ .node.clickable{cursor:pointer;}#mermaid-svg-veAj2s5FqoLKCDOZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-veAj2s5FqoLKCDOZ .arrowheadPath{fill:#333333;}#mermaid-svg-veAj2s5FqoLKCDOZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-veAj2s5FqoLKCDOZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-veAj2s5FqoLKCDOZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-veAj2s5FqoLKCDOZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-veAj2s5FqoLKCDOZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-veAj2s5FqoLKCDOZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-veAj2s5FqoLKCDOZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-veAj2s5FqoLKCDOZ .cluster text{fill:#333;}#mermaid-svg-veAj2s5FqoLKCDOZ .cluster span{color:#333;}#mermaid-svg-veAj2s5FqoLKCDOZ 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-veAj2s5FqoLKCDOZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-veAj2s5FqoLKCDOZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-veAj2s5FqoLKCDOZ .icon-shape,#mermaid-svg-veAj2s5FqoLKCDOZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-veAj2s5FqoLKCDOZ .icon-shape p,#mermaid-svg-veAj2s5FqoLKCDOZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-veAj2s5FqoLKCDOZ .icon-shape .label rect,#mermaid-svg-veAj2s5FqoLKCDOZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-veAj2s5FqoLKCDOZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-veAj2s5FqoLKCDOZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-veAj2s5FqoLKCDOZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
是
否
进入恢复
判定为伪重传
ACK 处理完成
重复 ACK?
计数 dupacks;
达 3 触发快速重传
(RFC 6582 形态)
RACK:最近一次重传
可证已丢失?(RFC 8985)
标记 >= lost seq 的段
处于恢复态?
TLP 探测到期?(RFC 8985)
2*SRTT 无 ACK
发送一个探测段
Early Retransmit
(RFC 5827):在途很少时
降低 dupthresh
PRR (RFC 6937):cwnd
朝 ssthresh 平滑升降
而非盲目减半
D-SACK undo (RFC 2883)
- Eifel (RFC 3522) 还原 cwnd
重传被标记的段,
从重传队列零拷贝克隆
重传队列存的是 BufRef 句柄,重传克隆引用而不拷贝字节。伪重传检测有两条
独立信号(D-SACK 反馈与 Eifel 时间戳检查),任一都可触发 cwnd 还原。
9. 拥塞控制插件
CC 算法通过与 Linux 内核 tcp_congestion_ops 同形的操作表接入,移植工作
直接从内核源码出发并保持其结构:
#mermaid-svg-6hwigxsaeHVYLKul{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-6hwigxsaeHVYLKul .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6hwigxsaeHVYLKul .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6hwigxsaeHVYLKul .error-icon{fill:#552222;}#mermaid-svg-6hwigxsaeHVYLKul .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6hwigxsaeHVYLKul .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6hwigxsaeHVYLKul .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6hwigxsaeHVYLKul .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6hwigxsaeHVYLKul .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6hwigxsaeHVYLKul .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6hwigxsaeHVYLKul .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6hwigxsaeHVYLKul .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6hwigxsaeHVYLKul .marker.cross{stroke:#333333;}#mermaid-svg-6hwigxsaeHVYLKul svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6hwigxsaeHVYLKul p{margin:0;}#mermaid-svg-6hwigxsaeHVYLKul g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-6hwigxsaeHVYLKul g.classGroup text .title{font-weight:bolder;}#mermaid-svg-6hwigxsaeHVYLKul .cluster-label text{fill:#333;}#mermaid-svg-6hwigxsaeHVYLKul .cluster-label span{color:#333;}#mermaid-svg-6hwigxsaeHVYLKul .cluster-label span p{background-color:transparent;}#mermaid-svg-6hwigxsaeHVYLKul .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6hwigxsaeHVYLKul .cluster text{fill:#333;}#mermaid-svg-6hwigxsaeHVYLKul .cluster span{color:#333;}#mermaid-svg-6hwigxsaeHVYLKul .nodeLabel,#mermaid-svg-6hwigxsaeHVYLKul .edgeLabel{color:#131300;}#mermaid-svg-6hwigxsaeHVYLKul .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-6hwigxsaeHVYLKul .label text{fill:#131300;}#mermaid-svg-6hwigxsaeHVYLKul .labelBkg{background:#ECECFF;}#mermaid-svg-6hwigxsaeHVYLKul .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-6hwigxsaeHVYLKul .classTitle{font-weight:bolder;}#mermaid-svg-6hwigxsaeHVYLKul .node rect,#mermaid-svg-6hwigxsaeHVYLKul .node circle,#mermaid-svg-6hwigxsaeHVYLKul .node ellipse,#mermaid-svg-6hwigxsaeHVYLKul .node polygon,#mermaid-svg-6hwigxsaeHVYLKul .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6hwigxsaeHVYLKul .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul g.clickable{cursor:pointer;}#mermaid-svg-6hwigxsaeHVYLKul g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-6hwigxsaeHVYLKul g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-6hwigxsaeHVYLKul .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-6hwigxsaeHVYLKul .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-6hwigxsaeHVYLKul .dashed-line{stroke-dasharray:3;}#mermaid-svg-6hwigxsaeHVYLKul .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-6hwigxsaeHVYLKul #compositionStart,#mermaid-svg-6hwigxsaeHVYLKul .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul #compositionEnd,#mermaid-svg-6hwigxsaeHVYLKul .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul #dependencyStart,#mermaid-svg-6hwigxsaeHVYLKul .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul #dependencyStart,#mermaid-svg-6hwigxsaeHVYLKul .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul #extensionStart,#mermaid-svg-6hwigxsaeHVYLKul .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul #extensionEnd,#mermaid-svg-6hwigxsaeHVYLKul .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul #aggregationStart,#mermaid-svg-6hwigxsaeHVYLKul .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul #aggregationEnd,#mermaid-svg-6hwigxsaeHVYLKul .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul #lollipopStart,#mermaid-svg-6hwigxsaeHVYLKul .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul #lollipopEnd,#mermaid-svg-6hwigxsaeHVYLKul .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6hwigxsaeHVYLKul .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-6hwigxsaeHVYLKul .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6hwigxsaeHVYLKul .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6hwigxsaeHVYLKul .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6hwigxsaeHVYLKul :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 默认
XtcpCongestionOps
+const char* name
+init(sk)
+release(sk)
+ssthresh(sk) : UInt32
+cong_avoid(sk, ack, acked)
+set_state(sk, new_state)
+cwnd_event(sk, ev)
+pkts_acked(sk, sample)
+undo_cwnd(sk) : UInt32
+cong_control(sk, rate_sample)
+reinit_ssthresh(sk) : UInt32
KCC
Reno
Cubic
BBRv1
注册显式且即时生效:RegisterCongestionControl(ops) 使算法可按名选用;
仍有连接使用时拒绝注销。选择按监听器生效,切换算法只影响新连接,不触碰
存量连接。RateSample 向 BBRv1 这类带宽时延积算法提供与内核相同的信息。
10. 队列规则插件
#mermaid-svg-2LiLRtN8v4YKU3pJ{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-2LiLRtN8v4YKU3pJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2LiLRtN8v4YKU3pJ .error-icon{fill:#552222;}#mermaid-svg-2LiLRtN8v4YKU3pJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2LiLRtN8v4YKU3pJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2LiLRtN8v4YKU3pJ .marker.cross{stroke:#333333;}#mermaid-svg-2LiLRtN8v4YKU3pJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2LiLRtN8v4YKU3pJ p{margin:0;}#mermaid-svg-2LiLRtN8v4YKU3pJ g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-2LiLRtN8v4YKU3pJ g.classGroup text .title{font-weight:bolder;}#mermaid-svg-2LiLRtN8v4YKU3pJ .cluster-label text{fill:#333;}#mermaid-svg-2LiLRtN8v4YKU3pJ .cluster-label span{color:#333;}#mermaid-svg-2LiLRtN8v4YKU3pJ .cluster-label span p{background-color:transparent;}#mermaid-svg-2LiLRtN8v4YKU3pJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2LiLRtN8v4YKU3pJ .cluster text{fill:#333;}#mermaid-svg-2LiLRtN8v4YKU3pJ .cluster span{color:#333;}#mermaid-svg-2LiLRtN8v4YKU3pJ .nodeLabel,#mermaid-svg-2LiLRtN8v4YKU3pJ .edgeLabel{color:#131300;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-2LiLRtN8v4YKU3pJ .label text{fill:#131300;}#mermaid-svg-2LiLRtN8v4YKU3pJ .labelBkg{background:#ECECFF;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-2LiLRtN8v4YKU3pJ .classTitle{font-weight:bolder;}#mermaid-svg-2LiLRtN8v4YKU3pJ .node rect,#mermaid-svg-2LiLRtN8v4YKU3pJ .node circle,#mermaid-svg-2LiLRtN8v4YKU3pJ .node ellipse,#mermaid-svg-2LiLRtN8v4YKU3pJ .node polygon,#mermaid-svg-2LiLRtN8v4YKU3pJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2LiLRtN8v4YKU3pJ .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ g.clickable{cursor:pointer;}#mermaid-svg-2LiLRtN8v4YKU3pJ g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-2LiLRtN8v4YKU3pJ g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-2LiLRtN8v4YKU3pJ .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-2LiLRtN8v4YKU3pJ .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-2LiLRtN8v4YKU3pJ .dashed-line{stroke-dasharray:3;}#mermaid-svg-2LiLRtN8v4YKU3pJ .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-2LiLRtN8v4YKU3pJ #compositionStart,#mermaid-svg-2LiLRtN8v4YKU3pJ .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ #compositionEnd,#mermaid-svg-2LiLRtN8v4YKU3pJ .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ #dependencyStart,#mermaid-svg-2LiLRtN8v4YKU3pJ .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ #dependencyStart,#mermaid-svg-2LiLRtN8v4YKU3pJ .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ #extensionStart,#mermaid-svg-2LiLRtN8v4YKU3pJ .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ #extensionEnd,#mermaid-svg-2LiLRtN8v4YKU3pJ .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ #aggregationStart,#mermaid-svg-2LiLRtN8v4YKU3pJ .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ #aggregationEnd,#mermaid-svg-2LiLRtN8v4YKU3pJ .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ #lollipopStart,#mermaid-svg-2LiLRtN8v4YKU3pJ .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ #lollipopEnd,#mermaid-svg-2LiLRtN8v4YKU3pJ .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2LiLRtN8v4YKU3pJ .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-2LiLRtN8v4YKU3pJ .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2LiLRtN8v4YKU3pJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2LiLRtN8v4YKU3pJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2LiLRtN8v4YKU3pJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} XtcpQdiscOps
+const char* name
+init(q, params) : int
+destroy(q)
+enqueue(q, flow_id, packet) : int
+dequeue(q, now, next_pacing) : BufRef
+has_backlog(q) : bool
+change(q, params) : int
+reset(q)
+set_pacing_rate(q, flow_id, bps) : int
+get_pacing_rate(q, flow_id) : UInt64
+remove_flow(q, flow_id) : int
FQ
FqCodel
Cake
TBF
dequeue(now, next_pacing) 契约是集成的核心:qdisc 可以在 pacing 时间未到
时拒交报文,并报告下次可发时刻。栈视该截止时间为权威并据此安排下一次
轮询。remove_flow 让关闭中的连接确定性地回收排队段(返回的被丢弃段数
进入 tx 记账),这使关闭期清理精确而非泄漏。
11. mimt 通道
mimt("multiplexed in-memory transport",进程内多路传输)在同一进程的
组件间暴露类 TCP 流,不合成报文:读写直接在流对象之间移动缓冲。
读线程 MimtFlow(读侧) MimtFlow(写侧) 写线程 读线程 MimtFlow(读侧) MimtFlow(写侧) 写线程 #mermaid-svg-HZG8EKRv0bOA0V0u{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-HZG8EKRv0bOA0V0u .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HZG8EKRv0bOA0V0u .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HZG8EKRv0bOA0V0u .error-icon{fill:#552222;}#mermaid-svg-HZG8EKRv0bOA0V0u .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HZG8EKRv0bOA0V0u .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HZG8EKRv0bOA0V0u .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HZG8EKRv0bOA0V0u .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HZG8EKRv0bOA0V0u .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HZG8EKRv0bOA0V0u .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HZG8EKRv0bOA0V0u .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HZG8EKRv0bOA0V0u .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HZG8EKRv0bOA0V0u .marker.cross{stroke:#333333;}#mermaid-svg-HZG8EKRv0bOA0V0u svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HZG8EKRv0bOA0V0u p{margin:0;}#mermaid-svg-HZG8EKRv0bOA0V0u .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HZG8EKRv0bOA0V0u text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-HZG8EKRv0bOA0V0u .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-HZG8EKRv0bOA0V0u .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-HZG8EKRv0bOA0V0u .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-HZG8EKRv0bOA0V0u .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-HZG8EKRv0bOA0V0u #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-HZG8EKRv0bOA0V0u .sequenceNumber{fill:white;}#mermaid-svg-HZG8EKRv0bOA0V0u #sequencenumber{fill:#333;}#mermaid-svg-HZG8EKRv0bOA0V0u #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-HZG8EKRv0bOA0V0u .messageText{fill:#333;stroke:none;}#mermaid-svg-HZG8EKRv0bOA0V0u .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HZG8EKRv0bOA0V0u .labelText,#mermaid-svg-HZG8EKRv0bOA0V0u .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-HZG8EKRv0bOA0V0u .loopText,#mermaid-svg-HZG8EKRv0bOA0V0u .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-HZG8EKRv0bOA0V0u .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-HZG8EKRv0bOA0V0u .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-HZG8EKRv0bOA0V0u .noteText,#mermaid-svg-HZG8EKRv0bOA0V0u .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-HZG8EKRv0bOA0V0u .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HZG8EKRv0bOA0V0u .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HZG8EKRv0bOA0V0u .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HZG8EKRv0bOA0V0u .actorPopupMenu{position:absolute;}#mermaid-svg-HZG8EKRv0bOA0V0u .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-HZG8EKRv0bOA0V0u .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HZG8EKRv0bOA0V0u .actor-man circle,#mermaid-svg-HZG8EKRv0bOA0V0u line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-HZG8EKRv0bOA0V0u :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} fill-to-want 语义:连续排空 chunk 直到want 字节或队列空;只有队列空才允许短读 Write(buf, len)chunk 移入 rx 队列AsyncRead 完成Read 返回 n < want重新挂起;下一次 Write 将其完成Close()EOF 在排队字节之后传播挂起的读以 0 完成(EOF)
fill-to-want 规则的存在理由:部分完成若消费掉挂起的读,会让等待全长后才
重新挂起的调用方死锁(这是差分 ARM 测试发现的真实死锁;见 TESTING.md)。
一个被接受的读恰好对应一次完成。
12. 加锁规则
锁共三类。以下获取次序是全局的,代码中不存在其他次序。
#mermaid-svg-cW2gE3drf3O5uvmJ{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-cW2gE3drf3O5uvmJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cW2gE3drf3O5uvmJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cW2gE3drf3O5uvmJ .error-icon{fill:#552222;}#mermaid-svg-cW2gE3drf3O5uvmJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cW2gE3drf3O5uvmJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cW2gE3drf3O5uvmJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cW2gE3drf3O5uvmJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cW2gE3drf3O5uvmJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cW2gE3drf3O5uvmJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cW2gE3drf3O5uvmJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cW2gE3drf3O5uvmJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cW2gE3drf3O5uvmJ .marker.cross{stroke:#333333;}#mermaid-svg-cW2gE3drf3O5uvmJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cW2gE3drf3O5uvmJ p{margin:0;}#mermaid-svg-cW2gE3drf3O5uvmJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cW2gE3drf3O5uvmJ .cluster-label text{fill:#333;}#mermaid-svg-cW2gE3drf3O5uvmJ .cluster-label span{color:#333;}#mermaid-svg-cW2gE3drf3O5uvmJ .cluster-label span p{background-color:transparent;}#mermaid-svg-cW2gE3drf3O5uvmJ .label text,#mermaid-svg-cW2gE3drf3O5uvmJ span{fill:#333;color:#333;}#mermaid-svg-cW2gE3drf3O5uvmJ .node rect,#mermaid-svg-cW2gE3drf3O5uvmJ .node circle,#mermaid-svg-cW2gE3drf3O5uvmJ .node ellipse,#mermaid-svg-cW2gE3drf3O5uvmJ .node polygon,#mermaid-svg-cW2gE3drf3O5uvmJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cW2gE3drf3O5uvmJ .rough-node .label text,#mermaid-svg-cW2gE3drf3O5uvmJ .node .label text,#mermaid-svg-cW2gE3drf3O5uvmJ .image-shape .label,#mermaid-svg-cW2gE3drf3O5uvmJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-cW2gE3drf3O5uvmJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cW2gE3drf3O5uvmJ .rough-node .label,#mermaid-svg-cW2gE3drf3O5uvmJ .node .label,#mermaid-svg-cW2gE3drf3O5uvmJ .image-shape .label,#mermaid-svg-cW2gE3drf3O5uvmJ .icon-shape .label{text-align:center;}#mermaid-svg-cW2gE3drf3O5uvmJ .node.clickable{cursor:pointer;}#mermaid-svg-cW2gE3drf3O5uvmJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cW2gE3drf3O5uvmJ .arrowheadPath{fill:#333333;}#mermaid-svg-cW2gE3drf3O5uvmJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cW2gE3drf3O5uvmJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cW2gE3drf3O5uvmJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cW2gE3drf3O5uvmJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cW2gE3drf3O5uvmJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cW2gE3drf3O5uvmJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cW2gE3drf3O5uvmJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cW2gE3drf3O5uvmJ .cluster text{fill:#333;}#mermaid-svg-cW2gE3drf3O5uvmJ .cluster span{color:#333;}#mermaid-svg-cW2gE3drf3O5uvmJ 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-cW2gE3drf3O5uvmJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cW2gE3drf3O5uvmJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-cW2gE3drf3O5uvmJ .icon-shape,#mermaid-svg-cW2gE3drf3O5uvmJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cW2gE3drf3O5uvmJ .icon-shape p,#mermaid-svg-cW2gE3drf3O5uvmJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cW2gE3drf3O5uvmJ .icon-shape .label rect,#mermaid-svg-cW2gE3drf3O5uvmJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cW2gE3drf3O5uvmJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cW2gE3drf3O5uvmJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cW2gE3drf3O5uvmJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 分片锁
async_mutex
(仅异步 API 使用)
flow sync_
(每连接)
- 分片锁:保护流表与分片级记账。持有区间短且有界。
- flow
sync_:保护单连接可变状态。在分片锁之后获取,绝不在其前。 async_mutex:串行化异步 API 的完成投递。在分片锁之后获取,绝不
在其前。
无死锁论证:上图无环,且 src/ 中所有多锁路径都按所列次序获取(已审计;
并发路径的压力测试见 TESTING.md)。回调在所有锁之外运行:handler 被调用
时分片锁已释放,因此用户代码回调进栈不会死锁。
13. 设计决策及其代价
| 决策 | 收益 | 代价 |
|---|---|---|
| 固定 8 分片,创建时定位 | 无迁移竞争;凭 id O(1) 分发 | 哈希偏斜即负载偏斜;用雪崩哈希缓解,测试断言 |
| 每分片单锁 | 推理简单,数据面无锁序问题 | 同一分片多线程时争用;RX 扩展数字中可见 |
全程零拷贝 BufRef |
重传与跨分片交接免拷贝 | 需要句柄纪律;池耗尽意味着丢弃而非增长 |
| 内核同形插件表 | 移植贴近参考源码 | 接口略宽于严格所需 |
| 虚拟时钟确定性测试 | CI 可复现;时序 bug 只可能藏在实时路径 | 实时行为需另行测量(PERFORMANCE.md) |
| 过载时丢弃而非增长 | 每连接内存硬上限 | 极端过载下吞吐退化而非延迟退化 |
14. 有意缺席的部分
- 尚无 DPDK/EFVI 后端:接口预留,实现未写。现有后端为 manual(进程内)、
TUN、TAP。 - 无 UDP、无 socket-fd 仿真、无 POSIX 兼容层。
TCP_CORK可解析接受但 v1 中不改变任何行为。- 流的分片间热迁移已有设计(GOALS.md),尚未接入生产路径。