From b8edb7a5e9731d399dbb48960e45f204a34ab298 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 25 Jun 2020 10:47:33 -0700 Subject: [PATCH] control/controlclient: add Debug field to NetworkMap As part of disabling background STUN packets when idle, we want an emergency override switch to turn it back on, in case it interacts poorly in the wild. We'll send that via control, but we'll want to plumb it down to magicsock via NetworkMap. Updates tailscale/corp#320 Signed-off-by: Brad Fitzpatrick --- control/controlclient/direct.go | 1 + control/controlclient/netmap.go | 17 +++++-- control/controlclient/netmap_test.go | 72 +++++++++++++++++++++------- 3 files changed, 69 insertions(+), 21 deletions(-) diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 3ffeaba87..8346b59a7 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -620,6 +620,7 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM Hostinfo: resp.Node.Hostinfo, PacketFilter: c.parsePacketFilter(resp.PacketFilter), DERPMap: lastDERPMap, + Debug: resp.Debug, } for _, profile := range resp.UserProfiles { nm.UserProfiles[profile.ID] = profile diff --git a/control/controlclient/netmap.go b/control/controlclient/netmap.go index 71c00f90c..0556a25e4 100644 --- a/control/controlclient/netmap.go +++ b/control/controlclient/netmap.go @@ -39,6 +39,9 @@ type NetworkMap struct { // between updates and should not be modified. DERPMap *tailcfg.DERPMap + // Debug knobs from control server for debug or feature gating. + Debug *tailcfg.Debug + // ACLs User tailcfg.UserID @@ -70,9 +73,17 @@ func (nm NetworkMap) String() string { func (nm *NetworkMap) Concise() string { buf := new(strings.Builder) - fmt.Fprintf(buf, "netmap: self: %v auth=%v :%v %v\n", - nm.NodeKey.ShortString(), nm.MachineStatus, - nm.LocalPort, nm.Addresses) + fmt.Fprintf(buf, "netmap: self: %v auth=%v", + nm.NodeKey.ShortString(), nm.MachineStatus) + if nm.LocalPort != 0 { + fmt.Fprintf(buf, " port=%v", nm.LocalPort) + } + if nm.Debug != nil { + j, _ := json.Marshal(nm.Debug) + fmt.Fprintf(buf, " debug=%s", j) + } + fmt.Fprintf(buf, " %v", nm.Addresses) + buf.WriteByte('\n') for _, p := range nm.Peers { aip := make([]string, len(p.AllowedIPs)) for i, a := range p.AllowedIPs { diff --git a/control/controlclient/netmap_test.go b/control/controlclient/netmap_test.go index 93f511b75..d9c23b93c 100644 --- a/control/controlclient/netmap_test.go +++ b/control/controlclient/netmap_test.go @@ -11,26 +11,62 @@ import ( ) func TestNetworkMapConcise(t *testing.T) { - nm := &NetworkMap{ - Peers: []*tailcfg.Node{ - { - Name: "foo", - Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"}, + nodekey := func(b byte) (ret tailcfg.NodeKey) { + for i := range ret { + ret[i] = b + } + return + } + for _, tt := range []struct { + name string + nm *NetworkMap + want string + }{ + { + name: "basic", + nm: &NetworkMap{ + NodeKey: nodekey(1), + Peers: []*tailcfg.Node{ + { + Key: nodekey(2), + DERP: "127.3.3.40:2", + Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"}, + }, + { + Key: nodekey(3), + DERP: "127.3.3.40:4", + Endpoints: []string{"10.2.0.100:12", "10.1.0.100:12345"}, + }, + }, }, - { - Name: "bar", - Endpoints: []string{"10.2.0.100:12", "10.1.0.100:12345"}, + want: "netmap: self: [AQEBA] auth=machine-unknown []\n [AgICA] D2 : 192.168.0.100:12 192.168.0.100:12354\n [AwMDA] D4 : 10.2.0.100:12 10.1.0.100:12345\n", + }, + { + name: "debug_non_nil", + nm: &NetworkMap{ + NodeKey: nodekey(1), + Debug: &tailcfg.Debug{}, }, + want: "netmap: self: [AQEBA] auth=machine-unknown debug={} []\n", }, - } - var got string - n := int(testing.AllocsPerRun(1000, func() { - got = nm.Concise() - })) - t.Logf("Allocs = %d", n) - want := "netmap: self: [AAAAA] auth=machine-unknown :0 []\n" + - " [AAAAA] : 192.168.0.100:12 192.168.0.100:12354\n [AAAAA] : 10.2.0.100:12 10.1.0.100:12345\n" - if got != want { - t.Errorf("Wrong output\n Got: %q\nWant: %q\n## Got (unescaped):\n%s\n## Want (unescaped):\n%s\n", got, want, got, want) + { + name: "debug_values", + nm: &NetworkMap{ + NodeKey: nodekey(1), + Debug: &tailcfg.Debug{LogHeapPprof: true}, + }, + want: "netmap: self: [AQEBA] auth=machine-unknown debug={\"LogHeapPprof\":true} []\n", + }, + } { + t.Run(tt.name, func(t *testing.T) { + var got string + n := int(testing.AllocsPerRun(1000, func() { + got = tt.nm.Concise() + })) + t.Logf("Allocs = %d", n) + if got != tt.want { + t.Errorf("Wrong output\n Got: %q\nWant: %q\n## Got (unescaped):\n%s\n## Want (unescaped):\n%s\n", got, tt.want, got, tt.want) + } + }) } }