Filter interface data from stats segment by known vpp_iface; this avoids an issue in VPP where deleted interfaces remain in the stats segment

This commit is contained in:
Pim van Pelt
2025-11-23 11:05:05 +01:00
parent 5e36d5c926
commit b450e02b8d
3 changed files with 77 additions and 18 deletions

View File

@@ -15,17 +15,19 @@ type StatsCallback func(*api.InterfaceStats)
// StatsManager handles VPP statistics operations
type StatsManager struct {
client *VPPClient
statsCallback StatsCallback
period time.Duration
running bool
client *VPPClient
interfaceManager *InterfaceManager
statsCallback StatsCallback
period time.Duration
running bool
}
// NewStatsManager creates a new stats manager
func NewStatsManager(client *VPPClient) *StatsManager {
func NewStatsManager(client *VPPClient, interfaceManager *InterfaceManager) *StatsManager {
return &StatsManager{
client: client,
period: time.Duration(*Period) * time.Second,
client: client,
interfaceManager: interfaceManager,
period: time.Duration(*Period) * time.Second,
}
}
@@ -139,11 +141,24 @@ func (sm *StatsManager) queryAndReportStats() bool {
return false
}
// Filter out deleted interfaces by comparing with current interface list
filteredStats, err := sm.filterValidInterfaces(stats)
if err != nil {
logger.Printf("Failed to filter interface stats: %v", err)
return false
}
// Debug log basic info
logger.Debugf("Retrieved stats for %d interfaces", len(stats.Interfaces))
originalCount := len(stats.Interfaces)
filteredCount := len(filteredStats.Interfaces)
logger.Debugf("Retrieved stats for %d interfaces, filtered to %d valid interfaces", originalCount, filteredCount)
if originalCount > filteredCount {
logger.Debugf("Filtered out %d deleted interfaces", originalCount-filteredCount)
}
// Debug logging for individual interfaces
for _, iface := range stats.Interfaces {
for _, iface := range filteredStats.Interfaces {
logger.Debugf("Interface %d (%s): RX %d pkts/%d bytes, TX %d pkts/%d bytes",
iface.InterfaceIndex, iface.InterfaceName,
iface.Rx.Packets, iface.Rx.Bytes,
@@ -152,8 +167,45 @@ func (sm *StatsManager) queryAndReportStats() bool {
// Call the callback to update the MIB
if sm.statsCallback != nil {
sm.statsCallback(stats)
sm.statsCallback(filteredStats)
}
return true
}
// filterValidInterfaces removes stats for deleted interfaces by comparing with current interface list
func (sm *StatsManager) filterValidInterfaces(stats *api.InterfaceStats) (*api.InterfaceStats, error) {
if sm.interfaceManager == nil {
logger.Debugf("No interface manager available, returning unfiltered stats")
return stats, nil
}
// Get current interface details
currentInterfaces, err := sm.interfaceManager.GetAllInterfaceDetails()
if err != nil {
logger.Debugf("Failed to get current interface list: %v", err)
return stats, err
}
// Create a map of valid sw_if_index values
validInterfaces := make(map[uint32]bool)
for _, iface := range currentInterfaces {
validInterfaces[uint32(iface.SwIfIndex)] = true
}
// Filter the stats to only include valid interfaces
filteredStats := &api.InterfaceStats{
Interfaces: make([]api.InterfaceCounters, 0, len(stats.Interfaces)),
}
for _, ifaceStat := range stats.Interfaces {
if validInterfaces[ifaceStat.InterfaceIndex] {
filteredStats.Interfaces = append(filteredStats.Interfaces, ifaceStat)
} else {
logger.Debugf("Filtering out stats for deleted interface %d (%s)",
ifaceStat.InterfaceIndex, ifaceStat.InterfaceName)
}
}
return filteredStats, nil
}