From c21a3c47333f5d990569861e826bc6be15b46e40 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Thu, 27 Oct 2022 14:14:18 -0700 Subject: [PATCH] types/netlogtype: new package for network logging types (#6092) The netlog.Message type is useful to depend on from other packages, but doing so would transitively cause gvisor and other large packages to be linked in. Avoid this problem by moving all network logging types to a single package. We also update staticcheck to take in: https://github.com/dominikh/go-tools/commit/003d277bcf3bcc320b9fddf720cd0d49e0bfb782 Signed-off-by: Joe Tsai --- cmd/netlogfmt/main.go | 14 ++++---- cmd/tailscaled/depaware.txt | 3 +- go.mod | 2 +- go.sum | 4 +-- net/tstun/wrap.go | 4 +-- net/tstun/wrap_test.go | 13 ++++---- net/tunstats/stats.go | 39 +++++++---------------- net/tunstats/stats_test.go | 22 ++++++------- types/netlogtype/netlogtype.go | 58 ++++++++++++++++++++++++++++++++++ wgengine/netlog/logger.go | 39 +++++++---------------- wgengine/netlog/logger_test.go | 5 ++- 11 files changed, 112 insertions(+), 91 deletions(-) create mode 100644 types/netlogtype/netlogtype.go diff --git a/cmd/netlogfmt/main.go b/cmd/netlogfmt/main.go index 06bfc1b18..b89520b5c 100644 --- a/cmd/netlogfmt/main.go +++ b/cmd/netlogfmt/main.go @@ -39,10 +39,8 @@ import ( "golang.org/x/exp/maps" "golang.org/x/exp/slices" - "tailscale.com/net/flowtrack" - "tailscale.com/net/tunstats" + "tailscale.com/types/netlogtype" "tailscale.com/util/must" - "tailscale.com/wgengine/netlog" ) var ( @@ -62,7 +60,7 @@ func main() { Logtail struct { ID string `json:"id"` } `json:"logtail"` - netlog.Message + netlogtype.Message } if err := dec.Decode(&msg); err != nil { if err == io.EOF { @@ -77,16 +75,16 @@ func main() { // Construct a table of network traffic per connection. rows := [][7]string{{3: "Tx[P/s]", 4: "Tx[B/s]", 5: "Rx[P/s]", 6: "Rx[B/s]"}} duration := msg.End.Sub(msg.Start) - addRows := func(heading string, traffic []netlog.TupleCounts) { + addRows := func(heading string, traffic []netlogtype.ConnectionCounts) { if len(traffic) == 0 { return } - slices.SortFunc(traffic, func(x, y netlog.TupleCounts) bool { + slices.SortFunc(traffic, func(x, y netlogtype.ConnectionCounts) bool { nx := x.TxPackets + x.TxBytes + x.RxPackets + x.RxBytes ny := y.TxPackets + y.TxBytes + y.RxPackets + y.RxBytes return nx > ny }) - var sum tunstats.Counts + var sum netlogtype.Counts for _, cc := range traffic { sum = sum.Add(cc.Counts) } @@ -97,7 +95,7 @@ func main() { 5: formatSI(float64(sum.RxPackets) / duration.Seconds()), 6: formatIEC(float64(sum.RxBytes) / duration.Seconds()), }) - if len(traffic) == 1 && traffic[0].Tuple == (flowtrack.Tuple{}) { + if len(traffic) == 1 && traffic[0].Connection.IsZero() { return // this is already a summary counts } formatAddrPort := func(a netip.AddrPort) string { diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 88ec65e4d..58032b196 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -240,7 +240,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/net/tsdial from tailscale.com/control/controlclient+ 💣 tailscale.com/net/tshttpproxy from tailscale.com/control/controlclient+ tailscale.com/net/tstun from tailscale.com/net/dns+ - tailscale.com/net/tunstats from tailscale.com/net/tstun+ + tailscale.com/net/tunstats from tailscale.com/net/tstun tailscale.com/net/wsconn from tailscale.com/control/controlhttp+ tailscale.com/paths from tailscale.com/ipn/ipnlocal+ 💣 tailscale.com/portlist from tailscale.com/ipn/ipnlocal @@ -262,6 +262,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/types/ipproto from tailscale.com/net/flowtrack+ tailscale.com/types/key from tailscale.com/control/controlbase+ tailscale.com/types/logger from tailscale.com/control/controlclient+ + tailscale.com/types/netlogtype from tailscale.com/net/tstun+ tailscale.com/types/netmap from tailscale.com/control/controlclient+ tailscale.com/types/nettype from tailscale.com/wgengine/magicsock+ tailscale.com/types/opt from tailscale.com/control/controlclient+ diff --git a/go.mod b/go.mod index a7bc9ebc3..3ce2e0cda 100644 --- a/go.mod +++ b/go.mod @@ -67,7 +67,7 @@ require ( golang.zx2c4.com/wireguard v0.0.0-20220904105730-b51010ba13f0 golang.zx2c4.com/wireguard/windows v0.5.3 gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5 - honnef.co/go/tools v0.4.0-0.dev.0.20220404092545-59d7a2877f83 + honnef.co/go/tools v0.4.0-0.dev.0.20220517111757-f4a2f64ce238 inet.af/peercred v0.0.0-20210906144145-0893ea02156a inet.af/wf v0.0.0-20220728202103-50d96caab2f6 nhooyr.io/websocket v1.8.7 diff --git a/go.sum b/go.sum index ccac75d61..5a8af70e0 100644 --- a/go.sum +++ b/go.sum @@ -1829,8 +1829,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY= honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= -honnef.co/go/tools v0.4.0-0.dev.0.20220404092545-59d7a2877f83 h1:lZ9GIYaU+o5+X6ST702I/Ntyq9Y2oIMZ42rBQpem64A= -honnef.co/go/tools v0.4.0-0.dev.0.20220404092545-59d7a2877f83/go.mod h1:vlRD9XErLMGT+mDuofSr0mMMquscM/1nQqtRSsh6m70= +honnef.co/go/tools v0.4.0-0.dev.0.20220517111757-f4a2f64ce238 h1:8Vr1KP9OTjoKQSSeLefzibQgDV4s2ujJElKHqMi7nsA= +honnef.co/go/tools v0.4.0-0.dev.0.20220517111757-f4a2f64ce238/go.mod h1:DCQzo6aCmhYDJH+We7BIU38vNvVkaOKa6s57pewKdvI= howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= diff --git a/net/tstun/wrap.go b/net/tstun/wrap.go index c730c8272..ebb09ed6e 100644 --- a/net/tstun/wrap.go +++ b/net/tstun/wrap.go @@ -22,7 +22,6 @@ import ( "golang.zx2c4.com/wireguard/tun" "gvisor.dev/gvisor/pkg/tcpip/stack" "tailscale.com/disco" - "tailscale.com/net/flowtrack" "tailscale.com/net/packet" "tailscale.com/net/tsaddr" "tailscale.com/net/tunstats" @@ -31,6 +30,7 @@ import ( "tailscale.com/types/ipproto" "tailscale.com/types/key" "tailscale.com/types/logger" + "tailscale.com/types/netlogtype" "tailscale.com/util/clientmetric" "tailscale.com/wgengine/filter" ) @@ -853,7 +853,7 @@ func (t *Wrapper) SetStatisticsEnabled(enable bool) { // ExtractStatistics extracts and resets the counters for all active connections. // It must be called periodically otherwise the memory used is unbounded. -func (t *Wrapper) ExtractStatistics() map[flowtrack.Tuple]tunstats.Counts { +func (t *Wrapper) ExtractStatistics() map[netlogtype.Connection]netlogtype.Counts { return t.stats.Extract() } diff --git a/net/tstun/wrap_test.go b/net/tstun/wrap_test.go index bdcd9e39c..18acf3ba1 100644 --- a/net/tstun/wrap_test.go +++ b/net/tstun/wrap_test.go @@ -19,15 +19,14 @@ import ( "go4.org/netipx" "golang.zx2c4.com/wireguard/tun/tuntest" "tailscale.com/disco" - "tailscale.com/net/flowtrack" "tailscale.com/net/netaddr" "tailscale.com/net/packet" - "tailscale.com/net/tunstats" "tailscale.com/tstest" "tailscale.com/tstime/mono" "tailscale.com/types/ipproto" "tailscale.com/types/key" "tailscale.com/types/logger" + "tailscale.com/types/netlogtype" "tailscale.com/wgengine/filter" ) @@ -379,17 +378,17 @@ func TestFilter(t *testing.T) { } got := tun.ExtractStatistics() - want := map[flowtrack.Tuple]tunstats.Counts{} + want := map[netlogtype.Connection]netlogtype.Counts{} if !tt.drop { var p packet.Parsed p.Decode(tt.data) switch tt.dir { case in: - tuple := flowtrack.Tuple{Proto: ipproto.UDP, Src: p.Dst, Dst: p.Src} - want[tuple] = tunstats.Counts{RxPackets: 1, RxBytes: uint64(len(tt.data))} + conn := netlogtype.Connection{Proto: ipproto.UDP, Src: p.Dst, Dst: p.Src} + want[conn] = netlogtype.Counts{RxPackets: 1, RxBytes: uint64(len(tt.data))} case out: - tuple := flowtrack.Tuple{Proto: ipproto.UDP, Src: p.Src, Dst: p.Dst} - want[tuple] = tunstats.Counts{TxPackets: 1, TxBytes: uint64(len(tt.data))} + conn := netlogtype.Connection{Proto: ipproto.UDP, Src: p.Src, Dst: p.Dst} + want[conn] = netlogtype.Counts{TxPackets: 1, TxBytes: uint64(len(tt.data))} } } if !reflect.DeepEqual(got, want) { diff --git a/net/tunstats/stats.go b/net/tunstats/stats.go index d2e17cd96..597ca9f6e 100644 --- a/net/tunstats/stats.go +++ b/net/tunstats/stats.go @@ -9,8 +9,8 @@ package tunstats import ( "sync" - "tailscale.com/net/flowtrack" "tailscale.com/net/packet" + "tailscale.com/types/netlogtype" ) // Statistics maintains counters for every connection. @@ -18,36 +18,19 @@ import ( // The zero value is ready for use. type Statistics struct { mu sync.Mutex - m map[flowtrack.Tuple]Counts -} - -// Counts are statistics about a particular connection. -type Counts struct { - TxPackets uint64 `json:"txPkts,omitempty"` - TxBytes uint64 `json:"txBytes,omitempty"` - RxPackets uint64 `json:"rxPkts,omitempty"` - RxBytes uint64 `json:"rxBytes,omitempty"` -} - -// Add adds the counts from both c1 and c2. -func (c1 Counts) Add(c2 Counts) Counts { - c1.TxPackets += c2.TxPackets - c1.TxBytes += c2.TxBytes - c1.RxPackets += c2.RxPackets - c1.RxBytes += c2.RxBytes - return c1 + m map[netlogtype.Connection]netlogtype.Counts } // UpdateTx updates the counters for a transmitted IP packet // The source and destination of the packet directly correspond with -// the source and destination in flowtrack.Tuple. +// the source and destination in netlogtype.Connection. func (s *Statistics) UpdateTx(b []byte) { s.update(b, false) } // UpdateRx updates the counters for a received IP packet. // The source and destination of the packet are inverted with respect to -// the source and destination in flowtrack.Tuple. +// the source and destination in netlogtype.Connection. func (s *Statistics) UpdateRx(b []byte) { s.update(b, true) } @@ -55,17 +38,17 @@ func (s *Statistics) UpdateRx(b []byte) { func (s *Statistics) update(b []byte, receive bool) { var p packet.Parsed p.Decode(b) - tuple := flowtrack.Tuple{Proto: p.IPProto, Src: p.Src, Dst: p.Dst} + conn := netlogtype.Connection{Proto: p.IPProto, Src: p.Src, Dst: p.Dst} if receive { - tuple.Src, tuple.Dst = tuple.Dst, tuple.Src + conn.Src, conn.Dst = conn.Dst, conn.Src } s.mu.Lock() defer s.mu.Unlock() if s.m == nil { - s.m = make(map[flowtrack.Tuple]Counts) + s.m = make(map[netlogtype.Connection]netlogtype.Counts) } - cnts := s.m[tuple] + cnts := s.m[conn] if receive { cnts.RxPackets++ cnts.RxBytes += uint64(len(b)) @@ -73,15 +56,15 @@ func (s *Statistics) update(b []byte, receive bool) { cnts.TxPackets++ cnts.TxBytes += uint64(len(b)) } - s.m[tuple] = cnts + s.m[conn] = cnts } // Extract extracts and resets the counters for all active connections. // It must be called periodically otherwise the memory used is unbounded. -func (s *Statistics) Extract() map[flowtrack.Tuple]Counts { +func (s *Statistics) Extract() map[netlogtype.Connection]netlogtype.Counts { s.mu.Lock() defer s.mu.Unlock() m := s.m - s.m = make(map[flowtrack.Tuple]Counts) + s.m = make(map[netlogtype.Connection]netlogtype.Counts) return m } diff --git a/net/tunstats/stats_test.go b/net/tunstats/stats_test.go index ce9a37d1d..1e73ce441 100644 --- a/net/tunstats/stats_test.go +++ b/net/tunstats/stats_test.go @@ -15,8 +15,8 @@ import ( "time" qt "github.com/frankban/quicktest" - "tailscale.com/net/flowtrack" "tailscale.com/types/ipproto" + "tailscale.com/types/netlogtype" ) func testPacketV4(proto ipproto.Proto, srcAddr, dstAddr [4]byte, srcPort, dstPort, size uint16) (out []byte) { @@ -48,17 +48,17 @@ func TestConcurrent(t *testing.T) { c := qt.New(t) var stats Statistics - var wants []map[flowtrack.Tuple]Counts - gots := make([]map[flowtrack.Tuple]Counts, runtime.NumCPU()) + var wants []map[netlogtype.Connection]netlogtype.Counts + gots := make([]map[netlogtype.Connection]netlogtype.Counts, runtime.NumCPU()) var group sync.WaitGroup for i := range gots { group.Add(1) go func(i int) { defer group.Done() - gots[i] = make(map[flowtrack.Tuple]Counts) + gots[i] = make(map[netlogtype.Connection]netlogtype.Counts) rn := rand.New(rand.NewSource(time.Now().UnixNano())) var p []byte - var t flowtrack.Tuple + var t netlogtype.Connection for j := 0; j < 1000; j++ { delay := rn.Intn(10000) if p == nil || rn.Intn(64) == 0 { @@ -72,7 +72,7 @@ func TestConcurrent(t *testing.T) { dstPort := uint16(rand.Intn(16)) size := uint16(64 + rand.Intn(1024)) p = testPacketV4(proto, srcAddr.As4(), dstAddr.As4(), srcPort, dstPort, size) - t = flowtrack.Tuple{Proto: proto, Src: netip.AddrPortFrom(srcAddr, srcPort), Dst: netip.AddrPortFrom(dstAddr, dstPort)} + t = netlogtype.Connection{Proto: proto, Src: netip.AddrPortFrom(srcAddr, srcPort), Dst: netip.AddrPortFrom(dstAddr, dstPort)} } t2 := t receive := rn.Intn(2) == 0 @@ -102,17 +102,17 @@ func TestConcurrent(t *testing.T) { group.Wait() wants = append(wants, stats.Extract()) - got := make(map[flowtrack.Tuple]Counts) - want := make(map[flowtrack.Tuple]Counts) + got := make(map[netlogtype.Connection]netlogtype.Counts) + want := make(map[netlogtype.Connection]netlogtype.Counts) mergeMaps(got, gots...) mergeMaps(want, wants...) c.Assert(got, qt.DeepEquals, want) } -func mergeMaps(dst map[flowtrack.Tuple]Counts, srcs ...map[flowtrack.Tuple]Counts) { +func mergeMaps(dst map[netlogtype.Connection]netlogtype.Counts, srcs ...map[netlogtype.Connection]netlogtype.Counts) { for _, src := range srcs { - for tuple, cnts := range src { - dst[tuple] = dst[tuple].Add(cnts) + for conn, cnts := range src { + dst[conn] = dst[conn].Add(cnts) } } } diff --git a/types/netlogtype/netlogtype.go b/types/netlogtype/netlogtype.go new file mode 100644 index 000000000..c0f985eef --- /dev/null +++ b/types/netlogtype/netlogtype.go @@ -0,0 +1,58 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package netlogtype defines types for network logging. +package netlogtype + +import ( + "net/netip" + "time" + + "tailscale.com/types/ipproto" +) + +// Message is the log message that captures network traffic. +type Message struct { + Start time.Time `json:"start"` // inclusive + End time.Time `json:"end"` // inclusive + + VirtualTraffic []ConnectionCounts `json:"virtualTraffic,omitempty"` + SubnetTraffic []ConnectionCounts `json:"subnetTraffic,omitempty"` + ExitTraffic []ConnectionCounts `json:"exitTraffic,omitempty"` + PhysicalTraffic []ConnectionCounts `json:"physicalTraffic,omitempty"` +} + +// ConnectionCounts is a flattened struct of both a connection and counts. +type ConnectionCounts struct { + Connection + Counts +} + +// Connection is a 5-tuple of proto, source and destination IP and port. +type Connection struct { + Proto ipproto.Proto `json:"proto,omitzero,omitempty"` + Src netip.AddrPort `json:"src,omitzero"` + Dst netip.AddrPort `json:"dst,omitzero"` +} + +func (c Connection) IsZero() bool { return c == Connection{} } + +// Counts are statistics about a particular connection. +type Counts struct { + TxPackets uint64 `json:"txPkts,omitzero,omitempty"` + TxBytes uint64 `json:"txBytes,omitzero,omitempty"` + RxPackets uint64 `json:"rxPkts,omitzero,omitempty"` + RxBytes uint64 `json:"rxBytes,omitzero,omitempty"` +} + +func (c Counts) IsZero() bool { return c == Counts{} } + +// Add adds the counts from both c1 and c2. +func (c1 Counts) Add(c2 Counts) Counts { + c1.TxPackets += c2.TxPackets + c1.TxBytes += c2.TxBytes + c1.RxPackets += c2.RxPackets + c1.RxBytes += c2.RxBytes + return c1 +} diff --git a/wgengine/netlog/logger.go b/wgengine/netlog/logger.go index 2d0284b2a..f0e6ee4f7 100644 --- a/wgengine/netlog/logger.go +++ b/wgengine/netlog/logger.go @@ -20,10 +20,9 @@ import ( "golang.org/x/sync/errgroup" "tailscale.com/logpolicy" "tailscale.com/logtail" - "tailscale.com/net/flowtrack" "tailscale.com/net/tsaddr" - "tailscale.com/net/tunstats" "tailscale.com/smallzstd" + "tailscale.com/types/netlogtype" "tailscale.com/wgengine/router" ) @@ -36,29 +35,13 @@ const pollPeriod = 5 * time.Second // TODO(joetsai): Make *magicsock.Conn implement this interface. type Device interface { SetStatisticsEnabled(bool) - ExtractStatistics() map[flowtrack.Tuple]tunstats.Counts + ExtractStatistics() map[netlogtype.Connection]netlogtype.Counts } type noopDevice struct{} -func (noopDevice) SetStatisticsEnabled(bool) {} -func (noopDevice) ExtractStatistics() map[flowtrack.Tuple]tunstats.Counts { return nil } - -// Message is the log message that captures network traffic. -type Message struct { - Start time.Time `json:"start"` // inclusive - End time.Time `json:"end"` // inclusive - VirtualTraffic []TupleCounts `json:"virtualTraffic,omitempty"` - SubnetTraffic []TupleCounts `json:"subnetTraffic,omitempty"` - ExitTraffic []TupleCounts `json:"exitTraffic,omitempty"` - PhysicalTraffic []TupleCounts `json:"physicalTraffic,omitempty"` -} - -// TupleCounts is a flattened struct of both a connection and counts. -type TupleCounts struct { - flowtrack.Tuple - tunstats.Counts -} +func (noopDevice) SetStatisticsEnabled(bool) {} +func (noopDevice) ExtractStatistics() map[netlogtype.Connection]netlogtype.Counts { return nil } // Logger logs statistics about every connection. // At present, it only logs connections within a tailscale network. @@ -192,8 +175,8 @@ func (nl *Logger) Startup(nodeID, domainID logtail.PrivateID, tun, sock Device) return nil } -func recordStatistics(logger *logtail.Logger, start, end time.Time, tunStats, sockStats map[flowtrack.Tuple]tunstats.Counts, addrs map[netip.Addr]bool, prefixes map[netip.Prefix]bool) { - m := Message{Start: start.UTC(), End: end.UTC()} +func recordStatistics(logger *logtail.Logger, start, end time.Time, tunStats, sockStats map[netlogtype.Connection]netlogtype.Counts, addrs map[netip.Addr]bool, prefixes map[netip.Prefix]bool) { + m := netlogtype.Message{Start: start.UTC(), End: end.UTC()} classifyAddr := func(a netip.Addr) (isTailscale, withinRoute bool) { // NOTE: There could be mis-classifications where an address is treated @@ -214,23 +197,23 @@ func recordStatistics(logger *logtail.Logger, start, end time.Time, tunStats, so dstIsTailscaleIP, dstWithinSubnet := classifyAddr(conn.Dst.Addr()) switch { case srcIsTailscaleIP && dstIsTailscaleIP: - m.VirtualTraffic = append(m.VirtualTraffic, TupleCounts{conn, cnts}) + m.VirtualTraffic = append(m.VirtualTraffic, netlogtype.ConnectionCounts{Connection: conn, Counts: cnts}) case srcWithinSubnet || dstWithinSubnet: - m.SubnetTraffic = append(m.SubnetTraffic, TupleCounts{conn, cnts}) + m.SubnetTraffic = append(m.SubnetTraffic, netlogtype.ConnectionCounts{Connection: conn, Counts: cnts}) default: const anonymize = true if anonymize { if len(m.ExitTraffic) == 0 { - m.ExitTraffic = []TupleCounts{{}} + m.ExitTraffic = []netlogtype.ConnectionCounts{{}} } m.ExitTraffic[0].Counts = m.ExitTraffic[0].Counts.Add(cnts) } else { - m.ExitTraffic = append(m.ExitTraffic, TupleCounts{conn, cnts}) + m.ExitTraffic = append(m.ExitTraffic, netlogtype.ConnectionCounts{Connection: conn, Counts: cnts}) } } } for conn, cnts := range sockStats { - m.PhysicalTraffic = append(m.PhysicalTraffic, TupleCounts{conn, cnts}) + m.PhysicalTraffic = append(m.PhysicalTraffic, netlogtype.ConnectionCounts{Connection: conn, Counts: cnts}) } if len(m.VirtualTraffic)+len(m.SubnetTraffic)+len(m.ExitTraffic)+len(m.PhysicalTraffic) > 0 { diff --git a/wgengine/netlog/logger_test.go b/wgengine/netlog/logger_test.go index 654379315..5da4ad5ea 100644 --- a/wgengine/netlog/logger_test.go +++ b/wgengine/netlog/logger_test.go @@ -11,9 +11,8 @@ import ( qt "github.com/frankban/quicktest" "tailscale.com/logtail" - "tailscale.com/net/flowtrack" - "tailscale.com/net/tunstats" "tailscale.com/tstest" + "tailscale.com/types/netlogtype" "tailscale.com/util/must" "tailscale.com/wgengine/router" ) @@ -42,7 +41,7 @@ func (d *fakeDevice) SetStatisticsEnabled(enable bool) { } } -func (fakeDevice) ExtractStatistics() map[flowtrack.Tuple]tunstats.Counts { +func (fakeDevice) ExtractStatistics() map[netlogtype.Connection]netlogtype.Counts { // TODO(dsnet): Add a test that verifies that statistics are correctly // extracted from the device and uploaded. Unfortunately, // we can't reliably run this test until we fix http://go/oss/5856.