Repository: cilium/ebpf
Pull request #766 (2022-08-23 09:18:44)

feature: define `sys.MapFlags` and re-export it for map flags feature detection
As requested in https://github.com/cilium/ebpf/pull/673 this PR defines a new internal type `sys.MapFlags` describing the different map flags constant, and use a re-exported version of it as the type argument for `HaveMapFlag` feature detection API

paulcacheux: Oh no worries ! Please let me know if something else is required

Patch:
diff --git a/features/map.go b/features/map.go
index e83e48c..c9a70df 100644
--- a/features/map.go
+++ b/features/map.go
@@ -13,7 +13,7 @@ import (
 
 func init() {
 	mc.mapTypes = make(map[ebpf.MapType]error)
-	mc.mapFlags = make(map[uint32]error)
+	mc.mapFlags = make(map[MapFlags]error)
 }
 
 var (
@@ -23,7 +23,7 @@ var (
 type mapCache struct {
 	sync.Mutex
 	mapTypes map[ebpf.MapType]error
-	mapFlags map[uint32]error
+	mapFlags map[MapFlags]error
 }
 
 func createMapTypeAttr(mt ebpf.MapType) *sys.MapCreateAttr {
@@ -164,10 +164,23 @@ func isStorageMap(mt ebpf.MapType) bool {
 	return false
 }
 
+// MapFlags document which flags may be feature probed.
+type MapFlags = sys.MapFlags
+
+// Flags which may be feature probed.
+const (
+	BPF_F_NO_PREALLOC MapFlags = unix.BPF_F_NO_PREALLOC
+	BPF_F_RDONLY_PROG MapFlags = unix.BPF_F_RDONLY_PROG
+	BPF_F_WRONLY_PROG MapFlags = unix.BPF_F_WRONLY_PROG
+	BPF_F_MMAPABLE    MapFlags = unix.BPF_F_MMAPABLE
+	BPF_F_INNER_MAP   MapFlags = unix.BPF_F_INNER_MAP
+)
+
 // HaveMapFlag probes the running kernel for the availability of the specified map flag.
 //
+// Returns an error if flag is not one of the flags declared in this package.
 // See the package documentation for the meaning of the error return value.
-func HaveMapFlag(flag uint32) (err error) {
+func HaveMapFlag(flag MapFlags) (err error) {
 	defer func() {
 		// This closure modifies a named return variable.
 		err = wrapProbeErrors(err)
@@ -176,7 +189,7 @@ func HaveMapFlag(flag uint32) (err error) {
 	return haveMapFlag(flag)
 }
 
-func haveMapFlag(flag uint32) error {
+func haveMapFlag(flag MapFlags) error {
 	mc.Lock()
 	defer mc.Unlock()
 	err, ok := mc.mapFlags[flag]
@@ -204,7 +217,7 @@ func haveMapFlag(flag uint32) error {
 	return err
 }
 
-func createMapFlagTypeAttr(flag uint32) (*sys.MapCreateAttr, error) {
+func createMapFlagTypeAttr(flag MapFlags) (*sys.MapCreateAttr, error) {
 	a := &sys.MapCreateAttr{
 		KeySize:    4,
 		ValueSize:  4,
diff --git a/info.go b/info.go
index ae77bc6..8f42173 100644
--- a/info.go
+++ b/info.go
@@ -48,7 +48,7 @@ func newMapInfoFromFd(fd *sys.FD) (*MapInfo, error) {
 		info.KeySize,
 		info.ValueSize,
 		info.MaxEntries,
-		info.MapFlags,
+		uint32(info.MapFlags),
 		unix.ByteSliceToString(info.Name[:]),
 	}, nil
 }
diff --git a/internal/cmd/gentypes/main.go b/internal/cmd/gentypes/main.go
index 98786be..cc9d88c 100644
--- a/internal/cmd/gentypes/main.go
+++ b/internal/cmd/gentypes/main.go
@@ -66,6 +66,7 @@ func generateTypes(spec *btf.Spec) ([]byte, error) {
 	btfID := &btf.Int{Size: 4}
 	pointer := &btf.Int{Size: 8}
 	logLevel := &btf.Int{Size: 4}
+	mapFlags := &btf.Int{Size: 4}
 
 	// Pre-declare handwritten types so that generated types can refer to them.
 	var (
@@ -74,6 +75,7 @@ func generateTypes(spec *btf.Spec) ([]byte, error) {
 		_ sys.BTFID
 		_ sys.Pointer
 		_ sys.LogLevel
+		_ sys.MapFlags
 	)
 
 	gf := &btf.GoFormatter{
@@ -83,6 +85,7 @@ func generateTypes(spec *btf.Spec) ([]byte, error) {
 			btfID:    "BTFID",
 			pointer:  "Pointer",
 			logLevel: "LogLevel",
+			mapFlags: "MapFlags",
 		},
 		Identifier: internal.Identifier,
 		EnumIdentifier: func(name, element string) string {
@@ -167,7 +170,10 @@ import (
 		},
 		{
 			"MapInfo", "bpf_map_info",
-			[]patch{replace(objName, "name")},
+			[]patch{
+				replace(objName, "name"),
+				replace(mapFlags, "map_flags"),
+			},
 		},
 		{
 			"BtfInfo", "bpf_btf_info",
@@ -228,6 +234,7 @@ import (
 			[]patch{
 				replace(objName, "map_name"),
 				replace(enumTypes["MapType"], "map_type"),
+				replace(mapFlags, "map_flags"),
 			},
 		},
 		{
diff --git a/internal/sys/syscall.go b/internal/sys/syscall.go
index 871772d..6dde230 100644
--- a/internal/sys/syscall.go
+++ b/internal/sys/syscall.go
@@ -110,6 +110,9 @@ type LinkID uint32
 // BTFID uniquely identifies a BTF blob loaded into the kernel.
 type BTFID uint32
 
+// MapFlags control map behaviour.
+type MapFlags uint32
+
 // wrappedErrno wraps syscall.Errno to prevent direct comparisons with
 // syscall.E* or unix.E* constants.
 //
diff --git a/internal/sys/types.go b/internal/sys/types.go
index f1fde4e..fd2ec24 100644
--- a/internal/sys/types.go
+++ b/internal/sys/types.go
@@ -474,7 +474,7 @@ type MapInfo struct {
 	KeySize               uint32
 	ValueSize             uint32
 	MaxEntries            uint32
-	MapFlags              uint32
+	MapFlags              MapFlags
 	Name                  ObjName
 	Ifindex               uint32
 	BtfVmlinuxValueTypeId uint32
@@ -680,7 +680,7 @@ type MapCreateAttr struct {
 	KeySize               uint32
 	ValueSize             uint32
 	MaxEntries            uint32
-	MapFlags              uint32
+	MapFlags              MapFlags
 	InnerMapFd            uint32
 	NumaNode              uint32
 	MapName               ObjName
diff --git a/map.go b/map.go
index e4a6c87..6a134ae 100644
--- a/map.go
+++ b/map.go
@@ -413,7 +413,7 @@ func (spec *MapSpec) createMap(inner *sys.FD, opts MapOptions, handles *handleCa
 		KeySize:    spec.KeySize,
 		ValueSize:  spec.ValueSize,
 		MaxEntries: spec.MaxEntries,
-		MapFlags:   spec.Flags,
+		MapFlags:   sys.MapFlags(spec.Flags),
 		NumaNode:   spec.NumaNode,
 	}
 


Test patch:
diff --git a/features/map_test.go b/features/map_test.go
index d87237f..9b08fc1 100644
--- a/features/map_test.go
+++ b/features/map_test.go
@@ -9,7 +9,6 @@ import (
 
 	"github.com/cilium/ebpf"
 	"github.com/cilium/ebpf/internal/testutils"
-	"github.com/cilium/ebpf/internal/unix"
 )
 
 var mapTypeMinVersion = map[ebpf.MapType]string{
@@ -66,18 +65,18 @@ func TestHaveMapType(t *testing.T) {
 }
 
 type haveMapFlagsTestEntry struct {
-	flags            uint32
+	flags            MapFlags
 	minKernelVersion string
 	description      string
 }
 
 func TestHaveMapFlag(t *testing.T) {
 	mapFlagTestEntries := []haveMapFlagsTestEntry{
-		{unix.BPF_F_RDONLY_PROG, "5.2", "read_only_array_map"},
-		{unix.BPF_F_WRONLY_PROG, "5.2", "write_only_array_map"},
-		{unix.BPF_F_MMAPABLE, "5.5", "mmapable_array_map"},
-		{unix.BPF_F_INNER_MAP, "5.10", "inner_map_array_map"},
-		{unix.BPF_F_NO_PREALLOC, "4.6", "no_prealloc_hash_map"},
+		{BPF_F_RDONLY_PROG, "5.2", "read_only_array_map"},
+		{BPF_F_WRONLY_PROG, "5.2", "write_only_array_map"},
+		{BPF_F_MMAPABLE, "5.5", "mmapable_array_map"},
+		{BPF_F_INNER_MAP, "5.10", "inner_map_array_map"},
+		{BPF_F_NO_PREALLOC, "4.6", "no_prealloc_hash_map"},
 	}
 
 	for _, entry := range mapFlagTestEntries {