github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/map_data.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 var _ BPFMap = (*dataMap)(nil) 13 14 // dataMap is a special map type which is used to load relocated data from .data, .rodata and .bss sections. 15 // It is actually an array map, but its contents are set just after loading, an this map has no exposed functions 16 // to be used by users of the library. 17 type dataMap struct { 18 AbstractMap 19 20 readOnly bool 21 } 22 23 func (m *dataMap) Load() error { 24 err := m.load(func(attr *bpfsys.BPFAttrMapCreate) { 25 attr.MapType = bpftypes.BPF_MAP_TYPE_ARRAY 26 27 if m.readOnly { 28 if kernelsupport.CurrentFeatures.API.Has(kernelsupport.KFeatAPIMapBPFRW) { 29 attr.MapFlags |= bpftypes.BPFMapFlagsReadOnlyProg 30 } 31 } 32 }) 33 if err != nil { 34 return fmt.Errorf("error while loading map: %w", err) 35 } 36 37 err = mapRegister.add(m) 38 if err != nil { 39 return fmt.Errorf("map register: %w", err) 40 } 41 42 // TODO move to abstract map load 43 if m.InitialData[0] != nil { 44 k := uint32(0) 45 attr := bpfsys.BPFAttrMapElem{ 46 MapFD: m.fd, 47 Flags: bpfsys.BPFMapElemAny, 48 } 49 50 attr.Key, err = m.toKeyPtr(&k) 51 if err != nil { 52 return fmt.Errorf("unable to make ptr of uint32(0): %w", err) 53 } 54 55 if len(m.InitialData[0].([]byte)) != int(m.definition.ValueSize) { 56 return fmt.Errorf( 57 "initial data(%d) not of same size as map definition(%d)", 58 len(m.InitialData), 59 int(m.definition.ValueSize), 60 ) 61 } 62 63 value, ok := m.InitialData[0].([]byte) 64 if !ok { 65 panic("initial data value of a dataMap isn't []byte") 66 } 67 attr.Value_NextKey = uintptr(unsafe.Pointer(&value[0])) 68 69 err = bpfsys.MapUpdateElem(&attr) 70 if err != nil { 71 return fmt.Errorf("bpf syscall error: %w", err) 72 } 73 } 74 75 // Freeze the map if it is supposed to be read only 76 if m.readOnly && kernelsupport.CurrentFeatures.API.Has(kernelsupport.KFeatAPIMapFreeze) { 77 err = bpfsys.MapFreeze(&bpfsys.BPFAttrMapElem{ 78 MapFD: m.fd, 79 }) 80 if err != nil { 81 return fmt.Errorf("freeze map: %w", err) 82 } 83 } 84 85 return nil 86 } 87 88 // Close closes the file descriptor associate with the map, this will cause the map to unload from the kernel 89 // if it is not still in use by a eBPF program, bpf FS, or a userspace program still holding a fd to the map. 90 func (m *dataMap) Close() error { 91 err := mapRegister.delete(m) 92 if err != nil { 93 return fmt.Errorf("map register: %w", err) 94 } 95 96 return m.close() 97 }