net/connstats: make it modular (omittable)

Saves only 12 KB, but notably removes some deps on packages that future
changes can then eliminate entirely.

Updates #12614

Change-Id: Ibf830d3ee08f621d0a2011b1d4cd175427ef50df
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/17445/head
Brad Fitzpatrick 2 months ago committed by Brad Fitzpatrick
parent 2e381557b8
commit 3c7e351671

@ -134,7 +134,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/types/logger from tailscale.com/appc+
tailscale.com/types/logid from tailscale.com/cmd/tailscaled+
tailscale.com/types/mapx from tailscale.com/ipn/ipnext
tailscale.com/types/netlogtype from tailscale.com/net/connstats
tailscale.com/types/netmap from tailscale.com/control/controlclient+
tailscale.com/types/nettype from tailscale.com/net/batching+
tailscale.com/types/opt from tailscale.com/control/controlknobs+
@ -217,7 +216,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
golang.org/x/net/internal/socket from golang.org/x/net/icmp+
golang.org/x/net/ipv4 from github.com/tailscale/wireguard-go/conn+
golang.org/x/net/ipv6 from github.com/tailscale/wireguard-go/conn+
golang.org/x/sync/errgroup from github.com/mdlayher/socket+
golang.org/x/sync/errgroup from github.com/mdlayher/socket
golang.org/x/sys/cpu from github.com/tailscale/wireguard-go/tun+
golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+
golang.org/x/term from tailscale.com/logpolicy

@ -160,7 +160,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/types/logger from tailscale.com/appc+
tailscale.com/types/logid from tailscale.com/cmd/tailscaled+
tailscale.com/types/mapx from tailscale.com/ipn/ipnext
tailscale.com/types/netlogtype from tailscale.com/net/connstats
tailscale.com/types/netmap from tailscale.com/control/controlclient+
tailscale.com/types/nettype from tailscale.com/net/batching+
tailscale.com/types/opt from tailscale.com/control/controlknobs+
@ -245,7 +244,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
golang.org/x/net/internal/socket from golang.org/x/net/icmp+
golang.org/x/net/ipv4 from github.com/tailscale/wireguard-go/conn+
golang.org/x/net/ipv6 from github.com/tailscale/wireguard-go/conn+
golang.org/x/sync/errgroup from github.com/mdlayher/socket+
golang.org/x/sync/errgroup from github.com/mdlayher/socket
golang.org/x/sys/cpu from github.com/tailscale/wireguard-go/tun+
golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+
golang.org/x/term from tailscale.com/logpolicy

