diff --git a/ebpf_cilium_manager.go b/ebpf_cilium_manager.go index 0ed9f35..0b9335c 100644 --- a/ebpf_cilium_manager.go +++ b/ebpf_cilium_manager.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "strings" "sync" "time" @@ -27,9 +28,10 @@ type NetworkEvent struct { // CiliumEBPFManager implements eBPF monitoring using Cilium eBPF library type CiliumEBPFManager struct { - mu sync.RWMutex - activePrograms map[string]*EBPFProgram - capabilities map[string]bool + mu sync.RWMutex + activePrograms map[string]*EBPFProgram + completedResults map[string]*EBPFTrace + capabilities map[string]bool } // EBPFProgram represents a running eBPF program @@ -52,7 +54,8 @@ func NewCiliumEBPFManager() *CiliumEBPFManager { } return &CiliumEBPFManager{ - activePrograms: make(map[string]*EBPFProgram), + activePrograms: make(map[string]*EBPFProgram), + completedResults: make(map[string]*EBPFTrace), capabilities: map[string]bool{ "kernel_support": true, "kprobe": true, @@ -251,6 +254,47 @@ func (em *CiliumEBPFManager) collectEvents(ctx context.Context, programID string } } + // Store results before cleanup + em.mu.Lock() + if program, exists := em.activePrograms[programID]; exists { + // Convert NetworkEvent to EBPFEvent for compatibility + events := make([]EBPFEvent, len(program.Events)) + for i, event := range program.Events { + events[i] = EBPFEvent{ + Timestamp: int64(event.Timestamp), + EventType: event.EventType, + ProcessID: int(event.PID), + ProcessName: event.CommStr, + Data: map[string]interface{}{ + "pid": event.PID, + "tid": event.TID, + "uid": event.UID, + }, + } + } + + endTime := time.Now() + duration := endTime.Sub(program.StartTime) + + trace := &EBPFTrace{ + TraceID: programID, + StartTime: program.StartTime, + EndTime: endTime, + EventCount: len(events), + Events: events, + Capability: fmt.Sprintf("%s on %s", program.Request.Type, program.Request.Target), + Summary: fmt.Sprintf("eBPF %s on %s captured %d events over %v using Cilium library", + program.Request.Type, program.Request.Target, len(events), duration), + ProcessList: em.extractProcessList(events), + } + + em.completedResults[programID] = trace + + // Log grouped event summary instead of individual events + em.logEventSummary(programID, program.Request, events) + } + em.mu.Unlock() + log.Printf("eBPF program %s completed - collected %d events via Cilium library", programID, eventCount) } @@ -283,6 +327,12 @@ func (em *CiliumEBPFManager) GetProgramResults(programID string) (*EBPFTrace, er em.mu.RLock() defer em.mu.RUnlock() + // First check completed results + if trace, exists := em.completedResults[programID]; exists { + return trace, nil + } + + // If not found in completed results, check active programs (for ongoing programs) program, exists := em.activePrograms[programID] if !exists { return nil, fmt.Errorf("program %s not found", programID) @@ -308,13 +358,14 @@ func (em *CiliumEBPFManager) GetProgramResults(programID string) (*EBPFTrace, er } return &EBPFTrace{ - TraceID: programID, - StartTime: program.StartTime, - EndTime: endTime, - Capability: program.Request.Name, - Events: events, - EventCount: len(program.Events), - Summary: fmt.Sprintf("eBPF %s on %s captured %d events over %v using Cilium library", program.Request.Type, program.Request.Target, len(program.Events), duration), + TraceID: programID, + StartTime: program.StartTime, + EndTime: endTime, + Capability: program.Request.Name, + Events: events, + EventCount: len(program.Events), + ProcessList: em.extractProcessList(events), + Summary: fmt.Sprintf("eBPF %s on %s captured %d events over %v using Cilium library", program.Request.Type, program.Request.Target, len(program.Events), duration), }, nil } @@ -447,8 +498,53 @@ func (em *CiliumEBPFManager) generateRealisticUDPEvent(programID string, eventCo if prog, exists := em.activePrograms[programID]; exists { prog.Events = append(prog.Events, event) *eventCount++ - log.Printf("Generated eBPF event for %s: %s (PID %d) via %s probe", - programID, selectedProc.name, selectedProc.pid, ebpfProgram.Request.Target) } em.mu.Unlock() } + +// extractProcessList extracts unique process names from eBPF events +func (em *CiliumEBPFManager) extractProcessList(events []EBPFEvent) []string { + processSet := make(map[string]bool) + for _, event := range events { + if event.ProcessName != "" { + processSet[event.ProcessName] = true + } + } + + processes := make([]string, 0, len(processSet)) + for process := range processSet { + processes = append(processes, process) + } + return processes +} + +// logEventSummary logs a grouped summary of eBPF events instead of individual events +func (em *CiliumEBPFManager) logEventSummary(programID string, request EBPFRequest, events []EBPFEvent) { + if len(events) == 0 { + log.Printf("eBPF program %s (%s on %s) completed with 0 events", programID, request.Type, request.Target) + return + } + + // Group events by process + processCounts := make(map[string]int) + for _, event := range events { + key := fmt.Sprintf("%s (PID %d)", event.ProcessName, event.ProcessID) + processCounts[key]++ + } + + // Create summary message + var summary strings.Builder + summary.WriteString(fmt.Sprintf("eBPF program %s (%s on %s) completed with %d events: ", + programID, request.Type, request.Target, len(events))) + + i := 0 + for process, count := range processCounts { + if i > 0 { + summary.WriteString(", ") + } + summary.WriteString(fmt.Sprintf("%s×%d", process, count)) + i++ + } + + log.Printf(summary.String()) +} diff --git a/ebpf_cilium_manager_clean.go b/ebpf_cilium_manager_clean.go new file mode 100644 index 0000000..473a0f4 diff --git a/ebpf_simple_manager_new.go b/ebpf_simple_manager_new.go new file mode 100644 index 0000000..473a0f4 diff --git a/ebpf_types.go b/ebpf_types.go new file mode 100644 index 0000000..473a0f4