github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/map_definition.go (about)

     1  package gobpfld
     2  
     3  import (
     4  	"fmt"
     5  	"unsafe"
     6  
     7  	"github.com/dylandreimerink/gobpfld/bpfsys"
     8  	"github.com/dylandreimerink/gobpfld/bpftypes"
     9  	"github.com/dylandreimerink/gobpfld/kernelsupport"
    10  )
    11  
    12  // bpfMapDefSize is the size of BPFMapDef in bytes
    13  var bpfMapDefSize = int(unsafe.Sizeof(BPFMapDef{}))
    14  
    15  type BPFMapDef struct {
    16  	// Type describes map type this map is
    17  	Type bpftypes.BPFMapType
    18  	// KeySize is the size of the map key in bytes
    19  	KeySize uint32
    20  	// ValueSize is the size of the map value in bytes
    21  	ValueSize uint32
    22  	// MaxEntries is the maximum amount of entries in a map. Depending on the map type and flags, memory for all of
    23  	// these entries might be allocated on map creation or dynamically when inserting.
    24  	MaxEntries uint32
    25  	// Flags can be used to ask the kernel for special behavior, not all flags are allowed on all map types.
    26  	Flags bpftypes.BPFMapFlags
    27  }
    28  
    29  // Equal checks if two map definitions are functionally identical
    30  func (def BPFMapDef) Equal(other BPFMapDef) bool {
    31  	return def.Type == other.Type &&
    32  		def.KeySize == other.KeySize &&
    33  		def.ValueSize == other.ValueSize &&
    34  		def.MaxEntries == other.MaxEntries &&
    35  		def.Flags == other.Flags
    36  }
    37  
    38  // Validate checks if the map definition is valid, the kernel also does these checks but if the kernel finds an error
    39  // it doesn't return a nice error message. This give a better user experience.
    40  func (def BPFMapDef) Validate() error {
    41  	if kfeat, found := mapTypeToKFeature[def.Type]; found {
    42  		if !kernelsupport.CurrentFeatures.Map.Has(kfeat) {
    43  			return fmt.Errorf("map type '%s' not supported: %s", def.Type, bpfsys.ErrNotSupported)
    44  		}
    45  	}
    46  
    47  	if err := def.validateSizes(); err != nil {
    48  		return err
    49  	}
    50  
    51  	if err := def.validateFlags(); err != nil {
    52  		return err
    53  	}
    54  
    55  	switch def.Type {
    56  	case bpftypes.BPF_MAP_TYPE_STACK_TRACE:
    57  		// TODO value_size % 8 == 0
    58  		// TODO stack build id check https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/stackmap.c#L108
    59  	case bpftypes.BPF_MAP_TYPE_DEVMAP, bpftypes.BPF_MAP_TYPE_DEVMAP_HASH:
    60  		// TODO check value_size, which is dependant on host architecture
    61  	case bpftypes.BPF_MAP_TYPE_SOCKMAP:
    62  		// TODO check value_size, which is dependant on host architecture
    63  	case bpftypes.BPF_MAP_TYPE_CPUMAP:
    64  		// TODO check value_size, which is dependant on host architecture
    65  	case bpftypes.BPF_MAP_TYPE_CGROUP_STORAGE, bpftypes.BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE,
    66  		bpftypes.BPF_MAP_TYPE_INODE_STORAGE, bpftypes.BPF_MAP_TYPE_TASK_STORAGE:
    67  		// TODO check key_size
    68  	case bpftypes.BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:
    69  		// TODO check value size
    70  	case bpftypes.BPF_MAP_TYPE_STRUCT_OPS:
    71  		// TODO check key size
    72  	case bpftypes.BPF_MAP_TYPE_RINGBUF:
    73  		// TODO max_entries is a power of 2 and page aligned
    74  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/ringbuf.c#L154
    75  	}
    76  
    77  	return nil
    78  }
    79  
    80  func (def BPFMapDef) validateFlags() error {
    81  	requiredFlags := map[bpftypes.BPFMapType][]bpftypes.BPFMapFlags{
    82  		bpftypes.BPF_MAP_TYPE_LPM_TRIE: {
    83  			bpftypes.BPFMapFlagsNoPreAlloc,
    84  		},
    85  	}
    86  
    87  	if rFlags, ok := requiredFlags[def.Type]; ok {
    88  		for _, requiredFlag := range rFlags {
    89  			if def.Flags&requiredFlag == 0 {
    90  				return fmt.Errorf("maps of type %s must have the the %s flag set, map has the following flags set: %s",
    91  					def.Type, requiredFlag, def.Flags)
    92  			}
    93  		}
    94  	}
    95  
    96  	permittedFlags := map[bpftypes.BPFMapType]bpftypes.BPFMapFlags{
    97  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/hashtab.c#L369
    98  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/hashtab.c#L17
    99  		bpftypes.BPF_MAP_TYPE_HASH: bpftypes.BPFMapFlagsNoPreAlloc |
   100  			bpftypes.BPFMapFlagsNUMANode |
   101  			bpftypes.BPFMapFlagsReadOnly |
   102  			bpftypes.BPFMapFlagsWriteOnly |
   103  			bpftypes.BPFMapFlagsReadOnlyProg |
   104  			bpftypes.BPFMapFlagsWriteOnlyProg |
   105  			bpftypes.BPFMapFlagsZeroSeed,
   106  
   107  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L631
   108  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L17
   109  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L51
   110  		bpftypes.BPF_MAP_TYPE_ARRAY: bpftypes.BPFMapFlagsNUMANode |
   111  			bpftypes.BPFMapFlagsMMapable |
   112  			bpftypes.BPFMapFlagsReadOnly |
   113  			bpftypes.BPFMapFlagsWriteOnly |
   114  			bpftypes.BPFMapFlagsReadOnlyProg |
   115  			bpftypes.BPFMapFlagsWriteOnlyProg |
   116  			bpftypes.BPFMapFlagsInnerMap,
   117  
   118  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L1046
   119  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L668
   120  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L59
   121  		bpftypes.BPF_MAP_TYPE_PROG_ARRAY: bpftypes.BPFMapFlagsNUMANode |
   122  			bpftypes.BPFMapFlagsReadOnly |
   123  			bpftypes.BPFMapFlagsWriteOnly,
   124  
   125  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L1153
   126  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L668
   127  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L59
   128  		bpftypes.BPF_MAP_TYPE_PERF_EVENT_ARRAY: bpftypes.BPFMapFlagsNUMANode |
   129  			bpftypes.BPFMapFlagsReadOnly |
   130  			bpftypes.BPFMapFlagsWriteOnly,
   131  
   132  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/hashtab.c#L369
   133  		bpftypes.BPF_MAP_TYPE_PERCPU_HASH: bpftypes.BPFMapFlagsNoPreAlloc |
   134  			bpftypes.BPFMapFlagsNUMANode |
   135  			bpftypes.BPFMapFlagsReadOnly |
   136  			bpftypes.BPFMapFlagsWriteOnly |
   137  			bpftypes.BPFMapFlagsReadOnlyProg |
   138  			bpftypes.BPFMapFlagsWriteOnlyProg |
   139  			bpftypes.BPFMapFlagsZeroSeed,
   140  
   141  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L654
   142  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L17
   143  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L59
   144  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L64
   145  		bpftypes.BPF_MAP_TYPE_PERCPU_ARRAY: bpftypes.BPFMapFlagsNUMANode |
   146  			bpftypes.BPFMapFlagsReadOnly |
   147  			bpftypes.BPFMapFlagsWriteOnly |
   148  			bpftypes.BPFMapFlagsReadOnlyProg |
   149  			bpftypes.BPFMapFlagsWriteOnlyProg,
   150  
   151  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/stackmap.c#L16
   152  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/stackmap.c#L89
   153  		bpftypes.BPF_MAP_TYPE_STACK_TRACE: bpftypes.BPFMapFlagsNUMANode |
   154  			bpftypes.BPFMapFlagsReadOnly |
   155  			bpftypes.BPFMapFlagsWriteOnly |
   156  			bpftypes.BPFMapFlagsStackBuildID,
   157  
   158  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L1190
   159  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L668
   160  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L59
   161  		bpftypes.BPF_MAP_TYPE_CGROUP_ARRAY: bpftypes.BPFMapFlagsNUMANode |
   162  			bpftypes.BPFMapFlagsReadOnly |
   163  			bpftypes.BPFMapFlagsWriteOnly,
   164  
   165  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/hashtab.c#L369
   166  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/hashtab.c#L404
   167  		bpftypes.BPF_MAP_TYPE_LRU_HASH: bpftypes.BPFMapFlagsNoCommonLRU |
   168  			bpftypes.BPFMapFlagsNUMANode |
   169  			bpftypes.BPFMapFlagsReadOnly |
   170  			bpftypes.BPFMapFlagsWriteOnly |
   171  			bpftypes.BPFMapFlagsReadOnlyProg |
   172  			bpftypes.BPFMapFlagsWriteOnlyProg |
   173  			bpftypes.BPFMapFlagsZeroSeed,
   174  
   175  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/hashtab.c#L369
   176  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/hashtab.c#L404
   177  		bpftypes.BPF_MAP_TYPE_LRU_PERCPU_HASH: bpftypes.BPFMapFlagsNoCommonLRU |
   178  			bpftypes.BPFMapFlagsNUMANode |
   179  			bpftypes.BPFMapFlagsReadOnly |
   180  			bpftypes.BPFMapFlagsWriteOnly |
   181  			bpftypes.BPFMapFlagsReadOnlyProg |
   182  			bpftypes.BPFMapFlagsWriteOnlyProg |
   183  			bpftypes.BPFMapFlagsZeroSeed,
   184  
   185  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/lpm_trie.c#L537
   186  		bpftypes.BPF_MAP_TYPE_LPM_TRIE: bpftypes.BPFMapFlagsNoPreAlloc |
   187  			bpftypes.BPFMapFlagsNUMANode |
   188  			bpftypes.BPFMapFlagsReadOnly |
   189  			bpftypes.BPFMapFlagsWriteOnly |
   190  			bpftypes.BPFMapFlagsReadOnlyProg |
   191  			bpftypes.BPFMapFlagsWriteOnlyProg,
   192  
   193  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L1276
   194  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L668
   195  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L59
   196  		bpftypes.BPF_MAP_TYPE_ARRAY_OF_MAPS: bpftypes.BPFMapFlagsNUMANode |
   197  			bpftypes.BPFMapFlagsReadOnly |
   198  			bpftypes.BPFMapFlagsWriteOnly,
   199  
   200  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L1046
   201  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L668
   202  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/arraymap.c#L59
   203  		bpftypes.BPF_MAP_TYPE_HASH_OF_MAPS: bpftypes.BPFMapFlagsNUMANode |
   204  			bpftypes.BPFMapFlagsReadOnly |
   205  			bpftypes.BPFMapFlagsWriteOnly,
   206  
   207  		bpftypes.BPF_MAP_TYPE_DEVMAP: bpftypes.BPFMapFlagsNUMANode |
   208  			bpftypes.BPFMapFlagsReadOnly |
   209  			bpftypes.BPFMapFlagsWriteOnly,
   210  
   211  		bpftypes.BPF_MAP_TYPE_SOCKMAP: bpftypes.BPFMapFlagsNUMANode |
   212  			bpftypes.BPFMapFlagsReadOnly |
   213  			bpftypes.BPFMapFlagsWriteOnly,
   214  
   215  		bpftypes.BPF_MAP_TYPE_CPUMAP: bpftypes.BPFMapFlagsNUMANode,
   216  
   217  		bpftypes.BPF_MAP_TYPE_XSKMAP: bpftypes.BPFMapFlagsNUMANode |
   218  			bpftypes.BPFMapFlagsReadOnly |
   219  			bpftypes.BPFMapFlagsWriteOnly,
   220  
   221  		// bpftypes.BPF_MAP_TYPE_SOCKHASH:
   222  
   223  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/local_storage.c#L18
   224  		bpftypes.BPF_MAP_TYPE_CGROUP_STORAGE: bpftypes.BPFMapFlagsNUMANode |
   225  			bpftypes.BPFMapFlagsReadOnly |
   226  			bpftypes.BPFMapFlagsWriteOnly |
   227  			bpftypes.BPFMapFlagsReadOnlyProg |
   228  			bpftypes.BPFMapFlagsWriteOnlyProg,
   229  
   230  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/reuseport_array.c#L43
   231  		bpftypes.BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: bpftypes.BPFMapFlagsNUMANode |
   232  			bpftypes.BPFMapFlagsMMapable |
   233  			bpftypes.BPFMapFlagsReadOnly |
   234  			bpftypes.BPFMapFlagsWriteOnly |
   235  			bpftypes.BPFMapFlagsReadOnlyProg |
   236  			bpftypes.BPFMapFlagsWriteOnlyProg |
   237  			bpftypes.BPFMapFlagsInnerMap,
   238  
   239  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/local_storage.c#L18
   240  		bpftypes.BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: bpftypes.BPFMapFlagsNUMANode |
   241  			bpftypes.BPFMapFlagsReadOnly |
   242  			bpftypes.BPFMapFlagsWriteOnly |
   243  			bpftypes.BPFMapFlagsReadOnlyProg |
   244  			bpftypes.BPFMapFlagsWriteOnlyProg,
   245  
   246  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/queue_stack_maps.c#L13
   247  		bpftypes.BPF_MAP_TYPE_QUEUE: bpftypes.BPFMapFlagsNUMANode |
   248  			bpftypes.BPFMapFlagsReadOnly |
   249  			bpftypes.BPFMapFlagsWriteOnly |
   250  			bpftypes.BPFMapFlagsReadOnlyProg |
   251  			bpftypes.BPFMapFlagsWriteOnlyProg,
   252  
   253  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/queue_stack_maps.c#L13
   254  		bpftypes.BPF_MAP_TYPE_STACK: bpftypes.BPFMapFlagsNUMANode |
   255  			bpftypes.BPFMapFlagsReadOnly |
   256  			bpftypes.BPFMapFlagsWriteOnly |
   257  			bpftypes.BPFMapFlagsReadOnlyProg |
   258  			bpftypes.BPFMapFlagsWriteOnlyProg,
   259  
   260  		// bpftypes.BPF_MAP_TYPE_SK_STORAGE:
   261  
   262  		bpftypes.BPF_MAP_TYPE_DEVMAP_HASH: bpftypes.BPFMapFlagsNUMANode |
   263  			bpftypes.BPFMapFlagsReadOnly |
   264  			bpftypes.BPFMapFlagsWriteOnly,
   265  
   266  		// https://elixir.bootlin.com/linux/v5.11.15/source/kernel/bpf/bpf_struct_ops.c#L540
   267  		bpftypes.BPF_MAP_TYPE_STRUCT_OPS: 0,
   268  
   269  		bpftypes.BPF_MAP_TYPE_RINGBUF: bpftypes.BPFMapFlagsNUMANode,
   270  
   271  		bpftypes.BPF_MAP_TYPE_INODE_STORAGE: bpftypes.BPFMapFlagsNUMANode |
   272  			bpftypes.BPFMapFlagsReadOnly |
   273  			bpftypes.BPFMapFlagsWriteOnly |
   274  			bpftypes.BPFMapFlagsReadOnlyProg |
   275  			bpftypes.BPFMapFlagsWriteOnlyProg,
   276  
   277  		bpftypes.BPF_MAP_TYPE_TASK_STORAGE: bpftypes.BPFMapFlagsNUMANode |
   278  			bpftypes.BPFMapFlagsReadOnly |
   279  			bpftypes.BPFMapFlagsWriteOnly |
   280  			bpftypes.BPFMapFlagsReadOnlyProg |
   281  			bpftypes.BPFMapFlagsWriteOnlyProg,
   282  	}
   283  
   284  	if pFlags, ok := permittedFlags[def.Type]; ok {
   285  		// For each flag that exists
   286  		for f := bpftypes.BPFMapFlags(1); f < bpftypes.BPFMapFlagsMax; f = f << 1 {
   287  			// If this flag is in the def and it is not permitted
   288  			if def.Flags&f > 0 && f&pFlags == 0 {
   289  				return fmt.Errorf(
   290  					"maps of type %s may not have the %s flag set, "+
   291  						"map has the following flags set: %s, "+
   292  						"only the following flags are allowed: %s",
   293  					def.Type, f, def.Flags, pFlags)
   294  			}
   295  		}
   296  
   297  		// If both the program read-only and write-only flags are set
   298  		if def.Flags&(bpftypes.BPFMapFlagsReadOnlyProg|bpftypes.BPFMapFlagsWriteOnlyProg) ==
   299  			(bpftypes.BPFMapFlagsReadOnlyProg | bpftypes.BPFMapFlagsWriteOnlyProg) {
   300  			return fmt.Errorf(
   301  				"the %s and %s flags are mutually exclusive",
   302  				bpftypes.BPFMapFlagsReadOnlyProg,
   303  				bpftypes.BPFMapFlagsWriteOnlyProg,
   304  			)
   305  		}
   306  	}
   307  
   308  	return nil
   309  }
   310  
   311  func (def BPFMapDef) validateSizes() error {
   312  	keySizes := map[bpftypes.BPFMapType]uint32{
   313  		bpftypes.BPF_MAP_TYPE_ARRAY:               4,
   314  		bpftypes.BPF_MAP_TYPE_PROG_ARRAY:          4,
   315  		bpftypes.BPF_MAP_TYPE_PERF_EVENT_ARRAY:    4,
   316  		bpftypes.BPF_MAP_TYPE_PERCPU_ARRAY:        4,
   317  		bpftypes.BPF_MAP_TYPE_STACK_TRACE:         4,
   318  		bpftypes.BPF_MAP_TYPE_CGROUP_ARRAY:        4,
   319  		bpftypes.BPF_MAP_TYPE_ARRAY_OF_MAPS:       4,
   320  		bpftypes.BPF_MAP_TYPE_DEVMAP:              4,
   321  		bpftypes.BPF_MAP_TYPE_SOCKMAP:             4,
   322  		bpftypes.BPF_MAP_TYPE_CPUMAP:              4,
   323  		bpftypes.BPF_MAP_TYPE_XSKMAP:              4,
   324  		bpftypes.BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: 4,
   325  		bpftypes.BPF_MAP_TYPE_QUEUE:               0,
   326  		bpftypes.BPF_MAP_TYPE_STACK:               0,
   327  		bpftypes.BPF_MAP_TYPE_DEVMAP_HASH:         4,
   328  		bpftypes.BPF_MAP_TYPE_RINGBUF:             0,
   329  	}
   330  
   331  	if exactSize, ok := keySizes[def.Type]; ok && exactSize != def.KeySize {
   332  		return fmt.Errorf("maps of type %s must always have a key size of %d bytes, "+
   333  			"key size of this map is %d bytes", def.Type, exactSize, def.KeySize)
   334  	}
   335  
   336  	minKeySizes := map[bpftypes.BPFMapType]uint32{
   337  		bpftypes.BPF_MAP_TYPE_HASH:            1,
   338  		bpftypes.BPF_MAP_TYPE_PERCPU_HASH:     1,
   339  		bpftypes.BPF_MAP_TYPE_LRU_HASH:        1,
   340  		bpftypes.BPF_MAP_TYPE_LRU_PERCPU_HASH: 1,
   341  		bpftypes.BPF_MAP_TYPE_LPM_TRIE:        6,
   342  	}
   343  
   344  	if minSize, ok := minKeySizes[def.Type]; ok && def.KeySize < minSize {
   345  		return fmt.Errorf("maps of type %s must have a key size of at least %d bytes, "+
   346  			"key size of this map is %d bytes", def.Type, minSize, def.KeySize)
   347  	}
   348  
   349  	exactValueSizes := map[bpftypes.BPFMapType]uint32{
   350  		bpftypes.BPF_MAP_TYPE_PROG_ARRAY:       4,
   351  		bpftypes.BPF_MAP_TYPE_PERF_EVENT_ARRAY: 4,
   352  		bpftypes.BPF_MAP_TYPE_CGROUP_ARRAY:     4,
   353  		bpftypes.BPF_MAP_TYPE_ARRAY_OF_MAPS:    4,
   354  		bpftypes.BPF_MAP_TYPE_HASH_OF_MAPS:     4,
   355  		bpftypes.BPF_MAP_TYPE_XSKMAP:           4,
   356  		bpftypes.BPF_MAP_TYPE_RINGBUF:          0,
   357  	}
   358  
   359  	if exactSize, ok := exactValueSizes[def.Type]; ok && exactSize != def.ValueSize {
   360  		return fmt.Errorf("maps of type %s must always have a value size of %d bytes, "+
   361  			"value size of this map is %d bytes", def.Type, exactSize, def.ValueSize)
   362  	}
   363  
   364  	minValueSizes := map[bpftypes.BPFMapType]uint32{
   365  		bpftypes.BPF_MAP_TYPE_HASH:                  1,
   366  		bpftypes.BPF_MAP_TYPE_ARRAY:                 1,
   367  		bpftypes.BPF_MAP_TYPE_PERCPU_HASH:           1,
   368  		bpftypes.BPF_MAP_TYPE_PERCPU_ARRAY:          1,
   369  		bpftypes.BPF_MAP_TYPE_STACK_TRACE:           8,
   370  		bpftypes.BPF_MAP_TYPE_LRU_HASH:              1,
   371  		bpftypes.BPF_MAP_TYPE_LRU_PERCPU_HASH:       1,
   372  		bpftypes.BPF_MAP_TYPE_LPM_TRIE:              1,
   373  		bpftypes.BPF_MAP_TYPE_CGROUP_STORAGE:        1,
   374  		bpftypes.BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: 1,
   375  		bpftypes.BPF_MAP_TYPE_QUEUE:                 1,
   376  		bpftypes.BPF_MAP_TYPE_STACK:                 1,
   377  		bpftypes.BPF_MAP_TYPE_INODE_STORAGE:         1,
   378  		bpftypes.BPF_MAP_TYPE_TASK_STORAGE:          1,
   379  	}
   380  
   381  	if minSize, ok := minValueSizes[def.Type]; ok && def.ValueSize < minSize {
   382  		return fmt.Errorf("maps of type %s must have a value size of at least %d bytes, "+
   383  			"value size of this map is %d bytes", def.Type, minSize, def.ValueSize)
   384  	}
   385  
   386  	minEntries := map[bpftypes.BPFMapType]uint32{
   387  		bpftypes.BPF_MAP_TYPE_HASH:                1,
   388  		bpftypes.BPF_MAP_TYPE_ARRAY:               1,
   389  		bpftypes.BPF_MAP_TYPE_PROG_ARRAY:          1,
   390  		bpftypes.BPF_MAP_TYPE_PERF_EVENT_ARRAY:    1,
   391  		bpftypes.BPF_MAP_TYPE_PERCPU_HASH:         1,
   392  		bpftypes.BPF_MAP_TYPE_PERCPU_ARRAY:        1,
   393  		bpftypes.BPF_MAP_TYPE_CGROUP_ARRAY:        1,
   394  		bpftypes.BPF_MAP_TYPE_LRU_HASH:            1,
   395  		bpftypes.BPF_MAP_TYPE_LRU_PERCPU_HASH:     1,
   396  		bpftypes.BPF_MAP_TYPE_ARRAY_OF_MAPS:       1,
   397  		bpftypes.BPF_MAP_TYPE_DEVMAP:              1,
   398  		bpftypes.BPF_MAP_TYPE_SOCKMAP:             1,
   399  		bpftypes.BPF_MAP_TYPE_CPUMAP:              1,
   400  		bpftypes.BPF_MAP_TYPE_REUSEPORT_SOCKARRAY: 1,
   401  		bpftypes.BPF_MAP_TYPE_DEVMAP_HASH:         1,
   402  		bpftypes.BPF_MAP_TYPE_STRUCT_OPS:          1,
   403  	}
   404  
   405  	if minEntries, ok := minEntries[def.Type]; ok && def.MaxEntries < minEntries {
   406  		return fmt.Errorf("maps of type %s must have a max_entries number of at least %d, "+
   407  			"max_entries of this map is %d", def.Type, minEntries, def.MaxEntries)
   408  	}
   409  
   410  	maxEntries := map[bpftypes.BPFMapType]uint32{
   411  		bpftypes.BPF_MAP_TYPE_CGROUP_STORAGE:        0,
   412  		bpftypes.BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: 0,
   413  		bpftypes.BPF_MAP_TYPE_STRUCT_OPS:            1,
   414  		bpftypes.BPF_MAP_TYPE_INODE_STORAGE:         0,
   415  		bpftypes.BPF_MAP_TYPE_TASK_STORAGE:          0,
   416  	}
   417  
   418  	if maxEntries, ok := maxEntries[def.Type]; ok && def.MaxEntries > maxEntries {
   419  		return fmt.Errorf("maps of type %s must have a max_entries number of at most %d, "+
   420  			"max_entries of this map is %d", def.Type, maxEntries, def.MaxEntries)
   421  	}
   422  
   423  	return nil
   424  }
   425  
   426  var mapTypeToKFeature = map[bpftypes.BPFMapType]kernelsupport.MapSupport{
   427  	bpftypes.BPF_MAP_TYPE_HASH:                  kernelsupport.KFeatMapHash,
   428  	bpftypes.BPF_MAP_TYPE_ARRAY:                 kernelsupport.KFeatMapArray,
   429  	bpftypes.BPF_MAP_TYPE_PROG_ARRAY:            kernelsupport.KFeatMapTailCall,
   430  	bpftypes.BPF_MAP_TYPE_PERF_EVENT_ARRAY:      kernelsupport.KFeatMapPerfEvent,
   431  	bpftypes.BPF_MAP_TYPE_PERCPU_HASH:           kernelsupport.KFeatMapPerCPUHash,
   432  	bpftypes.BPF_MAP_TYPE_PERCPU_ARRAY:          kernelsupport.KFeatMapPerCPUArray,
   433  	bpftypes.BPF_MAP_TYPE_STACK_TRACE:           kernelsupport.KFeatMapStackTrace,
   434  	bpftypes.BPF_MAP_TYPE_CGROUP_ARRAY:          kernelsupport.KFeatMapCGroupArray,
   435  	bpftypes.BPF_MAP_TYPE_LRU_HASH:              kernelsupport.KFeatMapLRUHash,
   436  	bpftypes.BPF_MAP_TYPE_LRU_PERCPU_HASH:       kernelsupport.KFeatMapLRUPerCPUHash,
   437  	bpftypes.BPF_MAP_TYPE_LPM_TRIE:              kernelsupport.KFeatMapLPMTrie,
   438  	bpftypes.BPF_MAP_TYPE_ARRAY_OF_MAPS:         kernelsupport.KFeatMapArrayOfMaps,
   439  	bpftypes.BPF_MAP_TYPE_HASH_OF_MAPS:          kernelsupport.KFeatMapHashOfMaps,
   440  	bpftypes.BPF_MAP_TYPE_DEVMAP:                kernelsupport.KFeatMapNetdevArray,
   441  	bpftypes.BPF_MAP_TYPE_SOCKMAP:               kernelsupport.KFeatMapSocketArray,
   442  	bpftypes.BPF_MAP_TYPE_CPUMAP:                kernelsupport.KFeatMapCPU,
   443  	bpftypes.BPF_MAP_TYPE_XSKMAP:                kernelsupport.KFeatMapAFXDP,
   444  	bpftypes.BPF_MAP_TYPE_SOCKHASH:              kernelsupport.KFeatMapSocketHash,
   445  	bpftypes.BPF_MAP_TYPE_CGROUP_STORAGE:        kernelsupport.KFeatMapCGroupStorage,
   446  	bpftypes.BPF_MAP_TYPE_REUSEPORT_SOCKARRAY:   kernelsupport.KFeatMapReuseportSocketArray,
   447  	bpftypes.BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE: kernelsupport.KFeatMapPerCPUCGroupStorage,
   448  	bpftypes.BPF_MAP_TYPE_QUEUE:                 kernelsupport.KFeatMapQueue,
   449  	bpftypes.BPF_MAP_TYPE_STACK:                 kernelsupport.KFeatMapStack,
   450  	bpftypes.BPF_MAP_TYPE_SK_STORAGE:            kernelsupport.KFeatMapSocketLocalStorage,
   451  	bpftypes.BPF_MAP_TYPE_DEVMAP_HASH:           kernelsupport.KFeatMapNetdevHash,
   452  	bpftypes.BPF_MAP_TYPE_STRUCT_OPS:            kernelsupport.KFeatMapStructOps,
   453  	bpftypes.BPF_MAP_TYPE_RINGBUF:               kernelsupport.KFeatMapRingBuffer,
   454  	bpftypes.BPF_MAP_TYPE_INODE_STORAGE:         kernelsupport.KFeatMapINodeStorage,
   455  	bpftypes.BPF_MAP_TYPE_TASK_STORAGE:          kernelsupport.KFeatMapTaskStorage,
   456  }