@ -243,6 +243,7 @@ func TestMinTailscaledNoCLI(t *testing.T) {
"golang.org/x/net/proxy",
"internal/socks",
"github.com/tailscale/peercred",
"tailscale.com/types/netlogtype",
}
deptest.DepChecker{
GOOS: "linux",

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build ts_omit_connstats
package buildfeatures
// HasConnStats is whether the binary was built with support for modular feature "Track per-packet connection statistics".
// Specifically, it's whether the binary was NOT built with the "ts_omit_connstats" build tag.
// It's a const so it can be used for dead code elimination.
const HasConnStats = false

@ -0,0 +1,13 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by gen.go; DO NOT EDIT.
//go:build !ts_omit_connstats
package buildfeatures
// HasConnStats is whether the binary was built with support for modular feature "Track per-packet connection statistics".
// Specifically, it's whether the binary was NOT built with the "ts_omit_connstats" build tag.
// It's a const so it can be used for dead code elimination.
const HasConnStats = true

@ -130,7 +130,11 @@ var Features = map[FeatureTag]FeatureMeta{
Deps: []FeatureTag{"c2n"},
},
"completion": {Sym: "Completion", Desc: "CLI shell completion"},
"cloud": {Sym: "Cloud", Desc: "detect cloud environment to learn instances IPs and DNS servers"},
"connstats": {
Sym: "ConnStats",
Desc: "Track per-packet connection statistics",
},
"cloud": {Sym: "Cloud", Desc: "detect cloud environment to learn instances IPs and DNS servers"},
"dbus": {
Sym: "DBus",
Desc: "Linux DBus support",

@ -1,6 +1,8 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build !ts_omit_connstats
// Package connstats maintains statistics about connections
// flowing through a TUN device (which operate at the IP layer).
package connstats

@ -0,0 +1,24 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build ts_omit_connstats
package connstats
import (
"context"
"net/netip"
"time"
)
type Statistics struct{}
func NewStatistics(maxPeriod time.Duration, maxConns int, dump func(start, end time.Time, virtual, physical any)) *Statistics {
return &Statistics{}
}
func (s *Statistics) UpdateTxVirtual(b []byte) {}
func (s *Statistics) UpdateRxVirtual(b []byte) {}
func (s *Statistics) UpdateTxPhysical(src netip.Addr, dst netip.AddrPort, packets, bytes int) {}
func (s *Statistics) UpdateRxPhysical(src netip.Addr, dst netip.AddrPort, packets, bytes int) {}
func (s *Statistics) Shutdown(context.Context) error { return nil }

@ -973,8 +973,10 @@ func (t *Wrapper) Read(buffs [][]byte, sizes []int, offset int) (int, error) {
panic(fmt.Sprintf("short copy: %d != %d", n, len(data)-res.dataOffset))
}
sizes[buffsPos] = n
if stats := t.stats.Load(); stats != nil {
stats.UpdateTxVirtual(p.Buffer())
if buildfeatures.HasConnStats {
if stats := t.stats.Load(); stats != nil {
stats.UpdateTxVirtual(p.Buffer())
}
}
buffsPos++
}
@ -1098,9 +1100,11 @@ func (t *Wrapper) injectedRead(res tunInjectedRead, outBuffs [][]byte, sizes []i
n, err = tun.GSOSplit(pkt, gsoOptions, outBuffs, sizes, offset)
}
if stats := t.stats.Load(); stats != nil {
for i := 0; i < n; i++ {
stats.UpdateTxVirtual(outBuffs[i][offset : offset+sizes[i]])
if buildfeatures.HasConnStats {
if stats := t.stats.Load(); stats != nil {
for i := 0; i < n; i++ {
stats.UpdateTxVirtual(outBuffs[i][offset : offset+sizes[i]])
}
}
}
@ -1266,9 +1270,11 @@ func (t *Wrapper) Write(buffs [][]byte, offset int) (int, error) {
}
func (t *Wrapper) tdevWrite(buffs [][]byte, offset int) (int, error) {
if stats := t.stats.Load(); stats != nil {
for i := range buffs {
stats.UpdateRxVirtual((buffs)[i][offset:])
if buildfeatures.HasConnStats {
if stats := t.stats.Load(); stats != nil {
for i := range buffs {
stats.UpdateRxVirtual((buffs)[i][offset:])
}
}
}
return t.tdev.Write(buffs, offset)
@ -1490,7 +1496,9 @@ func (t *Wrapper) Unwrap() tun.Device {
// SetStatistics specifies a per-connection statistics aggregator.
// Nil may be specified to disable statistics gathering.
func (t *Wrapper) SetStatistics(stats *connstats.Statistics) {
t.stats.Store(stats)
if buildfeatures.HasConnStats {
t.stats.Store(stats)
}
}
var (

@ -1865,8 +1865,10 @@ func (c *Conn) receiveIP(b []byte, ipp netip.AddrPort, cache *epAddrEndpointCach
now := mono.Now()
ep.lastRecvUDPAny.StoreAtomic(now)
connNoted := ep.noteRecvActivity(src, now)
if stats := c.stats.Load(); stats != nil {
stats.UpdateRxPhysical(ep.nodeAddr, ipp, 1, geneveInclusivePacketLen)
if buildfeatures.HasConnStats {
if stats := c.stats.Load(); stats != nil {
stats.UpdateRxPhysical(ep.nodeAddr, ipp, 1, geneveInclusivePacketLen)
}
}
if src.vni.IsSet() && (connNoted || looksLikeInitiationMsg(b)) {
// connNoted is periodic, but we also want to verify if the peer is who
@ -3743,7 +3745,9 @@ func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) {
// SetStatistics specifies a per-connection statistics aggregator.
// Nil may be specified to disable statistics gathering.
func (c *Conn) SetStatistics(stats *connstats.Statistics) {
c.stats.Store(stats)
if buildfeatures.HasConnStats {
c.stats.Store(stats)
}
}
// SetHomeless sets whether magicsock should idle harder and not have a DERP

@ -19,6 +19,7 @@ import (
"sync"
"time"
"tailscale.com/feature/buildfeatures"
"tailscale.com/health"
"tailscale.com/logpolicy"
"tailscale.com/logtail"
@ -130,20 +131,24 @@ func (nl *Logger) Startup(nodeID tailcfg.StableNodeID, nodeLogID, domainLogID lo
// can upload to the Tailscale log service, so stay below this limit.
const maxLogSize = 256 << 10
const maxConns = (maxLogSize - netlogtype.MaxMessageJSONSize) / netlogtype.MaxConnectionCountsJSONSize
nl.stats = connstats.NewStatistics(pollPeriod, maxConns, func(start, end time.Time, virtual, physical map[netlogtype.Connection]netlogtype.Counts) {
nl.mu.Lock()
addrs := nl.addrs
prefixes := nl.prefixes
nl.mu.Unlock()
recordStatistics(nl.logger, nodeID, start, end, virtual, physical, addrs, prefixes, logExitFlowEnabledEnabled)
})
if buildfeatures.HasConnStats {
nl.stats = connstats.NewStatistics(pollPeriod, maxConns, func(start, end time.Time, virtual, physical map[netlogtype.Connection]netlogtype.Counts) {
nl.mu.Lock()
addrs := nl.addrs
prefixes := nl.prefixes
nl.mu.Unlock()
recordStatistics(nl.logger, nodeID, start, end, virtual, physical, addrs, prefixes, logExitFlowEnabledEnabled)
})
}
// Register the connection tracker into the TUN device.
if tun == nil {
tun = noopDevice{}
}
nl.tun = tun
nl.tun.SetStatistics(nl.stats)
if buildfeatures.HasConnStats {
nl.tun.SetStatistics(nl.stats)
}
// Register the connection tracker into magicsock.
if sock == nil {

Loading…
Cancel
Save