1

By default, if a SYN packet is not responded within one second, linux sends another one under the assumption that the first one was dropped somewhere. Then another after two more seconds, then four, up to some limit.

How do I change the base from 1s to something higher, like 10s?

Reason

I have a high latency, low bandwidth (note: low bandwidth. This is not the classic bandwidth-delay product question). Since the channel is high latency under some configurations I'm not expecting an answer in less than a second. Since it's low bandwidth resending the SYN needlessly consumes precious bandwidth.

Specifically this is LoRa, and it can take over 5 seconds to transmit the SYN packet (depending on channel settings, which in turn depend on range, etc…). That means if I sent another one I'm holding the transmitter open for 5 seconds extra, and will quite possibly not even hear that the other end is replying, leading to even more retransmits.

What I've tried

iproute

I thought that I would be able to change this just like you can change the cwnd:

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

So I changed rtt, rttvar, and rto_min, to be much higher, but they had zero effect on the retransmission.

setsockopt / ioctl

I've not found any appropriate sockopt, but even if I did that would mean change to application code, right?

sysctl

Same here: Not only have I not found a setting, but also ideally this should not be system wide, since a node may have a normal internet connection too.

2
  • How did you change rto_min? Nov 24, 2020 at 20:44
  • ip r change 192.0.2.2/32 dev lora0 rtt 20s rto_min 20s rttvar 5s, and it comes back when listing as rtt 20s rttvar 5s rto_min lock 20s
    – Thomas
    Nov 24, 2020 at 22:45

1 Answer 1

0

I figured it out.

See this blog post for how you can make a eBPF program that will override the timeout.

In short, you need to load this sockops program:

#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;

You can compile and load it with:

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .