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

     1  package gobpfld
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/dylandreimerink/gobpfld/bpfsys"
     7  	"github.com/dylandreimerink/gobpfld/bpftypes"
     8  	"github.com/dylandreimerink/gobpfld/kernelsupport"
     9  )
    10  
    11  var _ BPFMap = (*PerCPUArrayMap)(nil)
    12  
    13  // PerCPUArrayMap is a map which has a integer key from 0 to MaxEntries. It is a generic map type so the value can be
    14  // any type. This map type stores an array of values for each key, the size of the array is equal to the CPU count
    15  // returned by the runtime.NumCPU() function.
    16  type PerCPUArrayMap struct {
    17  	AbstractMap
    18  }
    19  
    20  func (m *PerCPUArrayMap) Load() error {
    21  	if m.Definition.Type != bpftypes.BPF_MAP_TYPE_PERCPU_ARRAY {
    22  		return fmt.Errorf("map type in definition must be BPF_MAP_TYPE_PERCPU_ARRAY when using an PerCPUArrayMap")
    23  	}
    24  
    25  	err := m.load(nil)
    26  	if err != nil {
    27  		return err
    28  	}
    29  
    30  	err = mapRegister.add(m)
    31  	if err != nil {
    32  		return fmt.Errorf("map register: %w", err)
    33  	}
    34  
    35  	return nil
    36  }
    37  
    38  // Close closes the file descriptor associate with the map, this will cause the map to unload from the kernel
    39  // if it is not still in use by a eBPF program, bpf FS, or a userspace program still holding a fd to the map.
    40  func (m *PerCPUArrayMap) Close() error {
    41  	err := mapRegister.delete(m)
    42  	if err != nil {
    43  		return fmt.Errorf("map register: %w", err)
    44  	}
    45  
    46  	return m.close()
    47  }
    48  
    49  func (m *PerCPUArrayMap) Get(key uint32, value interface{}) error {
    50  	return m.get(&key, value)
    51  }
    52  
    53  // GetBatch fills the keys slice and values array/slice with the keys and values inside the map.
    54  // The keys slice and values array/slice must have the same length. The key and value of an entry is has the same
    55  // index, so for example the value for keys[2] is in values[2]. Count is the amount of entries returns,
    56  // partial is true if not all elements of keys and values could be set.
    57  //
    58  // This function is intended for small maps which can be read into userspace all at once since
    59  // GetBatch can only read from the beginning of the map. If the map is to large to read all at once
    60  // a iterator should be used instead of the Get or GetBatch function.
    61  func (m *PerCPUArrayMap) GetBatch(
    62  	keys []uint32,
    63  	values interface{},
    64  ) (
    65  	count int,
    66  	partial bool,
    67  	err error,
    68  ) {
    69  	if !kernelsupport.CurrentFeatures.Map.Has(kernelsupport.KFeatMapPerCPUArrayBatchOps) {
    70  		return 0,
    71  			false,
    72  			fmt.Errorf("batch get operation not support on Per CPU array map type on current kernel version")
    73  	}
    74  
    75  	keysLen := len(keys)
    76  
    77  	// Very unlikely, but we have to check
    78  	if keysLen > maxUint32 {
    79  		return 0, false, fmt.Errorf("max len of 'keys' allowed is %d", maxUint32)
    80  	}
    81  
    82  	return m.getBatch(&keys, values, uint32(keysLen))
    83  }
    84  
    85  func (m *PerCPUArrayMap) Set(key uint32, value interface{}, flags bpfsys.BPFAttrMapElemFlags) error {
    86  	return m.set(&key, value, flags)
    87  }
    88  
    89  func (m *PerCPUArrayMap) SetBatch(
    90  	keys []uint32,
    91  	values interface{},
    92  	flags bpfsys.BPFAttrMapElemFlags,
    93  ) (
    94  	count int,
    95  	err error,
    96  ) {
    97  	if !kernelsupport.CurrentFeatures.Map.Has(kernelsupport.KFeatMapPerCPUArrayBatchOps) {
    98  		return 0, fmt.Errorf("batch set operation not support on Per CPU array map type on current kernel version")
    99  	}
   100  
   101  	keysLen := len(keys)
   102  
   103  	// Very unlikely, but we have to check
   104  	if keysLen > maxUint32 {
   105  		return 0, fmt.Errorf("max len of 'keys' allowed is %d", maxUint32)
   106  	}
   107  
   108  	return m.setBatch(&keys, values, flags, uint32(keysLen))
   109  }
   110  
   111  func (m *PerCPUArrayMap) Iterator() MapIterator {
   112  	// If the kernel doesn't have support for batch lookup, use single lookup
   113  	if !kernelsupport.CurrentFeatures.Map.Has(kernelsupport.KFeatMapPerCPUArrayBatchOps) {
   114  		return &singleLookupIterator{
   115  			BPFMap: m,
   116  		}
   117  	}
   118  
   119  	// If there is no reason not to use the batch lookup iterator, use it
   120  	return &batchLookupIterator{
   121  		BPFMap: m,
   122  	}
   123  }