From 77dedcb26bdee2e3d29cb55137c942b26dd79905 Mon Sep 17 00:00:00 2001 From: Gary Lee Date: Thu, 23 Mar 2023 13:42:25 +1100 Subject: [PATCH 1/3] Add DSCP value to outgoing HTTP requests Add ability to specify a DSCP value in IPv4/IPv6 header of outgoing HTTP requests Signed-off-by: Gary Lee --- config/http_config.go | 23 +++++++++++++++++++++++ config/http_config_test.go | 11 +++++++++++ 2 files changed, 34 insertions(+) diff --git a/config/http_config.go b/config/http_config.go index 73163206..51d30d83 100644 --- a/config/http_config.go +++ b/config/http_config.go @@ -28,6 +28,7 @@ import ( "path/filepath" "strings" "sync" + "syscall" "time" "github.com/mwitkow/go-conntrack" @@ -43,6 +44,7 @@ var ( DefaultHTTPClientConfig = HTTPClientConfig{ FollowRedirects: true, EnableHTTP2: true, + DSCP: 0, } // defaultHTTPClientOptions holds the default HTTP client options. @@ -309,6 +311,8 @@ type HTTPClientConfig struct { EnableHTTP2 bool `yaml:"enable_http2" json:"enable_http2"` // Proxy configuration. ProxyConfig `yaml:",inline"` + // DSCP configuration + DSCP int `yaml:"dscp" json:"dscp"` } // SetDirectory joins any relative file paths with dir. @@ -1159,3 +1163,22 @@ func (c *ProxyConfig) Proxy() (fn func(*http.Request) (*url.URL, error)) { func (c *ProxyConfig) GetProxyConnectHeader() http.Header { return c.ProxyConnectHeader.HTTPHeader() } + +type DSCPDialer struct { + DSCP int +} + +func (d *DSCPDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { + conn, err := (&net.Dialer{ + Control: func(network, address string, c syscall.RawConn) error { + return c.Control(func(fd uintptr) { + if network == "tcp6" || network == "udp6" { + _ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, d.DSCP<<2) + } else { + _ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TOS, d.DSCP<<2) + } + }) + }}).DialContext(ctx, network, addr) + + return conn, err +} diff --git a/config/http_config_test.go b/config/http_config_test.go index 638a1332..59d606ff 100644 --- a/config/http_config_test.go +++ b/config/http_config_test.go @@ -1838,3 +1838,14 @@ no_proxy: promcon.io,cncf.io`, proxyServer.URL), }) } } + +func TestDSCPDialContext(t *testing.T) { + cfg := HTTPClientConfig{DSCP: 46} + dialer := &DSCPDialer{DSCP: cfg.DSCP} + httpClientOption := WithDialContextFunc(dialer.DialContext) + + _, err := NewClientFromConfig(cfg, "test", httpClientOption) + if err != nil { + t.Fatalf("Can't create a client from this config: %+v", cfg) + } +} From 831916b04ef88e9ac89b4f667aca98d5c131b139 Mon Sep 17 00:00:00 2001 From: Gary Lee Date: Tue, 28 Mar 2023 17:05:23 +1100 Subject: [PATCH 2/3] Add DSCP value to outgoing HTTP requests Replace syscall with golang.org/x/net calls Signed-off-by: Gary Lee --- config/http_config.go | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/config/http_config.go b/config/http_config.go index 51d30d83..5718c2c8 100644 --- a/config/http_config.go +++ b/config/http_config.go @@ -28,12 +28,13 @@ import ( "path/filepath" "strings" "sync" - "syscall" "time" "github.com/mwitkow/go-conntrack" "golang.org/x/net/http/httpproxy" "golang.org/x/net/http2" + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" "golang.org/x/oauth2" "golang.org/x/oauth2/clientcredentials" "gopkg.in/yaml.v2" @@ -1169,16 +1170,18 @@ type DSCPDialer struct { } func (d *DSCPDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { - conn, err := (&net.Dialer{ - Control: func(network, address string, c syscall.RawConn) error { - return c.Control(func(fd uintptr) { - if network == "tcp6" || network == "udp6" { - _ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_TCLASS, d.DSCP<<2) - } else { - _ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TOS, d.DSCP<<2) - } - }) - }}).DialContext(ctx, network, addr) - - return conn, err + conn, err := (&net.Dialer{}).DialContext(ctx, network, addr) + + if err != nil { + return conn, err + } + + err = ipv6.NewConn(conn).SetTrafficClass(d.DSCP << 2) + if err != nil { + // fallback to IPv4 + // err is ignored. It's probably not implemented on this platform if it fails + _ = ipv4.NewConn(conn).SetTOS(d.DSCP << 2) + } + + return conn, nil } From 5fc589b8f37d16dd7a5d8f4449d9f77ca51b11d8 Mon Sep 17 00:00:00 2001 From: Gary Lee Date: Mon, 3 Apr 2023 19:19:45 +1000 Subject: [PATCH 3/3] Add DSCP value to outgoing HTTP requests Remove whitespace Signed-off-by: Gary Lee --- config/http_config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/config/http_config.go b/config/http_config.go index 5718c2c8..1a5cac45 100644 --- a/config/http_config.go +++ b/config/http_config.go @@ -1171,7 +1171,6 @@ type DSCPDialer struct { func (d *DSCPDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { conn, err := (&net.Dialer{}).DialContext(ctx, network, addr) - if err != nil { return conn, err }