如何更改 Linux 中默认的 SYN 重传指数退避?

如何更改 Linux 中默认的 SYN 重传指数退避?

默认情况下,如果 SYN 数据包在一秒内没有得到响应,Linux 会假设第一个数据包已被丢弃在某处,然后发送另一个数据包。两秒后又是一次,然后是四秒,直到一定限度。

如何将基数从 1 秒更改为更高的值,例如 10 秒?

原因

我有高延迟、低带宽(注意:低带宽。这不是经典的带宽延迟乘积问题)。由于该通道在某些配置下具有高延迟,因此我预计不会在一秒内得到答案。由于带宽较低,重新发送 SYN 会不必要地消耗宝贵的带宽。

具体来说这是洛拉,并且传输 SYN 数据包可能需要 5 秒以上(取决于通道设置,而通道设置又取决于范围等……)。这意味着,如果我发送另一封邮件,我会额外保持发射器打开 5 秒,并且很可能甚至听不到另一端正在回复,从而导致更多的重发。

我尝试过的

ip路由

我认为我可以像更改 cwnd 一样更改它:

ip route change default via x.x.x.x initcwnd 20 initrwnd 20

所以我把rttrttvarrto_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

相关内容