Skip to content

Commit 6f8c486

Browse files
authored
perf: tweak tcp settings for better redirection performance (#559)
1 parent fca4ccf commit 6f8c486

File tree

1 file changed

+52
-8
lines changed

1 file changed

+52
-8
lines changed

pkg/wsman/client/wsman_tcp.go

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@ import (
88
"fmt"
99
"net"
1010
"sync"
11+
"time"
12+
)
13+
14+
const (
15+
// defaultBufferPoolSize controls the per-Receive temporary buffer size used to read from the socket.
16+
// Larger values reduce syscalls and fragmentation for KVM streaming payloads.
17+
defaultBufferPoolSize = 64 * 1024
18+
19+
// tcpSocketBufferSize sets OS-level socket read/write buffer hints for throughput.
20+
tcpSocketBufferSize = 256 * 1024
21+
22+
// defaultKeepAlive configures TCP keepalive probe interval on the dialer.
23+
defaultKeepAlive = 30 * time.Second
1124
)
1225

1326
func NewWsmanTCP(cp Parameters) *Target {
@@ -28,29 +41,30 @@ func NewWsmanTCP(cp Parameters) *Target {
2841
PinnedCert: cp.PinnedCert,
2942
bufferPool: sync.Pool{
3043
New: func() interface{} {
31-
return make([]byte, 4096) // Adjust size according to your needs.
44+
// Larger buffer to reduce read syscalls and frame fragmentation for KVM streams
45+
return make([]byte, defaultBufferPoolSize)
3246
},
3347
},
3448
}
3549
}
3650

3751
// Connect establishes a TCP connection to the endpoint specified in the Target struct.
3852
func (t *Target) Connect() error {
39-
var err error
53+
// Use a Dialer so we can enable TCP keep-alives and TCP_NODELAY for lower latency.
54+
d := &net.Dialer{KeepAlive: defaultKeepAlive}
4055

4156
if t.UseTLS {
42-
// check if pinnedCert is not null and not empty
57+
// Build TLS config with optional pinning
4358
var config *tls.Config
4459
if len(t.PinnedCert) > 0 {
4560
config = &tls.Config{
4661
InsecureSkipVerify: t.InsecureSkipVerify,
47-
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
62+
VerifyPeerCertificate: func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
4863
for _, rawCert := range rawCerts {
4964
cert, err := x509.ParseCertificate(rawCert)
5065
if err != nil {
5166
return err
5267
}
53-
5468
// Compare the current certificate with the pinned certificate
5569
sha256Fingerprint := sha256.Sum256(cert.Raw)
5670
if hex.EncodeToString(sha256Fingerprint[:]) == t.PinnedCert {
@@ -65,15 +79,45 @@ func (t *Target) Connect() error {
6579
config = &tls.Config{InsecureSkipVerify: t.InsecureSkipVerify}
6680
}
6781

68-
t.conn, err = tls.Dial("tcp", t.endpoint, config)
69-
} else {
70-
t.conn, err = net.Dial("tcp", t.endpoint)
82+
// Establish plain TCP first to set socket options
83+
plainConn, err := d.Dial("tcp", t.endpoint)
84+
if err != nil {
85+
return fmt.Errorf("failed to connect to %s: %w", t.endpoint, err)
86+
}
87+
88+
if tcp, ok := plainConn.(*net.TCPConn); ok {
89+
// Best-effort; ignore error to avoid failing connection setup
90+
_ = tcp.SetNoDelay(true)
91+
_ = tcp.SetReadBuffer(tcpSocketBufferSize)
92+
_ = tcp.SetWriteBuffer(tcpSocketBufferSize)
93+
}
94+
95+
tlsConn := tls.Client(plainConn, config)
96+
if err := tlsConn.Handshake(); err != nil {
97+
_ = plainConn.Close()
98+
99+
return fmt.Errorf("TLS handshake failed with %s: %w", t.endpoint, err)
100+
}
101+
102+
t.conn = tlsConn
103+
104+
return nil
71105
}
72106

107+
// Non-TLS path
108+
c, err := d.Dial("tcp", t.endpoint)
73109
if err != nil {
74110
return fmt.Errorf("failed to connect to %s: %w", t.endpoint, err)
75111
}
76112

113+
if tcp, ok := c.(*net.TCPConn); ok {
114+
_ = tcp.SetNoDelay(true)
115+
_ = tcp.SetReadBuffer(tcpSocketBufferSize)
116+
_ = tcp.SetWriteBuffer(tcpSocketBufferSize)
117+
}
118+
119+
t.conn = c
120+
77121
return nil
78122
}
79123

0 commit comments

Comments
 (0)