Skip to content

Commit 526b0b6

Browse files
committed
control/controlclient: start simplifying netmap fetch APIs
Step 1 of many, cleaning up the direct/auto client & restarting map requests that leads to all the unnecessary map requests. Updates tailscale/corp#5761 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
1 parent 467eb2e commit 526b0b6

File tree

2 files changed

+29
-19
lines changed

2 files changed

+29
-19
lines changed

control/controlclient/auto.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ func (g *LoginGoal) sendLogoutError(err error) {
4141
}
4242
}
4343

44+
var _ Client = (*Auto)(nil)
45+
4446
// Auto connects to a tailcontrol server for a node.
4547
// It's a concrete implementation of the Client interface.
4648
type Auto struct {
@@ -462,7 +464,7 @@ func (c *Auto) mapRoutine() {
462464
c.mu.Unlock()
463465
health.SetInPollNetMap(false)
464466

465-
err := c.direct.PollNetMap(ctx, -1, func(nm *netmap.NetworkMap) {
467+
err := c.direct.PollNetMap(ctx, func(nm *netmap.NetworkMap) {
466468
health.SetInPollNetMap(true)
467469
c.mu.Lock()
468470

control/controlclient/direct.go

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -620,18 +620,27 @@ func inTest() bool { return flag.Lookup("test.v") != nil }
620620

621621
// PollNetMap makes a /map request to download the network map, calling cb with
622622
// each new netmap.
623-
//
624-
// maxPolls is how many network maps to download; common values are 1
625-
// or -1 (to keep a long-poll query open to the server).
626-
func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*netmap.NetworkMap)) error {
627-
return c.sendMapRequest(ctx, maxPolls, cb)
623+
func (c *Direct) PollNetMap(ctx context.Context, cb func(*netmap.NetworkMap)) error {
624+
return c.sendMapRequest(ctx, -1, false, cb)
625+
}
626+
627+
// FetchNetMap fetches the netmap once.
628+
func (c *Direct) FetchNetMap(ctx context.Context) (*netmap.NetworkMap, error) {
629+
var ret *netmap.NetworkMap
630+
err := c.sendMapRequest(ctx, 1, false, func(nm *netmap.NetworkMap) {
631+
ret = nm
632+
})
633+
if err == nil && ret == nil {
634+
return nil, errors.New("[unexpected] sendMapRequest success without callback")
635+
}
636+
return ret, err
628637
}
629638

630639
// SendLiteMapUpdate makes a /map request to update the server of our latest state,
631640
// but does not fetch anything. It returns an error if the server did not return a
632641
// successful 200 OK response.
633642
func (c *Direct) SendLiteMapUpdate(ctx context.Context) error {
634-
return c.sendMapRequest(ctx, 1, nil)
643+
return c.sendMapRequest(ctx, 1, false, nil)
635644
}
636645

637646
// If we go more than pollTimeout without hearing from the server,
@@ -640,7 +649,7 @@ func (c *Direct) SendLiteMapUpdate(ctx context.Context) error {
640649
const pollTimeout = 120 * time.Second
641650

642651
// cb nil means to omit peers.
643-
func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netmap.NetworkMap)) error {
652+
func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, readOnly bool, cb func(*netmap.NetworkMap)) error {
644653
metricMapRequests.Add(1)
645654
metricMapRequestsActive.Add(1)
646655
defer metricMapRequestsActive.Add(-1)
@@ -703,6 +712,16 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netm
703712
Hostinfo: hi,
704713
DebugFlags: c.debugFlags,
705714
OmitPeers: cb == nil,
715+
716+
// On initial startup before we know our endpoints, set the ReadOnly flag
717+
// to tell the control server not to distribute out our (empty) endpoints to peers.
718+
// Presumably we'll learn our endpoints in a half second and do another post
719+
// with useful results. The first POST just gets us the DERP map which we
720+
// need to do the STUN queries to discover our endpoints.
721+
// TODO(bradfitz): we skip this optimization in tests, though,
722+
// because the e2e tests are currently hyperspecific about the
723+
// ordering of things. The e2e tests need love.
724+
ReadOnly: readOnly || (len(epStrs) == 0 && !everEndpoints && !inTest()),
706725
}
707726
var extraDebugFlags []string
708727
if hi != nil && c.linkMon != nil && !c.skipIPForwardingCheck &&
@@ -725,17 +744,6 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netm
725744
if c.newDecompressor != nil {
726745
request.Compress = "zstd"
727746
}
728-
// On initial startup before we know our endpoints, set the ReadOnly flag
729-
// to tell the control server not to distribute out our (empty) endpoints to peers.
730-
// Presumably we'll learn our endpoints in a half second and do another post
731-
// with useful results. The first POST just gets us the DERP map which we
732-
// need to do the STUN queries to discover our endpoints.
733-
// TODO(bradfitz): we skip this optimization in tests, though,
734-
// because the e2e tests are currently hyperspecific about the
735-
// ordering of things. The e2e tests need love.
736-
if len(epStrs) == 0 && !everEndpoints && !inTest() {
737-
request.ReadOnly = true
738-
}
739747

740748
bodyData, err := encode(request, serverKey, serverNoiseKey, machinePrivKey)
741749
if err != nil {

0 commit comments

Comments
 (0)