对 Linux TCP 特性表明一个否定态度并非大不敬,而是这玩意儿没鸟用。

还是 TCP Timestamps 的精度问题,本文仅针对 Linux TCP,不针对别的实现,看一下为什么它没鸟用。

源码分析,看我添加的注释:

static bool tcp_ack_update_rtt(struct sock *sk, const int flag,long seq_rtt_us, long sack_rtt_us,long ca_rtt_us, struct rate_sample *rs)
{const struct tcp_sock *tp = tcp_sk(sk);/* Prefer RTT measured from ACK's timing to TS-ECR. This is because* broken middle-boxes or peers may corrupt TS-ECR fields. But* Karn's algorithm forbids taking RTT if some retransmitted data* is acked (RFC6298).*/// 不要优先选择时间戳计算 RTT,但这里是另一个理由。if (seq_rtt_us < 0)seq_rtt_us = sack_rtt_us;/* RTTM Rule: A TSecr value received in a segment is used to* update the averaged RTT measurement only if the segment* acknowledges some new data, i.e., only if it advances the* left edge of the send window.* See draft-ietf-tcplw-high-performance-00, section 3.3.*/// 到此为止,看看 seq_rtt_us,ca_rtt_us 的单位,us,这是微秒,1000 us = 1 msif (seq_rtt_us < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&flag & FLAG_ACKED) {u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;// TCP 时间戳单位是 ms,这里 delta 是两个 ms 相见,只有 ms 精度。if (likely(delta < INT_MAX / (USEC_PER_SEC / TCP_TS_HZ))) {if (!delta)delta = 1;// seq_rtt_us 的最小值是 1000,这里就是问题所在。// 曾经,没有 delta = max(delta, 1),那时 delta 最小值就是 0。seq_rtt_us = delta * (USEC_PER_SEC / TCP_TS_HZ);ca_rtt_us = seq_rtt_us;}}rs->rtt_us = ca_rtt_us; /* RTT of last (S)ACKed packet (or -1) */if (seq_rtt_us < 0)return false;/* ca_rtt_us >= 0 is counting on the invariant that ca_rtt_us is* always taken together with ACK, SACK, or TS-opts. Any negative* values will be skipped with the seq_rtt_us < 0 check above.*/tcp_update_rtt_min(sk, ca_rtt_us, flag);tcp_rtt_estimator(sk, seq_rtt_us);tcp_set_rto(sk);/* RFC6298: only reset backoff on valid RTT measurement. */inet_csk(sk)->icsk_backoff = 0;return true;
}

发生重传且没有序列被 SACKed ,若开启 Timestamps,Linux TCP 使用 tsecr 和当前 ms 的差计算 RTT,这在 ms 精度时代是个优化,但在 us 精度时代就是累赘。

上述代码来自 5.10 内核,检测到乱序或丢包时,灌入 tcp_update_rtt_min 和 tcp_rtt_estimator 的 RTT 参数最小值为 1000,这对于 IDC 网络而言实在太大了,在 50 us 级 RTT 的连接中,1000 us 就是个噪点,它会拉偏 RTT 的移动指数平均值,进而拉偏 RTO。

检测到乱序或丢包,对端立即回复 ACK,此时实际 RTT 足够小到排除掉对端任何 Delay,若丢包属于随机丢包而非拥塞,该 RTT 有希望更新 rtt_min,但为了避免精度损失导致 delta == 0 异常,增加 delta = max(delta, 1) 约束,从而将足够大的值注入计算,反而帮了倒忙。

可若不增加 delta = max(delta, 1) 约束,又会遇到 0 这个极小异常点,怎么都不行。

看下面的脚本:

