Skip to content

Commit fa5cb4c

Browse files
committed
support IPv6: apply effective IP family consistently; add docs/networking.md
* split htrun init into phase1 (network resolution) and phase2 (clients/runtime) * apply effective IP family to all HTTP listeners and intra-cluster clients * fix IPv6 fallback bug where clients could dial v6 after v4 bind * align AuthN and control transports with resolved networking ------ * docs: add docs/networking.md ------ * part six, prev. commit: f3630bc Signed-off-by: Alex Aizman <alex.aizman@gmail.com>
1 parent bbe95b0 commit fa5cb4c

9 files changed

Lines changed: 338 additions & 70 deletions

File tree

ais/htrun.go

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -341,59 +341,13 @@ func (h *htrun) regNetHandlers(networkHandlers []networkHandler) {
341341
}
342342
}
343343

344-
func (h *htrun) init(config *cmn.Config) {
345-
// before newTLS() below & before intra-cluster clients
346-
if config.Net.HTTP.UseHTTPS {
347-
if err := certloader.Init(config.Net.HTTP.Certificate, config.Net.HTTP.CertKey, h.statsT); err != nil {
348-
cos.ExitLog(err)
349-
}
350-
}
351-
352-
initCtrlClient(config)
353-
initDataClient(config)
354-
355-
load.Init()
356-
357-
tcpbuf := config.Net.L4.SndRcvBufSize
358-
if h.si.IsProxy() {
359-
tcpbuf = 0
360-
} else if tcpbuf == 0 {
361-
tcpbuf = cmn.DefaultSndRcvBufferSize // ditto: targets use AIS default when not configured
362-
}
363-
364-
// PubNet enable tracing when configuration is set.
365-
muxers := newMuxers(tracing.IsEnabled())
366-
g.netServ.pub = &netServer{muxers: muxers, sndRcvBufSize: tcpbuf, useIPv6: config.Net.UseIPv6}
367-
g.netServ.control = g.netServ.pub // if not separately configured, intra-control net is public
368-
if config.HostNet.UseIntraControl {
369-
// TODO: for now tracing is always disabled for intra-cluster traffic.
370-
// Allow enabling through config.
371-
muxers = newMuxers(false /*enableTracing*/)
372-
g.netServ.control = &netServer{muxers: muxers, sndRcvBufSize: 0, lowLatencyToS: true, useIPv6: config.Net.UseIPv6}
373-
}
374-
g.netServ.data = g.netServ.control // if not configured, intra-data net is intra-control
375-
if config.HostNet.UseIntraData {
376-
// TODO: for now tracing is always disabled for intra-data traffic.
377-
// Allow enabling through config.
378-
muxers = newMuxers(false /*enableTracing*/)
379-
g.netServ.data = &netServer{muxers: muxers, sndRcvBufSize: tcpbuf, useIPv6: config.Net.UseIPv6}
380-
}
381-
382-
h.owner.smap = newSmapOwner(config)
383-
h.owner.rmd = newRMDOwner(config)
384-
h.owner.rmd.load()
385-
h.owner.csk.init()
386-
387-
h.gmm = memsys.PageMM()
388-
h.gmm.RegWithHK()
389-
h.smm = memsys.ByteMM()
390-
h.smm.RegWithHK()
391-
392-
hk.Reg("rate-limit"+hk.NameSuffix, h.ratelim.housekeep, hk.PruneRateLimiters)
393-
}
394-
395-
// steps 1 thru 4
396-
func (h *htrun) initSnode(config *cmn.Config) {
344+
// resolve node networking and initialize Snode (steps 1 thru 4); in particular:
345+
// - pick addresses
346+
// - decide effective IP family
347+
// - initialize effective networking state (do not mutate config)
348+
// - init net servers/muxers
349+
// see also: docs/networking.md
350+
func (h *htrun) initPhase1(config *cmn.Config) {
397351
var (
398352
pubAddr meta.NetInfo
399353
pubExtra []meta.NetInfo
@@ -530,6 +484,30 @@ func (h *htrun) initSnode(config *cmn.Config) {
530484
copy(h.si.PubExtra, pubExtra)
531485
nlog.Infof("%s (multihome) access: %v and %v", cmn.NetPublic, pubAddr, h.si.PubExtra)
532486
}
487+
488+
tcpbuf := config.Net.L4.SndRcvBufSize
489+
if h.si.IsProxy() {
490+
tcpbuf = 0
491+
} else if tcpbuf == 0 {
492+
tcpbuf = cmn.DefaultSndRcvBufferSize // ditto: targets use AIS default when not configured
493+
}
494+
495+
// pub-net first
496+
muxers := newMuxers(tracing.IsEnabled())
497+
g.netServ.pub = &netServer{muxers: muxers, sndRcvBufSize: tcpbuf, useIPv6: useIPv6}
498+
499+
// intra-control and intra-data
500+
// note: separate config and isolated bandwidth - strongly recommended
501+
g.netServ.control = g.netServ.pub
502+
if config.HostNet.UseIntraControl {
503+
muxers = newMuxers(false /*enableTracing*/)
504+
g.netServ.control = &netServer{muxers: muxers, sndRcvBufSize: 0, lowLatencyToS: true, useIPv6: useIPv6}
505+
}
506+
g.netServ.data = g.netServ.control // if not configured, intra-data net is intra-control
507+
if config.HostNet.UseIntraData {
508+
muxers = newMuxers(false /*enableTracing*/)
509+
g.netServ.data = &netServer{muxers: muxers, sndRcvBufSize: tcpbuf, useIPv6: useIPv6}
510+
}
533511
}
534512

535513
func mustDiffer(ip1 meta.NetInfo, port1 int, use1 bool, ip2 meta.NetInfo, port2 int, use2 bool, tag string) {
@@ -541,6 +519,39 @@ func mustDiffer(ip1 meta.NetInfo, port1 int, use1 bool, ip2 meta.NetInfo, port2
541519
}
542520
}
543521

522+
// phase2 init (part of the Run()):
523+
// - TLS/clients
524+
// - metadata owners (singletons)
525+
// - cluster key
526+
// - housekeep: memsys; rate-limit-prune
527+
func (h *htrun) initPhase2(config *cmn.Config) {
528+
debug.Assert(g.netServ.control != nil && g.netServ.data != nil && g.netServ.pub != nil) // (phase1 above)
529+
530+
// before newTLS() below & before intra-cluster clients
531+
if config.Net.HTTP.UseHTTPS {
532+
if err := certloader.Init(config.Net.HTTP.Certificate, config.Net.HTTP.CertKey, h.statsT); err != nil {
533+
cos.ExitLog(err)
534+
}
535+
}
536+
537+
initCtrlClient(config, g.netServ.control.useIPv6)
538+
initDataClient(config, g.netServ.data.useIPv6)
539+
540+
load.Init()
541+
542+
h.owner.smap = newSmapOwner(config)
543+
h.owner.rmd = newRMDOwner(config)
544+
h.owner.rmd.load()
545+
h.owner.csk.init()
546+
547+
h.gmm = memsys.PageMM()
548+
h.gmm.RegWithHK()
549+
h.smm = memsys.ByteMM()
550+
h.smm.RegWithHK()
551+
552+
hk.Reg("rate-limit"+hk.NameSuffix, h.ratelim.housekeep, hk.PruneRateLimiters)
553+
}
554+
544555
// at startup, check this Snode vs locally stored Smap replica (NOTE: some errors are FATAL)
545556
func (h *htrun) loadSmap() (smap *smapX, reliable bool) {
546557
smap = newSmap()

ais/http.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func handleData(path string, handler func(http.ResponseWriter, *http.Request)) {
5454
}
5555
}
5656

57-
func initCtrlClient(config *cmn.Config) {
57+
func initCtrlClient(config *cmn.Config, useIPv6 bool) {
5858
const (
5959
defaultControlWriteBufferSize = 16 * cos.KiB // for more defaults see cmn/network.go
6060
defaultControlReadBufferSize = 16 * cos.KiB
@@ -67,7 +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,
70+
UseIPv6: useIPv6,
7171
}
7272
if config.Net.HTTP.UseHTTPS {
7373
g.client.control = cmn.NewIntraClientTLS(cargs, config)
@@ -77,7 +77,7 @@ func initCtrlClient(config *cmn.Config) {
7777
}
7878

7979
// wbuf/rbuf - when not configured use AIS defaults (to override the usual 4KB)
80-
func initDataClient(config *cmn.Config) {
80+
func initDataClient(config *cmn.Config, useIPv6 bool) {
8181
wbuf, rbuf := config.Net.HTTP.WriteBufferSize, config.Net.HTTP.ReadBufferSize
8282
if wbuf == 0 {
8383
wbuf = cmn.DefaultWriteBufferSize
@@ -92,15 +92,17 @@ func initDataClient(config *cmn.Config) {
9292
IdleConnTimeout: config.Net.HTTP.IdleConnTimeout.D(),
9393
IdleConnsPerHost: config.Net.HTTP.MaxIdleConnsPerHost,
9494
MaxIdleConns: config.Net.HTTP.MaxIdleConns,
95+
UseIPv6: useIPv6,
9596
}
9697
if config.Net.HTTP.UseHTTPS {
9798
g.client.data = cmn.NewIntraClientTLS(cargs, config)
9899
} else {
99100
g.client.data = cmn.NewClient(cargs)
100101
}
101102

102-
// The g.client.data is used for the AWS MPT/presigned URL features.
103-
// Enable tracing on the data client to capture traces for related AWS client calls.
103+
// TODO:
104+
// tracing policy for intra-cluster HTTP (control and data, both)
105+
// should be unified; transport streams (and data movers) - are separate
104106
g.client.data = tracing.NewTraceableClient(g.client.data)
105107
}
106108

ais/proxy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ var _ cos.Runner = (*proxy)(nil)
8383
func (*proxy) Name() string { return apc.Proxy } // as cos.Runner
8484

8585
func (p *proxy) init(config *cmn.Config) {
86-
p.initSnode(config)
86+
p.initPhase1(config)
8787

8888
// (a) get node ID from command-line or env var (see envDaemonID())
8989
// (b) load existing ID from config file stored under local config `confdir` (compare w/ target)
@@ -184,7 +184,7 @@ func (p *proxy) pready(smap *smapX, withRR bool /* also check readiness to rebal
184184
// start proxy runner
185185
func (p *proxy) Run() error {
186186
config := cmn.GCO.Get()
187-
p.htrun.init(config)
187+
p.htrun.initPhase2(config)
188188
p.setusr1()
189189
p.owner.bmd = newBMDOwnerPrx(config)
190190
p.owner.etl = newEtlMDOwnerPrx(config)

ais/prxauth.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ const (
8787
/////////////////
8888

8989
func newAuthManager(config *cmn.Config, statsT stats.Tracker) *authManager {
90+
debug.Assert(g.netServ.pub != nil)
91+
9092
rootCtx, rootCancel := context.WithCancel(context.Background())
9193
keyCacheClient := newKeyCacheClient(config, statsT)
9294
keyCacheManager := tok.NewKeyCacheManager(config.Auth.OIDC, keyCacheClient, nil, statsT)
@@ -131,7 +133,7 @@ func newKeyCacheClient(config *cmn.Config, statsT stats.Tracker) *http.Client {
131133
Timeout: KeyCacheTimeout,
132134
IdleConnsPerHost: KeyCacheIdleConnsPerHost,
133135
MaxIdleConns: maxIdleConns,
134-
UseIPv6: config.Net.UseIPv6,
136+
UseIPv6: g.netServ.pub.useIPv6,
135137
}
136138
client := cmn.NewClientTLS(transport, tls, false)
137139

ais/prxrev.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +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,
232+
UseIPv6: g.netServ.control.useIPv6,
233233
})
234234
)
235235
if config.Net.HTTP.UseHTTPS {

ais/target.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ func (t *target) aisbp() *backend.AISbp {
251251
//
252252

253253
func (t *target) init(config *cmn.Config) {
254-
t.initSnode(config)
254+
t.initPhase1(config)
255255

256256
// (a) get node ID from command-line or env var (see envDaemonID())
257257
// (b) load existing node ID (replicated xattr at roots of respective mountpaths)
@@ -376,7 +376,7 @@ func (t *target) Run() error {
376376
cos.ExitLog(err)
377377
}
378378
config := cmn.GCO.Get()
379-
t.htrun.init(config)
379+
t.htrun.initPhase2(config)
380380
t.setusr1()
381381

382382
core.Tinit(t, config, true /*run hk*/)

ais/tgtobj_internal_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Package ais provides AIStore's proxy and target nodes.
22
/*
3-
* Copyright (c) 2018-2025, NVIDIA CORPORATION. All rights reserved.
3+
* Copyright (c) 2018-2026, NVIDIA CORPORATION. All rights reserved.
44
*/
55
package ais
66

@@ -65,13 +65,13 @@ func TestMain(m *testing.M) {
6565
config.Log.Level = "3"
6666
co := newConfigOwner(config)
6767
t = newTarget(co)
68-
t.initSnode(config)
68+
t.initPhase1(config)
6969
tid, _ := initTID(config)
7070
t.si.Init(tid, apc.Target)
7171

7272
fs.Add(testMountpath, t.SID())
7373

74-
t.htrun.init(config)
74+
t.htrun.initPhase2(config)
7575
t.ups.t = t
7676

7777
t.statsT = mock.NewStatsTracker()

0 commit comments

Comments
 (0)