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/logger from tailscale.com/appc+
tailscale.com/types/logid from tailscale.com/cmd/tailscaled+ tailscale.com/types/logid from tailscale.com/cmd/tailscaled+
tailscale.com/types/mapx from tailscale.com/ipn/ipnext 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/netmap from tailscale.com/control/controlclient+
tailscale.com/types/nettype from tailscale.com/net/batching+ tailscale.com/types/nettype from tailscale.com/net/batching+
tailscale.com/types/opt from tailscale.com/control/controlknobs+ 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/internal/socket from golang.org/x/net/icmp+
golang.org/x/net/ipv4 from github.com/tailscale/wireguard-go/conn+ 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/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/cpu from github.com/tailscale/wireguard-go/tun+
golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+ golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+
golang.org/x/term from tailscale.com/logpolicy 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/logger from tailscale.com/appc+
tailscale.com/types/logid from tailscale.com/cmd/tailscaled+ tailscale.com/types/logid from tailscale.com/cmd/tailscaled+
tailscale.com/types/mapx from tailscale.com/ipn/ipnext 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/netmap from tailscale.com/control/controlclient+
tailscale.com/types/nettype from tailscale.com/net/batching+ tailscale.com/types/nettype from tailscale.com/net/batching+
tailscale.com/types/opt from tailscale.com/control/controlknobs+ 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/internal/socket from golang.org/x/net/icmp+
golang.org/x/net/ipv4 from github.com/tailscale/wireguard-go/conn+ 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/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/cpu from github.com/tailscale/wireguard-go/tun+
golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+ golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+
golang.org/x/term from tailscale.com/logpolicy golang.org/x/term from tailscale.com/logpolicy

@ -243,6 +243,7 @@ func TestMinTailscaledNoCLI(t *testing.T) {
"golang.org/x/net/proxy", "golang.org/x/net/proxy",
"internal/socks", "internal/socks",
"github.com/tailscale/peercred", "github.com/tailscale/peercred",
"tailscale.com/types/netlogtype",
} }
deptest.DepChecker{ deptest.DepChecker{
GOOS: "linux", 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"}, Deps: []FeatureTag{"c2n"},
}, },
"completion": {Sym: "Completion", Desc: "CLI shell completion"}, "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": { "dbus": {
Sym: "DBus", Sym: "DBus",
Desc: "Linux DBus support", Desc: "Linux DBus support",

@ -1,6 +1,8 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
//go:build !ts_omit_connstats
// Package connstats maintains statistics about connections // Package connstats maintains statistics about connections
// flowing through a TUN device (which operate at the IP layer). // flowing through a TUN device (which operate at the IP layer).
package connstats 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)) panic(fmt.Sprintf("short copy: %d != %d", n, len(data)-res.dataOffset))
} }
sizes[buffsPos] = n sizes[buffsPos] = n
if stats := t.stats.Load(); stats != nil { if buildfeatures.HasConnStats {
stats.UpdateTxVirtual(p.Buffer()) if stats := t.stats.Load(); stats != nil {
stats.UpdateTxVirtual(p.Buffer())
}
} }
buffsPos++ buffsPos++
} }
@ -1098,9 +1100,11 @@ func (t *Wrapper) injectedRead(res tunInjectedRead, outBuffs [][]byte, sizes []i
n, err = tun.GSOSplit(pkt, gsoOptions, outBuffs, sizes, offset) n, err = tun.GSOSplit(pkt, gsoOptions, outBuffs, sizes, offset)
} }
if stats := t.stats.Load(); stats != nil { if buildfeatures.HasConnStats {
for i := 0; i < n; i++ { if stats := t.stats.Load(); stats != nil {
stats.UpdateTxVirtual(outBuffs[i][offset : offset+sizes[i]]) 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) { func (t *Wrapper) tdevWrite(buffs [][]byte, offset int) (int, error) {
if stats := t.stats.Load(); stats != nil { if buildfeatures.HasConnStats {
for i := range buffs { if stats := t.stats.Load(); stats != nil {
stats.UpdateRxVirtual((buffs)[i][offset:]) for i := range buffs {
stats.UpdateRxVirtual((buffs)[i][offset:])
}
} }
} }
return t.tdev.Write(buffs, offset) return t.tdev.Write(buffs, offset)
@ -1490,7 +1496,9 @@ func (t *Wrapper) Unwrap() tun.Device {
// SetStatistics specifies a per-connection statistics aggregator. // SetStatistics specifies a per-connection statistics aggregator.
// Nil may be specified to disable statistics gathering. // Nil may be specified to disable statistics gathering.
func (t *Wrapper) SetStatistics(stats *connstats.Statistics) { func (t *Wrapper) SetStatistics(stats *connstats.Statistics) {
t.stats.Store(stats) if buildfeatures.HasConnStats {
t.stats.Store(stats)
}
} }
var ( var (

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

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

Loading…
Cancel
Save