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