diff --git a/agent/network.go b/agent/network.go index 1a66b2ad..5de78a1f 100644 --- a/agent/network.go +++ b/agent/network.go @@ -104,10 +104,7 @@ func (a *Agent) initializeNetIoStats() { // get current network I/O stats and record valid interfaces if netIO, err := psutilNet.IOCounters(true); err == nil { for _, v := range netIO { - if nicsEnvExists && !isValidNic(v.Name, nicCfg) { - continue - } - if a.skipNetworkInterface(v) { + if skipNetworkInterface(v, nicCfg) { continue } slog.Info("Detected network interface", "name", v.Name, "sent", v.BytesSent, "recv", v.BytesRecv) @@ -243,7 +240,19 @@ func (a *Agent) applyNetworkTotals( a.netIoStats[cacheTimeMs] = nis } -func (a *Agent) skipNetworkInterface(v psutilNet.IOCountersStat) bool { +// skipNetworkInterface returns true if the network interface should be ignored. +func skipNetworkInterface(v psutilNet.IOCountersStat, nicCfg *NicConfig) bool { + if nicCfg != nil { + if !isValidNic(v.Name, nicCfg) { + return true + } + // In whitelist mode, we honor explicit inclusion without auto-filtering. + if !nicCfg.isBlacklist { + return false + } + // In blacklist mode, still apply the auto-filter below. + } + switch { case strings.HasPrefix(v.Name, "lo"), strings.HasPrefix(v.Name, "docker"), diff --git a/agent/network_test.go b/agent/network_test.go index 99b46c38..3f32715b 100644 --- a/agent/network_test.go +++ b/agent/network_test.go @@ -261,6 +261,39 @@ func TestNewNicConfig(t *testing.T) { }) } } +func TestSkipNetworkInterface(t *testing.T) { + tests := []struct { + name string + nic psutilNet.IOCountersStat + nicCfg *NicConfig + expectSkip bool + }{ + {"loopback lo", psutilNet.IOCountersStat{Name: "lo", BytesSent: 100, BytesRecv: 100}, nil, true}, + {"loopback lo0", psutilNet.IOCountersStat{Name: "lo0", BytesSent: 100, BytesRecv: 100}, nil, true}, + {"docker prefix", psutilNet.IOCountersStat{Name: "docker0", BytesSent: 100, BytesRecv: 100}, nil, true}, + {"br- prefix", psutilNet.IOCountersStat{Name: "br-lan", BytesSent: 100, BytesRecv: 100}, nil, true}, + {"veth prefix", psutilNet.IOCountersStat{Name: "veth0abc", BytesSent: 100, BytesRecv: 100}, nil, true}, + {"bond prefix", psutilNet.IOCountersStat{Name: "bond0", BytesSent: 100, BytesRecv: 100}, nil, true}, + {"cali prefix", psutilNet.IOCountersStat{Name: "cali1234", BytesSent: 100, BytesRecv: 100}, nil, true}, + {"zero BytesRecv", psutilNet.IOCountersStat{Name: "eth0", BytesSent: 100, BytesRecv: 0}, nil, true}, + {"zero BytesSent", psutilNet.IOCountersStat{Name: "eth0", BytesSent: 0, BytesRecv: 100}, nil, true}, + {"both zero", psutilNet.IOCountersStat{Name: "eth0", BytesSent: 0, BytesRecv: 0}, nil, true}, + {"normal eth0", psutilNet.IOCountersStat{Name: "eth0", BytesSent: 100, BytesRecv: 200}, nil, false}, + {"normal wlan0", psutilNet.IOCountersStat{Name: "wlan0", BytesSent: 1, BytesRecv: 1}, nil, false}, + {"whitelist overrides skip (docker)", psutilNet.IOCountersStat{Name: "docker0", BytesSent: 100, BytesRecv: 100}, newNicConfig("docker0"), false}, + {"whitelist overrides skip (lo)", psutilNet.IOCountersStat{Name: "lo", BytesSent: 100, BytesRecv: 100}, newNicConfig("lo"), false}, + {"whitelist exclusion", psutilNet.IOCountersStat{Name: "eth1", BytesSent: 100, BytesRecv: 100}, newNicConfig("eth0"), true}, + {"blacklist skip lo", psutilNet.IOCountersStat{Name: "lo", BytesSent: 100, BytesRecv: 100}, newNicConfig("-eth0"), true}, + {"blacklist explicit eth0", psutilNet.IOCountersStat{Name: "eth0", BytesSent: 100, BytesRecv: 100}, newNicConfig("-eth0"), true}, + {"blacklist allow eth1", psutilNet.IOCountersStat{Name: "eth1", BytesSent: 100, BytesRecv: 100}, newNicConfig("-eth0"), false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expectSkip, skipNetworkInterface(tt.nic, tt.nicCfg)) + }) + } +} + func TestEnsureNetworkInterfacesMap(t *testing.T) { var a Agent var stats system.Stats