Closed Lanius-collaris closed 4 months ago
(thank you)
Might as well be a bug (though, I doubt it triggers at all for non-local traffic?).
The moral of this story is, we don't need multiple goroutines acting on one channel (like today), but need multiple channels (carefully muxing/demuxing TCP streams & ICMP/UDP packets onto them) with each pinned exactly to just one goroutine consumer (like done by Google: https://github.com/google/gvisor/commit/19c7ca8c3bd9dd8bfe8c657845d79c752c9f3ff6).
We might want to prioritise backporting their processors.go
logic, if retrans are higher with regular traffic too (ie, internet bound TCP streams).
Although I'm not sure if it's prone to "deadlock".
netstack "deadlock"s can happen with any number of forwarders, but higher their count, the less likely netstack "deadlock"s (actually, it stalls).
maxForwarders
can be 0
. If there's just one forwarder, that is, if initForwarders=1
and maxForwarders=0
(both can also be set to 1
), this stall happens occasionally (but it is not rare). With initForwarders=3
, I never hit a stall. maxFowarders=9
is more of an insurance than guarantee.
I think the "buffer" is too shallow to make congestion control work. When forwarding TCP, inner TCP connections and outer TCP connections are piped.
I doubt it triggers at all for non-local traffic?
No matter how slow the outer link will be, the inner link will be fast forever.
I think the "buffer" is too shallow to make congestion control work.
Sorry, shallow buffer set where? In netstack.go
?
Sorry, shallow buffer set where? In
netstack.go
?
I don't know, there isn't a real router with queue between two endpoints of the inner TCP connection. Maybe forwarders act like shallow buffer. 🤕
I don't know, there isn't a real router with queue between two endpoints of the inner TCP connection.
Oh okay. Yeah, there's no real buffer there, but a splice/copy from one end of the pipe to the other: https://github.com/celzero/firestack/blob/7306ed7024fc8e8d9847f81cea42b827f0a5877a/intra/common.go#L25-L42
Maybe forwarders act like shallow buffer
I've removed the channel and forwarders acting on it, and brought in Google's changes (from upstream), which deals in a list-of-packet-buffers pre-sharded using 5-tuple (src,dst,proto) to any one among the preset 9
processors.
Fixed? 🤗
emulator64_x86_64:/data/local/tmp $ ./iperf3.17.1 -c 10.64.0.5
Connecting to host 10.64.0.5, port 5201
[ 5] local 10.111.222.1 port 47092 connected to 10.64.0.5 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 169 MBytes 1.42 Gbits/sec 13 515 KBytes
[ 5] 1.00-2.00 sec 172 MBytes 1.44 Gbits/sec 2 522 KBytes
[ 5] 2.00-3.00 sec 170 MBytes 1.43 Gbits/sec 2 530 KBytes
[ 5] 3.00-4.00 sec 172 MBytes 1.45 Gbits/sec 1 526 KBytes
[ 5] 4.00-5.00 sec 168 MBytes 1.41 Gbits/sec 3 510 KBytes
[ 5] 5.00-6.00 sec 173 MBytes 1.45 Gbits/sec 1 526 KBytes
[ 5] 6.00-7.00 sec 172 MBytes 1.44 Gbits/sec 1 536 KBytes
[ 5] 7.00-8.00 sec 170 MBytes 1.43 Gbits/sec 5 542 KBytes
[ 5] 8.00-9.00 sec 174 MBytes 1.46 Gbits/sec 5 547 KBytes
[ 5] 9.00-10.00 sec 174 MBytes 1.46 Gbits/sec 6 561 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 1.68 GBytes 1.44 Gbits/sec 39 sender
[ 5] 0.00-10.00 sec 1.67 GBytes 1.44 Gbits/sec receiver
iperf Done.
Thanks for confirming! (:
A happy coincidence that Google pushed out changes to the exact same part of the code to improve perf... that we ended up getting those fixes for free.
It is not a bug.
rethink firewall mode, no wireguard
initForwarders = 3, maxForwarders = 9 :
Note: iperf3 gets total retransmissions from tcp_info struct https://github.com/esnet/iperf/blob/master/src/tcp_info.c#L114-#L126 On linux, you can find definition of tcp_info in
/usr/include/linux/tcp.h
It's interesting that setting a smaller maxForwarders is able to reduce TCP retransmissions (but increases RTT, see Cwnd). Although I'm not sure if it's prone to "deadlock".
maxForwarders = 2:
maxForwarders = 1
Note: You can see Retr field = 0 with some apps (e.g. Intra). I guess they ACK all segments. lol