🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

Commit 3a4e3ae

Browse files
committed
feat: support IPv6 (part one)
* config: introduce cluster-level knob 'use_ipv6' - and wire it through common transport args * net: support IPv6 ToS (IPV6_TCLASS) in socket options - in addition to IPv4 (IP_TOS) * startup: add initial local IPv6 selection logic - NOTE: LocalNetConfig.Hostname* still takes precedence * TODO: - grep and fix all "To4()" occurrences - review IPv6 discovery - test... Signed-off-by: Alex Aizman <alex.aizman@gmail.com>
1 parent 5998375 commit 3a4e3ae

12 files changed

Lines changed: 255 additions & 81 deletions

File tree

‎ais/htcommon.go‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ type (
175175
sndRcvBufSize int
176176
sync.Mutex
177177
lowLatencyToS bool
178+
useIPv6 bool
178179
}
179180

180181
nlogWriter struct{}
@@ -523,10 +524,19 @@ func (server *netServer) listen(addr string, logger *log.Logger, tlsConf *tls.Co
523524
server.s.ReadHeaderTimeout = timeout
524525
}
525526

526-
// set sock options on the server side; NOTE https exclusion
527+
// NOTE: socket-level options (SO_RCVBUF / SO_SNDBUF, IP_TOS / IPV6_TCLASS)
528+
// are currently applied via http.Server.ConnState at StateNew, which
529+
// requires the connection to be a *net.TCPConn - to obtain syscall.RawConn.
530+
// When HTTPS is enabled, the connection passed to ConnState is *tls.Conn
531+
// (wrapped TCP), making a direct TCP assertion invalid.
532+
//
533+
// TODO: for HTTPS, consider moving the code to the Accept() path _or_ using
534+
// net.ListenConfig.Control before TLS wrapping.
535+
527536
if (server.sndRcvBufSize > 0 || server.lowLatencyToS) && !config.Net.HTTP.UseHTTPS {
528537
server.s.ConnState = server.connStateListener
529538
}
539+
530540
server.s.TLSConfig = tlsConf
531541
server.Unlock()
532542

@@ -602,12 +612,20 @@ func (server *netServer) connStateListener(c net.Conn, cs http.ConnState) {
602612
}
603613
tcpconn, ok := c.(*net.TCPConn)
604614
debug.Assert(ok)
615+
616+
// detect actual IP version from the connection
617+
// (may differ from config in misconfigurations (or future dual-stack))
618+
useIPv6 := server.useIPv6
619+
if ra, ok := tcpconn.RemoteAddr().(*net.TCPAddr); ok && ra.IP != nil {
620+
useIPv6 = ra.IP.To4() == nil
621+
}
622+
605623
rawconn, err := tcpconn.SyscallConn()
606624
if err != nil {
607625
nlog.Errorln("FATAL tcpconn.SyscallConn err:", err) // (unlikely)
608626
return
609627
}
610-
args := cmn.TransportArgs{SndRcvBufSize: server.sndRcvBufSize, LowLatencyToS: server.lowLatencyToS}
628+
args := cmn.TransportArgs{SndRcvBufSize: server.sndRcvBufSize, LowLatencyToS: server.lowLatencyToS, UseIPv6: useIPv6}
611629
args.ServerControl(rawconn)
612630
}
613631

