From 50f6327722b42439d2a5b5bab40d141d29a53070 Mon Sep 17 00:00:00 2001 From: Oleksandr Natalenko Date: Sat, 17 Apr 2021 14:49:29 +0200 Subject: [PATCH] tcp_linux: make tcp congestion control algorithm selectable Signed-off-by: Oleksandr Natalenko --- src/config/config.go | 2 ++ src/defaults/defaults.go | 1 + src/defaults/defaults_darwin.go | 1 + src/defaults/defaults_linux.go | 1 + src/defaults/defaults_openbsd.go | 1 + src/defaults/defaults_other.go | 1 + src/defaults/defaults_windows.go | 1 + src/yggdrasil/tcp_linux.go | 16 +++++++++++----- 8 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/config/config.go b/src/config/config.go index 95d9bbd1..57ea476d 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -80,6 +80,7 @@ type NodeConfig struct { SwitchOptions SwitchOptions `comment:"Advanced options for tuning the switch. Normally you will not need\nto edit these options."` NodeInfoPrivacy bool `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Yggdrasil version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."` NodeInfo map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."` + TCPCongestionControl string `json:",omitempty" comment:"Optional TCP congestion control algorithm used for connections. If not set, a system-wide setting is applied. Linux-only."` } // SessionFirewall controls the session firewall configuration. @@ -135,6 +136,7 @@ func GenerateConfig() *NodeConfig { cfg.SessionFirewall.AlwaysAllowOutbound = true cfg.SwitchOptions.MaxTotalQueueSize = 4 * 1024 * 1024 cfg.NodeInfoPrivacy = false + cfg.TCPCongestionControl = defaults.GetDefaults().DefaultTCPCongestionControl return &cfg } diff --git a/src/defaults/defaults.go b/src/defaults/defaults.go index a0d372e4..38f4b7f9 100644 --- a/src/defaults/defaults.go +++ b/src/defaults/defaults.go @@ -19,4 +19,5 @@ type platformDefaultParameters struct { MaximumIfMTU types.MTU DefaultIfMTU types.MTU DefaultIfName string + DefaultTCPCongestionControl string } diff --git a/src/defaults/defaults_darwin.go b/src/defaults/defaults_darwin.go index 9fbe6d8e..98e5f3f2 100644 --- a/src/defaults/defaults_darwin.go +++ b/src/defaults/defaults_darwin.go @@ -22,5 +22,6 @@ func GetDefaults() platformDefaultParameters { MaximumIfMTU: 65535, DefaultIfMTU: 65535, DefaultIfName: "auto", + DefaultTCPCongestionControl: "", } } diff --git a/src/defaults/defaults_linux.go b/src/defaults/defaults_linux.go index 5f3f12a8..063f5cec 100644 --- a/src/defaults/defaults_linux.go +++ b/src/defaults/defaults_linux.go @@ -21,5 +21,6 @@ func GetDefaults() platformDefaultParameters { MaximumIfMTU: 65535, DefaultIfMTU: 65535, DefaultIfName: "auto", + DefaultTCPCongestionControl: "bbr", } } diff --git a/src/defaults/defaults_openbsd.go b/src/defaults/defaults_openbsd.go index 6700eb8f..c14429df 100644 --- a/src/defaults/defaults_openbsd.go +++ b/src/defaults/defaults_openbsd.go @@ -21,5 +21,6 @@ func GetDefaults() platformDefaultParameters { MaximumIfMTU: 16384, DefaultIfMTU: 16384, DefaultIfName: "tun0", + DefaultTCPCongestionControl: "", } } diff --git a/src/defaults/defaults_other.go b/src/defaults/defaults_other.go index 3b035537..12d731aa 100644 --- a/src/defaults/defaults_other.go +++ b/src/defaults/defaults_other.go @@ -21,5 +21,6 @@ func GetDefaults() platformDefaultParameters { MaximumIfMTU: 65535, DefaultIfMTU: 65535, DefaultIfName: "none", + DefaultTCPCongestionControl: "", } } diff --git a/src/defaults/defaults_windows.go b/src/defaults/defaults_windows.go index 305a2ffe..c31dc3e3 100644 --- a/src/defaults/defaults_windows.go +++ b/src/defaults/defaults_windows.go @@ -21,5 +21,6 @@ func GetDefaults() platformDefaultParameters { MaximumIfMTU: 65535, DefaultIfMTU: 65535, DefaultIfName: "Yggdrasil", + DefaultTCPCongestionControl: "", } } diff --git a/src/yggdrasil/tcp_linux.go b/src/yggdrasil/tcp_linux.go index e18f92b1..9f44a769 100644 --- a/src/yggdrasil/tcp_linux.go +++ b/src/yggdrasil/tcp_linux.go @@ -11,19 +11,25 @@ import ( // WARNING: This context is used both by net.Dialer and net.Listen in tcp.go func (t *tcp) tcpContext(network, address string, c syscall.RawConn) error { + var tcp_cca = t.links.core.config.Current.TCPCongestionControl var control error - var bbr error + var ret error + + // do not change TCP congestion control algorithm so that a system-wide one is used + if tcp_cca == "" { + return nil + } control = c.Control(func(fd uintptr) { - bbr = unix.SetsockoptString(int(fd), unix.IPPROTO_TCP, unix.TCP_CONGESTION, "bbr") + ret = unix.SetsockoptString(int(fd), unix.IPPROTO_TCP, unix.TCP_CONGESTION, tcp_cca) }) // Log any errors - if bbr != nil { - t.links.core.log.Debugln("Failed to set tcp_congestion_control to bbr for socket, SetsockoptString error:", bbr) + if ret != nil { + t.links.core.log.Debugf("Failed to set tcp_congestion_control to %s for socket, SetsockoptString error: %s\n", tcp_cca, ret) } if control != nil { - t.links.core.log.Debugln("Failed to set tcp_congestion_control to bbr for socket, Control error:", control) + t.links.core.log.Debugf("Failed to set tcp_congestion_control to %s for socket, Control error:\n", tcp_cca, control) } // Return nil because errors here are not considered fatal for the connection, it just means congestion control is suboptimal