github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/map_prog_array.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  )
    10  
    11  var _ BPFMap = (*ProgArrayMap)(nil)
    12  
    13  // ProgArrayMap is a specialized map type used for tail calls https://docs.cilium.io/en/stable/bpf/#tail-calls
    14  type ProgArrayMap struct {
    15  	AbstractMap
    16  }
    17  
    18  func (m *ProgArrayMap) Load() error {
    19  	if m.Definition.Type != bpftypes.BPF_MAP_TYPE_PROG_ARRAY {
    20  		return fmt.Errorf("map type in definition must be BPF_MAP_TYPE_PROG_ARRAY when using an ProgArrayMap")
    21  	}
    22  
    23  	err := m.load(nil)
    24  	if err != nil {
    25  		return err
    26  	}
    27  
    28  	err = mapRegister.add(m)
    29  	if err != nil {
    30  		return fmt.Errorf("map register: %w", err)
    31  	}
    32  
    33  	return nil
    34  }
    35  
    36  // Close closes the file descriptor associate with the map, this will cause the map to unload from the kernel
    37  // if it is not still in use by a eBPF program, bpf FS, or a userspace program still holding a fd to the map.
    38  func (m *ProgArrayMap) Close() error {
    39  	err := mapRegister.delete(m)
    40  	if err != nil {
    41  		return fmt.Errorf("map register: %w", err)
    42  	}
    43  
    44  	return m.close()
    45  }
    46  
    47  // Get performs a lookup in the xskmap based on the key and returns the file descriptor of the socket
    48  func (m *ProgArrayMap) Get(key int) (int, error) {
    49  	if !m.loaded {
    50  		return 0, fmt.Errorf("can't read from an unloaded map")
    51  	}
    52  
    53  	var fd int
    54  	attr := &bpfsys.BPFAttrMapElem{
    55  		MapFD:         m.fd,
    56  		Key:           uintptr(unsafe.Pointer(&key)),
    57  		Value_NextKey: uintptr(unsafe.Pointer(&fd)),
    58  	}
    59  
    60  	err := bpfsys.MapLookupElem(attr)
    61  	if err != nil {
    62  		return 0, fmt.Errorf("bpf syscall error: %w", err)
    63  	}
    64  
    65  	return fd, nil
    66  }
    67  
    68  func (m *ProgArrayMap) Set(key int32, value BPFProgram) error {
    69  	if !m.loaded {
    70  		return fmt.Errorf("can't write to an unloaded map")
    71  	}
    72  
    73  	fd, err := value.Fd()
    74  	if err != nil {
    75  		return fmt.Errorf("prog fd: %w", err)
    76  	}
    77  
    78  	attr := &bpfsys.BPFAttrMapElem{
    79  		MapFD:         m.fd,
    80  		Key:           uintptr(unsafe.Pointer(&key)),
    81  		Value_NextKey: uintptr(unsafe.Pointer(&fd)),
    82  	}
    83  
    84  	err = bpfsys.MapUpdateElem(attr)
    85  	if err != nil {
    86  		return fmt.Errorf("bpf syscall error: %w", err)
    87  	}
    88  
    89  	return nil
    90  }
    91  
    92  // TODO add remaining map functions like Delete and iterator