![如何更改 Linux 中默认的 SYN 重传指数退避?](https://linux22.com/image/183994/%E5%A6%82%E4%BD%95%E6%9B%B4%E6%94%B9%20Linux%20%E4%B8%AD%E9%BB%98%E8%AE%A4%E7%9A%84%20SYN%20%E9%87%8D%E4%BC%A0%E6%8C%87%E6%95%B0%E9%80%80%E9%81%BF%EF%BC%9F.png)
默认情况下,如果 SYN 数据包在一秒内没有得到响应,Linux 会假设第一个数据包已被丢弃在某处,然后发送另一个数据包。两秒后又是一次,然后是四秒,直到一定限度。
如何将基数从 1 秒更改为更高的值,例如 10 秒?
原因
我有高延迟、低带宽(注意:低带宽。这不是经典的带宽延迟乘积问题)。由于该通道在某些配置下具有高延迟,因此我预计不会在一秒内得到答案。由于带宽较低,重新发送 SYN 会不必要地消耗宝贵的带宽。
具体来说这是洛拉,并且传输 SYN 数据包可能需要 5 秒以上(取决于通道设置,而通道设置又取决于范围等……)。这意味着,如果我发送另一封邮件,我会额外保持发射器打开 5 秒,并且很可能甚至听不到另一端正在回复,从而导致更多的重发。
我尝试过的
ip路由
我认为我可以像更改 cwnd 一样更改它:
ip route change default via x.x.x.x initcwnd 20 initrwnd 20
所以我把rtt
、rttvar
、rto_min
、 改得更高,但它们对重传的影响为零。
setsockopt/ioctl
我还没有找到任何合适的 sockopt,但即使我找到了,这也意味着要更改应用程序代码,对吧?
系统控制
同样:我不仅没有找到设置,而且理想情况下这不应该是系统范围的,因为节点也可能有正常的互联网连接。
答案1
我想到了。
看这篇博文了解如何制作一个可以覆盖超时的 eBPF 程序。
简而言之,您需要加载这个sockops
程序:
#include<linux/bpf.h>
#define SEC(NAME) __attribute__((section(NAME), used))
// TODO: assumes little-endian (x86, amd64)
#define bpf_ntohl(x) __builtin_bswap32(x)
SEC("sockops")
int bpf_sockmap(struct bpf_sock_ops *skops)
{
const int op = (int) skops->op;
if (op == BPF_SOCK_OPS_TIMEOUT_INIT) {
// TODO: this is in jiffies, and despite `getconf CLK_TCK` return 100, HZ is clearly 25 on my kernel.
// 5000 / 250 = 20 seconds
skops->reply = 5000;
return 1;
}
return 0;
}
char _license[] __attribute((section("license"),used)) = "GPL";
int _version SEC("version") = 1;
您可以使用以下命令编译并加载它:
clang $CFLAGS -target bpf -Wall -g -O2 -c set_rto.c -o set_rto.o
sudo bpftool prog load set_rto.o /sys/fs/bpf/bpf_sockop
sudo bpftool cgroup attach /sys/fs/cgroup/unified/ sock_ops pinned /sys/fs/bpf/set_rto