#!/usr/local/bin/stapglobal dsrttprobe kernel.function("tcp_ack_update_rtt")
{srtt = (@cast($sk,"struct tcp_sock")->srtt_us);dport =(@cast($sk, "struct sock")->__sk_common->skc_dport);if (dport == 0x8913) { // 过滤 iperf 端口dsrtt <<< srtt}
}probe timer.s(2) {printf("-----------\n")print(@hist_log(dsrtt))delete dsrtt
}

分别设置 net.ipv4.tcp_timestamps 为 1 或 0,观察一下分布,可呈现:

如果将 sack 也关闭,GBN 将持续使用 Timestamps 计算 RTT,结果就是持续值为 1000 us 的采样值被灌入移指平均计算。关掉 sack ,持续采样,不再 delete,分布如下:

所以,在 IDC 环境,请关闭 Timestamps。

在公网环境,这个问题不大,广域网 RTT 大于 1 ms,时间戳损失的精度有限,2.9 - 1.1 约等于 2,按 ms 精度计算,结果是 1,大约损失一半,这是损失的最大误差,在普遍 RTT 均大于 10 ms 的环境,偶尔的计算精度损失不会带来问题。

然而,对于 BBR ,即便精度损失不会带来计算问题,也还是会影响 BBR 的状态机。问题出在下面代码:

static void bbr_update_min_rtt(struct sock *sk, const struct rate_sample *rs)
{struct tcp_sock *tp = tcp_sk(sk);struct bbr *bbr = inet_csk_ca(sk);bool filter_expired;/* Track min RTT seen in the min_rtt_win_sec filter window: */filter_expired = after(tcp_jiffies32,bbr->min_rtt_stamp + bbr_min_rtt_win_sec * HZ);if (rs->rtt_us >= 0 &&(rs->rtt_us <= bbr->min_rtt_us ||(filter_expired && !rs->is_ack_delayed))) {bbr->min_rtt_us = rs->rtt_us;bbr->min_rtt_stamp = tcp_jiffies32;}
...

在 Recovery 状态用时间戳计算 RTT,精度损失将使 rs->rtt_us <= bbr->min_rtt_us 恒成立,进而持续 reset min_rtt_stamp,也就进不去 ProbeRTT 状态了。该问题已解决,去掉等号即可:
[PATCH net] tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
无论如何,Timestamps 总是在帮倒忙。

如果 Timestamps 没鸟用,还留着它空消耗选项空间有何用?

  • 要么改了它,像我一样改成 us 精度。
  • 要么学 Google:draft-yang-tcpm-ets-00
  • 要么关了它。

周末测的那版 BBR 发现一个问题,最近我总吐槽的 TCP Timestamps 精度问题还真的出了问题,换成我修改的那个 us 精度 Timestamps 后问题解决,我发现在 100 us 量级 RTT 的链路上问题更严重。梳理了之后,这是两个问题,三言两语试图说清楚。

浙江温州皮鞋湿,下雨进水不会胖。

Linux TCP Timestamps 没鸟用相关推荐

  1. 彻底实现Linux TCP的Pacing发送逻辑-高精度hrtimer版

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 代码的实 ...

  2. c语言linux TCP长连接 socket收发范例 断开自动重连

    原文链接:https://blog.csdn.net/chenhao0568/article/details/103420615 c语言linux TCP长连接 socket收发范例 断开自动重连 改 ...

  3. 晚上鸟沒事,白天没鸟事_鸟箱

    晚上鸟沒事,白天没鸟事 This is a sequel to my previous post about image classification using the NABirds data s ...

  4. Linux TCP Finwait2/Timewait状态要义浅析

    我讨厌TCP.但是我的工作中总是要接触TCP! 近期三四个礼拜,接连碰到三三两两TCP的问题,这些都无关拥塞控制,这些都是状态机方面的问题,但无论怎样,我是非常讨厌的,以至于恶心,我释放大量的感情色彩 ...

  5. 彻底实现Linux TCP的Pacing发送逻辑-普通timer版

    又到了周末,过年前的倒数第2个周末,工作和生活上的压力早已卸载,自己也就有必要写点自己觉得感兴趣或者不公道的事情了.即便如此,白天我并不自由,不管是工作日还是周末,我必须在公司或者家里做一些例行的事情 ...

  6. Linux TCP 单机优化

    TCP 的 send 函数 tcp_sendmsg/tcp_sendpage,要调用 lock_sock(sk). TCP 的 recv 函数 tcp_recvmsg,也要调用 lock_sock(s ...

  7. linux 协议栈之socket,Linux TCP/IP 协议栈之 Socket 的实现分析(一)

    内核版本:2.6.37 参考[作者:kendo的文章(基于内涵版本2.6.12)] 第一部份 Socket套接字的创建 socket 并不是 TCP/IP协议的一部份. 从广义上来讲,socket 是 ...

  8. Linux TCP并不是全双工的

    我说过好几次Linux TCP不是全双工的,没人信,也可能不知道我在说什么,总是有人拿TCP规范来怼我,说TCP就是全双工的,两边可以同时发送数据,显然没get到我的点. Linux TCP半双工体现 ...

  9. Linux TCP 连接数修改

    Linux TCP 连接数修改 一. 文件数限制修改 (1) vi /etc/security/limits.conf * soft nofile 10240 * hard nofile 10240 ...

  10. linux tcp keepalive,[20170504]Linux TCP keepalive timers.txt

    [20170504]Linux TCP keepalive timers.txt --//上午仔细看一些文档,发现实际上netstat命令就有输出,参数--timer或者-o参数. # netstat ...

最新文章

  1. MyBatis源码:原来 resultMap 解析完是这样
  2. php的防csrf攻击,zblog php添加Token防止CSRF攻击
  3. [小技巧] ArrayList与LinkedList对比与常见方法
  4. python特征工程意义_python数据挖掘--特征工程篇(附代码)
  5. 看unix高级编程时遇到apue.h找不到的问题
  6. 小技巧:Windows快捷键快速打开程序
  7. 新手背代码被说“笨”?文科程序员教你如何记代码,妈妈再也不用担心我的头发!
  8. 机器学习基石第十三讲笔记
  9. Tinder 和 Potluck 的卡片风格实现
  10. 注意力机制attention和Transformer
  11. 获取高德地图位置的经纬度
  12. C语言——单词精确查找
  13. python cox模型_Cox模型的基本概念_Python数据分析系列视频课程--玩转统计模型_数据挖掘与分析视频-51CTO学院...
  14. java 实现扑克牌洗牌功能
  15. 轻量级过程改进之项目计划
  16. c语言 文件加密与解密
  17. 如何查看mysql技术文档_数据库
  18. 基于wowchemy和hugo搭建个人网站
  19. mac执行java死卡_MacOS应用程序有时卡死,怎么办?2种方法轻松搞定
  20. See Finer, See More!腾讯上交提出IVT,越看越精细,进行精细全面的跨模态对比!

热门文章

  1. idea git操作
  2. 游戏公司的区块链冒险:一周时间从火爆到熄火
  3. 微信公众号开发模式没有域名怎么办?申请免费域名
  4. 西工大机考(社会学概论)大作业网考
  5. Python min()函数
  6. Photoshop CC 2018快捷键大全!
  7. mysql pdo_数据库PDO简介
  8. 把Android源码导入Android Studio进行调试
  9. 启动报错:读取 jar时出错; error in opening zip file
  10. SpringBoot优缺点分析