diff --git a/cmd/system-probe/modules/network_tracer.go b/cmd/system-probe/modules/network_tracer.go index 772210a52376e..0fc60446f86f3 100644 --- a/cmd/system-probe/modules/network_tracer.go +++ b/cmd/system-probe/modules/network_tracer.go @@ -172,6 +172,7 @@ func (nt *networkTracer) Register(httpMux *module.Router) error { } utils.WriteAsJSON(w, httpdebugging.HTTP(cs.HTTP, cs.DNS)) + nt.tracer.ReleaseUSMStats() }) httpMux.HandleFunc("/debug/kafka_monitoring", func(w http.ResponseWriter, req *http.Request) { diff --git a/pkg/network/nettop/main.go b/pkg/network/nettop/main.go index 1fb0f4da992ff..f3c9a5c7e3f0f 100644 --- a/pkg/network/nettop/main.go +++ b/pkg/network/nettop/main.go @@ -58,6 +58,7 @@ func main() { for _, c := range cs.Conns { fmt.Println(network.ConnectionSummary(&c, cs.DNS)) } + t.ReleaseUSMStats() } stopChan := make(chan struct{}) diff --git a/pkg/network/protocols/http/protocol.go b/pkg/network/protocols/http/protocol.go index 0c1c4e8b2bc06..4b75092efb46c 100644 --- a/pkg/network/protocols/http/protocol.go +++ b/pkg/network/protocols/http/protocol.go @@ -225,6 +225,11 @@ func (p *protocol) GetStats() *protocols.ProtocolStats { } } +// ReleaseStats releases stats objects. +func (p *protocol) ReleaseStats() { + p.statkeeper.ReleaseStats() +} + // IsBuildModeSupported returns always true, as http module is supported by all modes. func (*protocol) IsBuildModeSupported(buildmode.Type) bool { return true diff --git a/pkg/network/protocols/http/statkeeper.go b/pkg/network/protocols/http/statkeeper.go index 6cb428c4722bf..9d7aba246ea2e 100644 --- a/pkg/network/protocols/http/statkeeper.go +++ b/pkg/network/protocols/http/statkeeper.go @@ -21,6 +21,7 @@ import ( type StatKeeper struct { mux sync.Mutex stats map[Key]*RequestStats + prevStats map[Key]*RequestStats incomplete IncompleteBuffer maxEntries int quantizer *URLQuantizer @@ -87,7 +88,7 @@ func (h *StatKeeper) GetAndResetAllStats() (stats map[Key]*RequestStats) { } // Rotate stats - stats = h.stats + h.prevStats = h.stats h.stats = make(map[Key]*RequestStats) // Rotate ConnectionAggregator @@ -100,8 +101,8 @@ func (h *StatKeeper) GetAndResetAllStats() (stats map[Key]*RequestStats) { h.connectionAggregator = utils.NewConnectionAggregator() }() - h.clearEphemeralPorts(previousAggregationState, stats) - return stats + h.clearEphemeralPorts(previousAggregationState, h.prevStats) + return h.prevStats } // Close closes the stat keeper. @@ -217,3 +218,10 @@ func (h *StatKeeper) clearEphemeralPorts(aggregator *utils.ConnectionAggregator, stats[key] = aggregation } } + +// ReleaseStats release reported stats. +func (h *StatKeeper) ReleaseStats() { + h.mux.Lock() + defer h.mux.Unlock() + h.prevStats = nil +} diff --git a/pkg/network/protocols/http/statkeeper_test.go b/pkg/network/protocols/http/statkeeper_test.go index 8ae60da8b5859..6c9f8b52912e3 100644 --- a/pkg/network/protocols/http/statkeeper_test.go +++ b/pkg/network/protocols/http/statkeeper_test.go @@ -25,7 +25,9 @@ func TestProcessHTTPTransactions(t *testing.T) { cfg.MaxHTTPStatsBuffered = 1000 tel := NewTelemetry("http") sk := NewStatkeeper(cfg, tel, NewIncompleteBuffer(cfg, tel)) - + t.Cleanup(func() { + sk.ReleaseStats() + }) srcString := "1.1.1.1" dstString := "2.2.2.2" sourceIP := util.AddressFromString(srcString) diff --git a/pkg/network/protocols/http2/protocol.go b/pkg/network/protocols/http2/protocol.go index 433f55e15715e..525e17f0c1470 100644 --- a/pkg/network/protocols/http2/protocol.go +++ b/pkg/network/protocols/http2/protocol.go @@ -431,6 +431,10 @@ func (p *Protocol) GetStats() *protocols.ProtocolStats { } } +// ReleaseStats releases stats objects. +func (p *Protocol) ReleaseStats() { +} + // IsBuildModeSupported returns always true, as http2 module is supported by all modes. func (*Protocol) IsBuildModeSupported(buildmode.Type) bool { return true diff --git a/pkg/network/protocols/kafka/protocol.go b/pkg/network/protocols/kafka/protocol.go index 54bcb67ff5fdf..ace0b2f140cdb 100644 --- a/pkg/network/protocols/kafka/protocol.go +++ b/pkg/network/protocols/kafka/protocol.go @@ -361,6 +361,10 @@ func (p *protocol) GetStats() *protocols.ProtocolStats { } } +// ReleaseStats releases stats objects. +func (p *protocol) ReleaseStats() { +} + // IsBuildModeSupported returns always true, as kafka module is supported by all modes. func (*protocol) IsBuildModeSupported(buildmode.Type) bool { return true diff --git a/pkg/network/protocols/postgres/protocol.go b/pkg/network/protocols/postgres/protocol.go index c0d7aa37a6747..34c314771b631 100644 --- a/pkg/network/protocols/postgres/protocol.go +++ b/pkg/network/protocols/postgres/protocol.go @@ -239,6 +239,10 @@ func (p *protocol) GetStats() *protocols.ProtocolStats { } } +// ReleaseStats releases stats objects. +func (p *protocol) ReleaseStats() { +} + // IsBuildModeSupported returns always true, as postgres module is supported by all modes. func (*protocol) IsBuildModeSupported(buildmode.Type) bool { return true diff --git a/pkg/network/protocols/protocols.go b/pkg/network/protocols/protocols.go index acec71ad05d33..ceb75da72d286 100644 --- a/pkg/network/protocols/protocols.go +++ b/pkg/network/protocols/protocols.go @@ -61,6 +61,9 @@ type Protocol interface { // implementation. GetStats() *ProtocolStats + // ReleaseStats releases stats related objects. + ReleaseStats() + // IsBuildModeSupported return true is the given build mode is supported by this protocol. IsBuildModeSupported(buildmode.Type) bool } diff --git a/pkg/network/protocols/redis/protocol.go b/pkg/network/protocols/redis/protocol.go index 831d019b30416..b348fefb8de64 100644 --- a/pkg/network/protocols/redis/protocol.go +++ b/pkg/network/protocols/redis/protocol.go @@ -155,6 +155,10 @@ func (p *protocol) GetStats() *protocols.ProtocolStats { } } +// ReleaseStats releases stats objects. +func (p *protocol) ReleaseStats() { +} + // IsBuildModeSupported returns always true, as Redis module is supported by all modes. func (*protocol) IsBuildModeSupported(buildmode.Type) bool { return true diff --git a/pkg/network/tracer/tracer.go b/pkg/network/tracer/tracer.go index 56eaf657a802f..1797b8acc83b8 100644 --- a/pkg/network/tracer/tracer.go +++ b/pkg/network/tracer/tracer.go @@ -460,6 +460,11 @@ func (t *Tracer) GetActiveConnections(clientID string) (*network.Connections, er return conns, nil } +// ReleaseUSMStats releases usm stats objects. +func (t *Tracer) ReleaseUSMStats() { + t.usmMonitor.ReleaseStats() +} + // RegisterClient registers a clientID with the tracer func (t *Tracer) RegisterClient(clientID string) error { t.state.RegisterClient(clientID) diff --git a/pkg/network/tracer/tracer_unsupported.go b/pkg/network/tracer/tracer_unsupported.go index bf3474c079556..11eaffd300d9f 100644 --- a/pkg/network/tracer/tracer_unsupported.go +++ b/pkg/network/tracer/tracer_unsupported.go @@ -34,6 +34,9 @@ func (t *Tracer) GetActiveConnections(_ string) (*network.Connections, error) { return nil, ebpf.ErrNotImplemented } +// ReleaseUSMStats is not implemented on this OS for Tracer +func (t *Tracer) ReleaseUSMStats() {} + // GetNetworkID is not implemented on this OS for Tracer func (t *Tracer) GetNetworkID(_ context.Context) (string, error) { return "", ebpf.ErrNotImplemented diff --git a/pkg/network/tracer/tracer_windows.go b/pkg/network/tracer/tracer_windows.go index ba1706b108eb6..6433e78781f5d 100644 --- a/pkg/network/tracer/tracer_windows.go +++ b/pkg/network/tracer/tracer_windows.go @@ -251,6 +251,10 @@ func (t *Tracer) GetActiveConnections(clientID string) (*network.Connections, er return conns, nil } +// ReleaseUSMStats is not implemented on this OS for Tracer. +func (t *Tracer) ReleaseUSMStats() { +} + // RegisterClient registers the client func (t *Tracer) RegisterClient(clientID string) error { t.state.RegisterClient(clientID) diff --git a/pkg/network/usm/ebpf_gotls.go b/pkg/network/usm/ebpf_gotls.go index 2c1e31300612a..7663e81e283f0 100644 --- a/pkg/network/usm/ebpf_gotls.go +++ b/pkg/network/usm/ebpf_gotls.go @@ -289,6 +289,10 @@ func (p *goTLSProgram) GetStats() *protocols.ProtocolStats { return nil } +// ReleaseStats is a no-op. +func (p *goTLSProgram) ReleaseStats() { +} + // Stop terminates goTLS main goroutine. func (p *goTLSProgram) Stop(*manager.Manager) { close(p.done) diff --git a/pkg/network/usm/ebpf_main.go b/pkg/network/usm/ebpf_main.go index 85f9f7123a593..4ff4221d7790d 100644 --- a/pkg/network/usm/ebpf_main.go +++ b/pkg/network/usm/ebpf_main.go @@ -544,6 +544,12 @@ func (e *ebpfProgram) getProtocolStats() map[protocols.ProtocolType]interface{} return ret } +func (e *ebpfProgram) releaseStats() { + for _, protocol := range e.enabledProtocols { + protocol.Instance.ReleaseStats() + } +} + // executePerProtocol runs the given callback (`cb`) for every protocol in the given list (`protocolList`). // If the callback failed, then we call the error callback (`errorCb`). Eventually returning a list of protocols which // successfully executed the callback. diff --git a/pkg/network/usm/ebpf_ssl.go b/pkg/network/usm/ebpf_ssl.go index 64e452ea7fe45..6378c16218da5 100644 --- a/pkg/network/usm/ebpf_ssl.go +++ b/pkg/network/usm/ebpf_ssl.go @@ -569,6 +569,10 @@ func (o *sslProgram) GetStats() *protocols.ProtocolStats { return nil } +// ReleaseStats is a no-op. +func (o *sslProgram) ReleaseStats() { +} + const ( // Defined in https://man7.org/linux/man-pages/man5/proc.5.html. taskCommLen = 16 diff --git a/pkg/network/usm/monitor.go b/pkg/network/usm/monitor.go index 4ee3d2e535d68..2cf457862394e 100644 --- a/pkg/network/usm/monitor.go +++ b/pkg/network/usm/monitor.go @@ -196,6 +196,11 @@ func (m *Monitor) GetProtocolStats() map[protocols.ProtocolType]interface{} { return m.ebpfProgram.getProtocolStats() } +// ReleaseStats release stats related objects. +func (m *Monitor) ReleaseStats() { + m.ebpfProgram.releaseStats() +} + // Stop HTTP monitoring func (m *Monitor) Stop() { if m == nil { diff --git a/pkg/network/usm/monitor_testutil.go b/pkg/network/usm/monitor_testutil.go index 48f63271ed5ab..8650fc8e5194a 100644 --- a/pkg/network/usm/monitor_testutil.go +++ b/pkg/network/usm/monitor_testutil.go @@ -74,6 +74,7 @@ func (p *protocolMock) Stop(mgr *manager.Manager) { func (p *protocolMock) DumpMaps(io.Writer, string, *ebpf.Map) {} func (p *protocolMock) GetStats() *protocols.ProtocolStats { return nil } +func (p *protocolMock) ReleaseStats() {} // IsBuildModeSupported returns always true, as the mock is supported by all modes. func (*protocolMock) IsBuildModeSupported(buildmode.Type) bool { return true } diff --git a/pkg/network/usm/tests/tracer_classification_test.go b/pkg/network/usm/tests/tracer_classification_test.go index 1ddaa35bed5a5..0c048ffe74dfc 100644 --- a/pkg/network/usm/tests/tracer_classification_test.go +++ b/pkg/network/usm/tests/tracer_classification_test.go @@ -367,6 +367,7 @@ func waitForConnectionsWithProtocol(t *testing.T, tr *tracer.Tracer, targetAddr, if failed { t.Log(conns) } + tr.ReleaseUSMStats() return !failed }, 5*time.Second, 100*time.Millisecond, "could not find incoming or outgoing connections") if failed {