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

     1  package gobpfld
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/dylandreimerink/gobpfld/bpfsys"
     7  	"github.com/dylandreimerink/gobpfld/kernelsupport"
     8  )
     9  
    10  var _ BPFMap = (*HashMap)(nil)
    11  
    12  // HashMap is a generic map type, both the key and value may be of any type. The value of the key is hashed so values
    13  // do not need to be contiguous.
    14  type HashMap struct {
    15  	AbstractMap
    16  }
    17  
    18  func (m *HashMap) Load() error {
    19  	// NOTE: do not enforce definition type of map since hash map is currently still a catch all map type
    20  	err := m.load(nil)
    21  	if err != nil {
    22  		return err
    23  	}
    24  
    25  	err = mapRegister.add(m)
    26  	if err != nil {
    27  		return fmt.Errorf("map register: %w", err)
    28  	}
    29  
    30  	return nil
    31  }
    32  
    33  // Close closes the file descriptor associate with the map, this will cause the map to unload from the kernel
    34  // if it is not still in use by a eBPF program, bpf FS, or a userspace program still holding a fd to the map.
    35  func (m *HashMap) Close() error {
    36  	err := mapRegister.delete(m)
    37  	if err != nil {
    38  		return fmt.Errorf("map register: %w", err)
    39  	}
    40  
    41  	return m.close()
    42  }
    43  
    44  func (m *HashMap) Get(key interface{}, value interface{}) error {
    45  	return m.get(key, value)
    46  }
    47  
    48  // GetBatch fills the keys and values array/slice with the keys and values inside the map up to a maximum of
    49  // maxBatchSize entries. The keys and values array/slice must have at least a length of maxBatchSize.
    50  // The key and value of an entry is has the same index, so for example the value for keys[2] is in values[2].
    51  // Count is the amount of entries returns, partial is true if not all elements of keys and values could be set.
    52  //
    53  // This function is intended for small maps which can be read into userspace all at once since
    54  // GetBatch can only read from the beginning of the map. If the map is to large to read all at once
    55  // a iterator should be used instead of the Get or GetBatch function.
    56  func (m *HashMap) GetBatch(
    57  	keys interface{},
    58  	values interface{},
    59  	maxBatchSize uint32,
    60  ) (
    61  	count int,
    62  	partial bool,
    63  	err error,
    64  ) {
    65  	return m.getBatch(keys, values, maxBatchSize)
    66  }
    67  
    68  func (m *HashMap) Set(key interface{}, value interface{}, flags bpfsys.BPFAttrMapElemFlags) error {
    69  	return m.set(key, value, flags)
    70  }
    71  
    72  func (m *HashMap) SetBatch(
    73  	keys interface{},
    74  	values interface{},
    75  	flags bpfsys.BPFAttrMapElemFlags,
    76  	maxBatchSize uint32,
    77  ) (
    78  	count int,
    79  	err error,
    80  ) {
    81  	return m.setBatch(keys, values, flags, maxBatchSize)
    82  }
    83  
    84  func (m *HashMap) Delete(key interface{}) error {
    85  	return m.delete(key)
    86  }
    87  
    88  func (m *HashMap) DeleteBatch(
    89  	keys interface{},
    90  	maxBatchSize uint32,
    91  ) (
    92  	count int,
    93  	err error,
    94  ) {
    95  	return m.deleteBatch(keys, maxBatchSize)
    96  }
    97  
    98  func (m *HashMap) GetAndDelete(key interface{}, value interface{}) error {
    99  	return m.getAndDelete(key, value)
   100  }
   101  
   102  func (m *HashMap) GetAndDeleteBatch(
   103  	keys interface{},
   104  	values interface{},
   105  	maxBatchSize uint32,
   106  ) (
   107  	count int,
   108  	err error,
   109  ) {
   110  	return m.getAndDeleteBatch(keys, values, maxBatchSize)
   111  }
   112  
   113  func (m *HashMap) Iterator() MapIterator {
   114  	// If the kernel doesn't have support for batch lookup, use single lookup
   115  	if !kernelsupport.CurrentFeatures.API.Has(kernelsupport.KFeatAPIMapBatchOps) {
   116  		return &singleLookupIterator{
   117  			BPFMap: m,
   118  		}
   119  	}
   120  
   121  	// TODO change batch lookup iterator to support per-cpu values
   122  	if m.isPerCPUMap() {
   123  		return &singleLookupIterator{
   124  			BPFMap: m,
   125  		}
   126  	}
   127  
   128  	// If there is no reason not to use the batch lookup iterator, use it
   129  	return &batchLookupIterator{
   130  		BPFMap: m,
   131  	}
   132  }