Move interface counter state from global map to Interface struct

This commit is contained in:
Ian Gulliver
2026-02-02 10:16:37 -08:00
parent 2a8e376cbf
commit d4e7a8a9b7
2 changed files with 23 additions and 41 deletions

57
snmp.go
View File

@@ -6,30 +6,11 @@ import (
"net"
"regexp"
"strings"
"sync"
"time"
"github.com/gosnmp/gosnmp"
)
type ifaceCounters struct {
inPkts uint64
outPkts uint64
inBytes uint64
outBytes uint64
uptime uint64
timestamp time.Time
}
type counterTracker struct {
mu sync.Mutex
counters map[string]*ifaceCounters
}
var ifaceTracker = &counterTracker{
counters: map[string]*ifaceCounters{},
}
var portNameRewrites = []struct {
re *regexp.Regexp
repl string
@@ -289,21 +270,19 @@ func (t *Tendrils) queryInterfaceStats(snmp *gosnmp.GoSNMP, node *Node, ifNames
inPkts := ifHCInUcastPkts[ifIndex] + ifHCInMcastPkts[ifIndex] + ifHCInBcastPkts[ifIndex]
outPkts := ifHCOutUcastPkts[ifIndex] + ifHCOutMcastPkts[ifIndex] + ifHCOutBcastPkts[ifIndex]
key := node.ID + ":" + name
ifaceTracker.mu.Lock()
prev, hasPrev := ifaceTracker.counters[key]
hasPrev := !iface.prevTimestamp.IsZero()
if hasPrev {
if prev.uptime > 0 && stats.Uptime > 0 && stats.Uptime < prev.uptime {
log.Printf("[ERROR] port flap on %s %s: uptime dropped from %d to %d seconds", node.DisplayName(), name, prev.uptime, stats.Uptime)
if iface.prevUptime > 0 && stats.Uptime > 0 && stats.Uptime < iface.prevUptime {
log.Printf("[ERROR] port flap on %s %s: uptime dropped from %d to %d seconds", node.DisplayName(), name, iface.prevUptime, stats.Uptime)
t.errors.AddPortFlap(node, name)
}
if hasInBytes && hasOutBytes {
elapsed := now.Sub(prev.timestamp).Seconds()
elapsed := now.Sub(iface.prevTimestamp).Seconds()
if elapsed > 0 {
stats.InPktsRate = float64(inPkts-prev.inPkts) / elapsed
stats.OutPktsRate = float64(outPkts-prev.outPkts) / elapsed
stats.InBytesRate = float64(inBytes-prev.inBytes) / elapsed
stats.OutBytesRate = float64(outBytes-prev.outBytes) / elapsed
stats.InPktsRate = float64(inPkts-iface.prevInPkts) / elapsed
stats.OutPktsRate = float64(outPkts-iface.prevOutPkts) / elapsed
stats.InBytesRate = float64(inBytes-iface.prevInBytes) / elapsed
stats.OutBytesRate = float64(outBytes-iface.prevOutBytes) / elapsed
maxBytesRate := float64(stats.Speed) / 8 * 2
if stats.InBytesRate < 0 || stats.InBytesRate > maxBytesRate {
@@ -317,19 +296,15 @@ func (t *Tendrils) queryInterfaceStats(snmp *gosnmp.GoSNMP, node *Node, ifNames
}
}
}
storedUptime := stats.Uptime
if storedUptime == 0 && hasPrev {
storedUptime = prev.uptime
iface.prevInPkts = inPkts
iface.prevOutPkts = outPkts
iface.prevInBytes = inBytes
iface.prevOutBytes = outBytes
if stats.Uptime > 0 {
iface.prevUptime = stats.Uptime
}
ifaceTracker.counters[key] = &ifaceCounters{
inPkts: inPkts,
outPkts: outPkts,
inBytes: inBytes,
outBytes: outBytes,
uptime: storedUptime,
timestamp: now,
}
ifaceTracker.mu.Unlock()
iface.prevTimestamp = now
if poe, ok := poeStats[name]; ok {
stats.PoE = poe