Debug 记:Linux 升级内核到4.10.1 导致访问路由器WEB管理界面超级卡顿问题的解决 » 荒野无灯weblog

Keep It Simple, Stupid.

荒野无灯weblog

Debug 记:Linux 升级内核到4.10.1 导致访问路由器WEB管理界面超级卡顿问题的解决

相关图片有空补上。

环境: ArchLinux 最新版 ,linux kernel v4.10.1, 有线连接Padavan系统的路由器TOTOLINK A3004NS

▶ uname -a
Linux arch_huangye 4.10.1-1-ARCH #1 SMP PREEMPT Sun Feb 19 13:45:52 UTC 2017 x86_64 GNU/Linux
[A3004NS /etc/storage]# uname -a
Linux A3004NS 3.4.113 #1 SMP Sun Mar 12 14:32:40 CST 2017 mips GNU/Linux

问题产生之前所做的操作:升级 linux kernel到了 v4.10.1 , 并且给路由器刷了刚编译好的固件。 遇到的问题: 访问路由器WEB管理界面超级卡顿,能连接ssh且操作流畅,就是打开WEB管理的网页 超级卡顿,甚至有时候半天打不开一个页面。平常正常的时候都是秒开的。

升级完之后其实我并没有马上想到是电脑操作系统的问题。 由于这个padavan固件是我修改并编译的,因此我一开始以为是我调整了某个内核参数,导致它工作 不正常了。

想办法排除路由器的问题

尝试一: 为了排除固件问题,刷回旧版本的固件, 结果:故障问题依旧。说明不是固件的问题。 尝试二:为了排除路由器硬件可能的损坏问题,用同一台电脑同一根网络接上另一台路由器,PHICOMM K2, 这台路由器同样是刷了我改版的padavan系统。结果故障问题和A3004NS的一样。

经过以上的测试,已经基本上排除了是路由器的问题了。那么很容易想到是我升级了Linux内核导致的问题。 于是降级内核:

cd /var/cache/pacman/pkg
sudo pacman -U nvidia-378.13-2-x86_64.pkg.tar.xz linux-4.9.11-1-x86_64.pkg.tar.xz

然后重启电脑,发现问题消失了。证明猜测是对的。

继续探索问题产生的原因

目前为止只知道是从 4.9.11 的内核升级到 4.10.1 时产生了这个问题。那么为什么?

于是打开wireshark 开始抓包分析,结果发现在电脑与路由器开始进行http协议通信之前,tcp协议那里出了点问题。 主要表现是tcp retransmission 非常多。看来这是导致非常卡顿甚至打不开的原因了。

那么,是什么导致了这个tcp retransmission ?是不是新版本内核某项新增加的功能导致了这个问题? 或许我们应该去查看一下4.10.1 的kernel changelog 了。

我于是Google到了这个页面:https://kernelnewbies.org/LinuxChanges 通过搜索tcp关键字,很快定位到了有如下关键信息

Linux 4.10 was released on 19 Feb 2017. TCP: sender chronographs instrumentation. This feature exports the sender chronograph stats via the socket SO_TIMESTAMPING channel. Currently it can instrument how long a particular application unit of data was queued in TCP by tracking SOF_TIMESTAMPING_TX_SOFTWARE and SOF_TIMESTAMPING_TX_SCHED. Having these sender chronograph stats exported simultaneously along with these timestamps allow further breaking down the various sender limitation. For example, a video server can tell if a particular chunk of video on a connection takes a long time to deliver because TCP was experiencing small receive window commit, commit, commit, commit, commit, commit

TCP: randomize TCP timestamp offsets for each connection. It changes the meaning of the tcp_timestamps sysctl commit, commit

然后经过查看这几个commit,最终定位到了一个非常有嫌疑的commit:

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 5af48dd..5ca567f 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -610,8 +610,13 @@ tcp_syn_retries - INTEGER
    with the current initial RTO of 1second. With this the final timeout
    for an active TCP connection attempt will happen after 127seconds.

-tcp_timestamps - BOOLEAN
-   Enable timestamps as defined in RFC1323.
+tcp_timestamps - INTEGER
+Enable timestamps as defined in RFC1323.
+   0: Disabled.
+   1: Enable timestamps as defined in RFC1323 and use random offset for
+   each connection rather than only using the current time.
+   2: Like 1, but without random offsets.
+   Default: 1

 tcp_min_tso_segs - INTEGER
    Minimal number of segments per TSO frame.

从这里可以看出,tcp_timestamps 的意义被新代码改变了。原来的默认值1是启用timestamps但是没有random offset. 而新代码导致原来的值 1 的意义变成了Enable timestamps as defined in RFC1323 and use random offset,比较搞笑的时, 原来的1的值,现在变成了要设置成2了。

查看一下结果:

[root@hacklog ipv4]# cat tcp_timestamps
1

果然是1, 试试把它的值变成4.9.11内核的行为:

echo 2 > /proc/sys/net/ipv4/tcp_timestamps

然后再测试一下路由器的WEB UI页面,OK, good, 秒开。 问题原因找到。可以把这个值设定为默认了:

在 /etc/sysctl.d 下面新建一文件名为:77-tcp_timestamps.conf 内容如下:

# see https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=25429d7b7dca01dc4f17205de023a30ca09390d0
net.ipv4.tcp_timestamps=2

sudo sysctl -p --system 可以不要重启而使这个conf文件马上生效,不过我刚才已经用echo 改变那个值了,因此这里不是必要的。

验证

重启Arch之后,检查下值 生效否:

[root@hacklog sysctl.d]# sysctl -a | grep tcp_timestamps
net.ipv4.tcp_timestamps = 2

然后再测试下打开路由器界面,一切正常了。

结论

故障产生的原因是,4.10.1版本的内核新增加且默认启用的 random offset timestamps功能,跟3.4.113 的基于Linux的路由器通信时导致的。 3.4.113 的内核必然是没有开启 random offset的.

--EOF

Tagged in :

All Comments (1)
Gravatar image
Gravatar image
kn007
过来学习!