mirror of
https://github.com/henrygd/beszel.git
synced 2026-10-02 14:27:47 +02:00
fix(agent): use nvethernet MAC counters (#2090)
Co-authored-by: hank <hank@henrygd.me>
This commit is contained in:
71
agent/network_counters_linux.go
Normal file
71
agent/network_counters_linux.go
Normal file
@@ -0,0 +1,71 @@
|
||||
//go:build linux
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/safchain/ethtool"
|
||||
psutilNet "github.com/shirou/gopsutil/v4/net"
|
||||
)
|
||||
|
||||
// correctNvethernetCounters replaces the inflated sysfs byte counters of an
|
||||
// nvethernet NIC with its MAC octet counters.
|
||||
func correctNvethernetCounters(v *psutilNet.IOCountersStat) {
|
||||
tx, rx, ok := readEthtoolMACOctets(v.Name)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
v.BytesSent = tx
|
||||
v.BytesRecv = rx
|
||||
}
|
||||
|
||||
func isNvidiaEthernet(name string) bool {
|
||||
if name == "" || strings.Contains(name, "/") {
|
||||
return false
|
||||
}
|
||||
|
||||
driverPath := filepath.Join("/sys/class/net", name, "device/driver")
|
||||
target, err := os.Readlink(driverPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return filepath.Base(target) == "nvethernet"
|
||||
}
|
||||
|
||||
func readEthtoolMACOctets(name string) (tx, rx uint64, ok bool) {
|
||||
stats, err := ethtool.Stats(name)
|
||||
if err != nil {
|
||||
slog.Debug("Failed to read ethtool network counters", "interface", name, "err", err)
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
tx, okTx := ethtoolCounter(stats, "mmc_tx_octetcount_gb", "mmc_tx_octetcount_gb_h")
|
||||
rx, okRx := ethtoolCounter(stats, "mmc_rx_octetcount_gb", "mmc_rx_octetcount_gb_h")
|
||||
if !okTx || !okRx {
|
||||
return 0, 0, false
|
||||
}
|
||||
return tx, rx, true
|
||||
}
|
||||
|
||||
// ethtoolCounter combines nvethernet's split MMC counters. The driver accumulates
|
||||
// the low and high registers into independent 64-bit fields, so the low value can
|
||||
// exceed 32 bits and must be added rather than OR'd into the shifted high word.
|
||||
func ethtoolCounter(stats map[string]uint64, lowKey, highKey string) (uint64, bool) {
|
||||
low, ok := stats[lowKey]
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
high, hasHigh := stats[highKey]
|
||||
if !hasHigh {
|
||||
return low, true
|
||||
}
|
||||
if high > (math.MaxUint64-low)>>32 {
|
||||
return 0, false
|
||||
}
|
||||
return high<<32 + low, true
|
||||
}
|
||||
Reference in New Issue
Block a user