‎ais/htrun.go‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -363,20 +363,20 @@ func (h *htrun) init(config *cmn.Config) {
363363

364364
// PubNet enable tracing when configuration is set.
365365
muxers := newMuxers(tracing.IsEnabled())
366-
g.netServ.pub = &netServer{muxers: muxers, sndRcvBufSize: tcpbuf}
366+
g.netServ.pub = &netServer{muxers: muxers, sndRcvBufSize: tcpbuf, useIPv6: config.Net.UseIPv6}
367367
g.netServ.control = g.netServ.pub // if not separately configured, intra-control net is public
368368
if config.HostNet.UseIntraControl {
369369
// TODO: for now tracing is always disabled for intra-cluster traffic.
370370
// Allow enabling through config.
371371
muxers = newMuxers(false /*enableTracing*/)
372-
g.netServ.control = &netServer{muxers: muxers, sndRcvBufSize: 0, lowLatencyToS: true}
372+
g.netServ.control = &netServer{muxers: muxers, sndRcvBufSize: 0, lowLatencyToS: true, useIPv6: config.Net.UseIPv6}
373373
}
374374
g.netServ.data = g.netServ.control // if not configured, intra-data net is intra-control
375375
if config.HostNet.UseIntraData {
376376
// TODO: for now tracing is always disabled for intra-data traffic.
377377
// Allow enabling through config.
378378
muxers = newMuxers(false /*enableTracing*/)
379-
g.netServ.data = &netServer{muxers: muxers, sndRcvBufSize: tcpbuf}
379+
g.netServ.data = &netServer{muxers: muxers, sndRcvBufSize: tcpbuf, useIPv6: config.Net.UseIPv6}
380380
}
381381

382382
h.owner.smap = newSmapOwner(config)
@@ -402,7 +402,7 @@ func (h *htrun) initSnode(config *cmn.Config) {
402402
port = strconv.Itoa(config.HostNet.Port)
403403
proto = config.Net.HTTP.Proto
404404
)
405-
addrList, err := getLocalIPv4s(config)
405+
addrList, err := getLocalIPs(config)
406406
if err != nil {
407407
cos.ExitLogf("failed to get local IP addr list: %v", err)
408408
}
@@ -428,8 +428,8 @@ func (h *htrun) initSnode(config *cmn.Config) {
428428
// public hostname could be a load balancer's external IP or a service DNS
429429
nlog.Infoln("K8s deployment: skipping hostname validation for", config.HostNet.Hostname)
430430
pubAddr.Init(proto, pub, port)
431-
} else if err = initNetInfo(&pubAddr, addrList, proto, config.HostNet.Hostname, port); err != nil {
432-
cos.ExitLogf("failed to get %s IPv4/hostname: %v", cmn.NetPublic, err)
431+
} else if err = initNetInfo(&pubAddr, addrList, proto, config.HostNet.Hostname, port, config.Net.UseIPv6); err != nil {
432+
cos.ExitLogf("failed to select %s IP/hostname: %v", cmn.NetPublic, err)
433433
}
434434

435435
// multi-home (when config.HostNet.Hostname is a comma-separated list)
@@ -452,9 +452,9 @@ func (h *htrun) initSnode(config *cmn.Config) {
452452
ctrlAddr = pubAddr
453453
if config.HostNet.UseIntraControl {
454454
icport := strconv.Itoa(config.HostNet.PortIntraControl)
455-
err = initNetInfo(&ctrlAddr, addrList, proto, config.HostNet.HostnameIntraControl, icport)
455+
err = initNetInfo(&ctrlAddr, addrList, proto, config.HostNet.HostnameIntraControl, icport, config.Net.UseIPv6)
456456
if err != nil {
457-
cos.ExitLogf("failed to get %s IPv4/hostname: %v", cmn.NetIntraControl, err)
457+
cos.ExitLogf("failed to select %s IP/hostname: %v", cmn.NetIntraControl, err)
458458
}
459459
var s string
460460
if config.HostNet.HostnameIntraControl != "" {
@@ -465,9 +465,9 @@ func (h *htrun) initSnode(config *cmn.Config) {
465465
dataAddr = pubAddr
466466
if config.HostNet.UseIntraData {
467467
idport := strconv.Itoa(config.HostNet.PortIntraData)
468-
err = initNetInfo(&dataAddr, addrList, proto, config.HostNet.HostnameIntraData, idport)
468+
err = initNetInfo(&dataAddr, addrList, proto, config.HostNet.HostnameIntraData, idport, config.Net.UseIPv6)
469469
if err != nil {
470-
cos.ExitLogf("failed to get %s IPv4/hostname: %v", cmn.NetIntraData, err)
470+
cos.ExitLogf("failed to select %s IP/hostname: %v", cmn.NetIntraData, err)
471471
}
472472
var s string
473473
if config.HostNet.HostnameIntraData != "" {
@@ -628,7 +628,7 @@ func (h *htrun) run(config *cmn.Config) error {
628628
} else if len(h.si.PubExtra) > 0 {
629629
for _, pubExtra := range h.si.PubExtra {
630630
debug.Assert(pubExtra.Port == h.si.PubNet.Port, "expecting the same TCP port for all multi-home interfaces")
631-
server := &netServer{muxers: g.netServ.pub.muxers, sndRcvBufSize: g.netServ.pub.sndRcvBufSize}
631+
server := &netServer{muxers: g.netServ.pub.muxers, sndRcvBufSize: g.netServ.pub.sndRcvBufSize, useIPv6: config.Net.UseIPv6}
632632
go func() {
633633
_ = server.listen(pubExtra.TCPEndpoint(), logger, tlsConf, config)
634634
}()

‎ais/http.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ func initCtrlClient(config *cmn.Config) {
6767
IdleConnsPerHost: config.Net.HTTP.MaxIdleConnsPerHost,
6868
MaxIdleConns: config.Net.HTTP.MaxIdleConns,
6969
LowLatencyToS: true,
70+
UseIPv6: config.Net.UseIPv6,
7071
}
7172
if config.Net.HTTP.UseHTTPS {
7273
g.client.control = cmn.NewIntraClientTLS(cargs, config)

‎ais/prxauth.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ func newKeyCacheClient(config *cmn.Config, statsT stats.Tracker) *http.Client {
131131
Timeout: KeyCacheTimeout,
132132
IdleConnsPerHost: KeyCacheIdleConnsPerHost,
133133
MaxIdleConns: maxIdleConns,
134+
UseIPv6: config.Net.UseIPv6,
134135
}
135136
client := cmn.NewClientTLS(transport, tls, false)
136137

‎ais/prxrev.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ func rpTransport(config *cmn.Config) *http.Transport {
229229
IdleConnTimeout: config.Net.HTTP.IdleConnTimeout.D(),
230230
IdleConnsPerHost: config.Net.HTTP.MaxIdleConnsPerHost,
231231
MaxIdleConns: config.Net.HTTP.MaxIdleConns,
232+
UseIPv6: config.Net.UseIPv6,
232233
})
233234
)
234235
if config.Net.HTTP.UseHTTPS {

0 commit comments

Comments
 (0)