feature/*,net/tstun: add tundev_txq_drops clientmetric on Linux
By polling RTM_GETSTATS via netlink. RTM_GETSTATS is a relatively efficient and targeted (single device) polling method available since Linux v4.7. The tundevstats "feature" can be extended to other platforms in the future, and it's trivial to add new rtnl_link_stats64 counters on Linux. Updates tailscale/corp#38181 Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
committed by
Jordan Whited
parent
bdcf976477
commit
9c36a71a90
@@ -24,6 +24,7 @@ import (
|
||||
"go4.org/mem"
|
||||
"tailscale.com/disco"
|
||||
"tailscale.com/envknob"
|
||||
"tailscale.com/feature"
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/net/packet"
|
||||
"tailscale.com/net/packet/checksum"
|
||||
@@ -222,6 +223,10 @@ type Wrapper struct {
|
||||
|
||||
eventClient *eventbus.Client
|
||||
discoKeyAdvertisementPub *eventbus.Publisher[events.DiscoKeyAdvertisement]
|
||||
|
||||
// tunDevStatsCloser closes TUN device stats polling. It may be nil if
|
||||
// [HookPollTUNDevStats] is unset, or the hook func returned an error.
|
||||
tunDevStatsCloser io.Closer
|
||||
}
|
||||
|
||||
type metrics struct {
|
||||
@@ -296,6 +301,16 @@ func wrap(logf logger.Logf, tdev tun.Device, isTAP bool, m *usermetric.Registry,
|
||||
metrics: registerMetrics(m),
|
||||
}
|
||||
|
||||
if buildfeatures.HasTUNDevStats {
|
||||
if f, ok := HookPollTUNDevStats.GetOk(); ok {
|
||||
closer, err := f(tdev)
|
||||
if err != nil {
|
||||
w.logf("error initializing tun dev stats polling: %v", err)
|
||||
}
|
||||
w.tunDevStatsCloser = closer
|
||||
}
|
||||
}
|
||||
|
||||
w.eventClient = bus.Client("net.tstun")
|
||||
w.discoKeyAdvertisementPub = eventbus.Publish[events.DiscoKeyAdvertisement](w.eventClient)
|
||||
|
||||
@@ -313,6 +328,9 @@ func wrap(logf logger.Logf, tdev tun.Device, isTAP bool, m *usermetric.Registry,
|
||||
return w
|
||||
}
|
||||
|
||||
// HookPollTUNDevStats is the hook maybe set by feature/tundevstats.
|
||||
var HookPollTUNDevStats feature.Hook[func(dev tun.Device) (io.Closer, error)]
|
||||
|
||||
// now returns the current time, either by calling t.timeNow if set or time.Now
|
||||
// if not.
|
||||
func (t *Wrapper) now() time.Time {
|
||||
@@ -374,6 +392,9 @@ func (t *Wrapper) Close() error {
|
||||
t.outboundMu.Unlock()
|
||||
err = t.tdev.Close()
|
||||
t.eventClient.Close()
|
||||
if t.tunDevStatsCloser != nil {
|
||||
t.tunDevStatsCloser.Close()
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user