2.12 组会
1. 研究问题与设计目标
1.1 研究问题
Tor 的 stream-level 流控里,client 会基于“自身接收侧排队/排空能力”给对端一个速率信号(XON/XOFF)。
但原始实现中,XON 的 kbps_ewma 来自 client 的测量值(ewma_drain_rate),实验者很难在不破坏协议语义的情况下构造“可控”的速率建议序列。
因此我们的问题是:
1.2 设计目标
- 可控:支持固定速率、上限、比例缩放、方波(high/low)、强制 XOFF
- 热更新:无需重启,通过配置文件更新控制参数
- 低侵入:修改集中在 client 的 flow control 发送路径
- 可复现:现象稳定,对应清晰的触发条件
2. 背景机制:Tor 的 stream-level 流控
2.1 stream-level(而不是circuit-level)
Tor 的数据传输最终落在 TCP socket 上。对应用而言,关键瓶颈是 client 侧 socket 写出能力与缓冲排队。
- outbuf 堆积:表示应用侧写不动,或网络回压导致排队
- outbuf 排空:表示 client 能把数据持续写入 socket
因此在 stream 层做反馈,有两个直接优点:
- 反馈与“真实接收能力”绑定(排队/排空)
- 相对来说约束比较Hard,可能没办法调很高但是一定可以很低
2.2 XOFF 与 XON 的语义
- XOFF:硬回压信号。接收方明确表示“现在别再推数据了”。
- XON(kbps_ewma):软速率建议。接收方告诉发送方“我能稳定排空的速率大约是 X kbps”。
2.3 为什么 Exit 收到 XON 会对应调整速率(机制解释)
在发送端(exit 方向),“发送速率”受两类因素共同约束:
- 流控窗口/在途量(inflight)约束(Circuit 级别):发送端通常不会无限制地把数据推入网络,会受控于某种 inflight 上限或 pacing 预算。
- 接收端反馈(XON/XOFF)(Stream 级别):XOFF 会直接抑制发送;XON 提供一个速率目标,使发送端把 pacing 目标向该速率收敛。
直观类比:
- XOFF 类似“红灯”,直接停。
- XON(kbps) 类似“限速牌”,告诉你目标速度是多少。
因此,当 exit 收到新的 XON 建议值时:
- 其 pacing 目标会更新
- bucket/预算的补充速率会随之变化
- 最终表现为:
实际吞吐随 advertised_kbps(你广播的 kbps_ewma)发生可观测的响应。
3. 实现:用“advertised_kbps”替换“纯测量 kbps”
3.1 Block A:头部与实验标记(L33–L38)
引入头文件:
1 |
3.2 Block B:Client-only FlowCtl knobs(L54–L273)
这是本次工作的“控制面”。核心贡献是:
- 配置系统:从文件读取 mode 与参数
- 热更新:mtime 检测 + reload
- 模式集合:off/fixed/cap/scale/square/xoff
- 速率计算函数:
flowctl_compute_advertised_kbps(measured)
1 | /* ===================== Client-only FlowCtl knobs ===================== */ |
3.3 Block C:XON 发送路径改写(L448–L470)
这一块是“数据面”入口:在 circuit_send_stream_xon()(或等价函数)里做三件事:
- 发送前 reload:保证配置热更新能即时生效
- AP(client) 限定:只对 client 侧生效,避免影响 relay/exit
- payload 改写:把
xon_cell_set_kbps_ewma()的输入由 measured 改为 advertised
没有改变 XON 作为反馈信号的协议语义,只是把反馈值从“纯测量”替换为“实验可控的 advertised_kbps”。
1 | /* reload knobs (cheap: mtime check) */ |
3.4 Block D:last_sent 语义统一(L485–L488)
你把 stream->ewma_rate_last_sent 的语义改成:
- 记录 上一次发送的 advertised_kbps
1 | stream->ewma_rate_last_sent = advertised_kbps; |
3.5 Block E:xoff / 日志 / epoch 等增强(L497–L507)
- mode=xoff 时直接发送 XOFF
- 额外日志(measured vs advertised)
- epoch 记录(标记本次发送对应哪一版配置)
1 | stream->flowctl_epoch_last_sent = flowctl_epoch; |
3.6 Block F:rate-change 判定逻辑支持方波(L823–L850)
- 对 client 且 mode!=off:
- 计算
adv_now - square 模式:只要
adv_now != last_sent就触发 - 其他模式:用 change_pct 比较
adv_now与last_sent
- 计算
1 | /* Client-only: if knobs changed, force an advisory update quickly. */ |
4. 实验现象
下载时按照预期方波随周期从100k波动到3000k下一点。
电路切换现象
两条电路 connection-level
复现错误找原因