SACK 是什么
SACK 让接收端在确认包里附带「我已经收到哪些不连续的块」,发送端据此只重传真正缺失的部分,避免把已经到达的数据再发一遍。它在握手阶段通过 SACK Permitted 选项协商启用,抓包时看确认报文里的 SACK 块数量与推进情况,就能判断丢包恢复的效率。
基本信息
| 标准依据 | RFC 2018 定义,RFC 6675 给出重传算法 |
|---|---|
| 协商方式 | 握手中交换 SACK Permitted 选项 |
| 抓包字段 | tcp.options.sack_le 与 sack_re(Wireshark 解析) |
| 核心作用 | 只重传缺失块,减少无谓重传 |
| 配合字段 | tcp.analysis.duplicate_ack 与重传标注 |
典型使用场景
- 高丢包链路上评估恢复效率:缺口是否被快速补上
- 区分重复确认是乱序还是丢包:有 SACK 推进多为乱序
- 核对中间设备是否篡改或丢弃了握手选项
- 评估一次丢包对吞吐的实际影响
- 对比启用与未启用选择性确认时的恢复速度
常用过滤
常用过滤
tcp.options.sack # 带有 SACK 块的确认
tcp.options.sack_permitted && tcp.flags.syn == 1 # 握手协商情况
tcp.stream == N && tcp.options.sack # 指定会话的 SACK
tcp.options.sack && tcp.analysis.duplicate_ack # 重复确认中的 SACK观察项与含义
| 观察项 | 含义 | 说明 |
|---|---|---|
| 握手含 SACK Permitted | 双方支持选择性确认 | 未协商则退化为逐段确认 |
| 确认携带 SACK 块 | 接收端已收到的不连续块 | 据此判断缺口位置 |
| SACK 块逐步推进 | 恢复正在进行 | 缺口在被填上 |
| SACK 块长时间不变 | 恢复受阻 | 检查丢包是否持续 |
SACK 描述的是接收缓冲中的不连续区域,解读时要与序列号一起看,不能只数块的数量。
中间设备丢弃或改写选项会破坏协商,怀疑时直接核对握手报文的选项列表。
补充要点
- 把 SACK 与重复确认结合看,能判断接收端是缺一段还是收到乱序
- 缺口长时间不被补齐时,问题可能在发送端的重传策略而不在接收端
- 选择性确认不改变丢包发生的事实,只影响恢复速度
- 长距离高丢包链路上,恢复速度对业务体验的影响往往比丢包率本身更大
统计 SACK 相关的恢复耗时可以用相邻两块推进之间的时间差近似,方法简单但需要人工核对。