diff --git a/.mk/bc.mk b/.mk/bc.mk index 47324de2c..c0b5f2db8 100644 --- a/.mk/bc.mk +++ b/.mk/bc.mk @@ -32,7 +32,7 @@ define MAPS "direct_flows":"ringbuf", "aggregated_flows":"hash", "additional_flow_metrics":"per_cpu_hash", - "packets_record":"ringbuf", + "packet_record":"ringbuf", "dns_flows":"hash", "global_counters":"per_cpu_array", "filter_map":"lpm_trie", diff --git a/Makefile b/Makefile index 700408d0d..aa3ebd979 100644 --- a/Makefile +++ b/Makefile @@ -164,6 +164,11 @@ test: ## Test code using go test @echo "### Testing code" GOOS=$(GOOS) go test -mod vendor ./pkg/... ./cmd/... -coverpkg=./... -coverprofile cover.all.out +.PHONY: verify-maps +verify-maps: ## Verify map names consistency across all sources + @echo "### Verifying map names consistency" + go test -v ./pkg/maps + .PHONY: test-race test-race: ## Test code using go test -race @echo "### Testing code for race conditions" diff --git a/pkg/maps/maps.go b/pkg/maps/maps.go new file mode 100644 index 000000000..d2d988459 --- /dev/null +++ b/pkg/maps/maps.go @@ -0,0 +1,15 @@ +package maps + +// Map names +var Maps = []string{ + "direct_flows", + "aggregated_flows", + "additional_flow_metrics", + "packet_record", + "dns_flows", + "global_counters", + "filter_map", + "peer_filter_map", + "ipsec_ingress_map", + "ipsec_egress_map", +} diff --git a/pkg/maps/maps_test.go b/pkg/maps/maps_test.go new file mode 100644 index 000000000..8453411e2 --- /dev/null +++ b/pkg/maps/maps_test.go @@ -0,0 +1,104 @@ +package maps + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "reflect" + "regexp" + "sort" + "strings" + "testing" + + "github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMapNamesMatchEBPFDefinitions(t *testing.T) { + // Extract map names from netobserv-ebpf-agent/pkg/ebpf + ebpfMaps := extractEBPFMapNames() + + // Get map names from our package + packageMaps := Maps + + // Sort both slices for comparison + sort.Strings(ebpfMaps) + sort.Strings(packageMaps) + fmt.Printf("eBPF maps: %+v\n", ebpfMaps) + fmt.Printf("Package maps: %+v\n", packageMaps) + + // Verify they match + assert.Equal(t, ebpfMaps, packageMaps, + "Map names in pkg/maps/maps.go do not match eBPF definitions in bpf/maps_definition.h") +} + +func TestMapNamesMatchBcMk(t *testing.T) { + // Extract map names from .mk/bc.mk + bcMaps, err := extractBcMkMapNames("../../.mk/bc.mk") + require.NoError(t, err, "Failed to extract map names from .mk/bc.mk") + + // Get map names from our package + packageMaps := Maps + + // Sort both slices for comparison + sort.Strings(bcMaps) + sort.Strings(packageMaps) + fmt.Printf("bc.mk maps: %+v\n", bcMaps) + fmt.Printf("Package maps: %+v\n", packageMaps) + + // Verify they match + assert.Equal(t, bcMaps, packageMaps, + "Map names in pkg/maps/maps.go do not match definitions in .mk/bc.mk.\n"+ + "If you've added/removed maps, please update both files.") +} + +// extractBcMkMapNames parses the .mk/bc.mk file and extracts map names from the MAPS JSON +func extractBcMkMapNames(filePath string) ([]string, error) { + content, err := os.ReadFile(filePath) + if err != nil { + return nil, err + } + + // Find the MAPS definition block + mapsRegex := regexp.MustCompile(`define MAPS\s*\n((.|\s)*?)\nendef`) + matches := mapsRegex.FindStringSubmatch(string(content)) + + if len(matches) < 2 { + return nil, errors.New("Could not find MAPS definition in .mk/bc.mk") + } + + // Extract the JSON content + jsonContent := strings.TrimSpace(matches[1]) + + // Parse JSON to extract map names + var mapsData map[string]string + if err := json.Unmarshal([]byte(jsonContent), &mapsData); err != nil { + return nil, err + } + + // Extract just the map names (keys) + var mapNames []string + for mapName := range mapsData { + mapNames = append(mapNames, mapName) + } + + return mapNames, nil +} + +// extractEBPFMapNames extracts map names from the compiled eBPF agent +func extractEBPFMapNames() []string { + var maps []string + mapType := reflect.ValueOf(ebpf.BpfMapSpecs{}) + for i := 0; i < mapType.NumField(); i++ { + val := reflect.Indirect(mapType) + mapName := val.Type().Field(i).Tag.Get("ebpf") + + if mapName != "" { + maps = append(maps, mapName) + } + } + + return maps +}