github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/emulator/maps_array.go (about) 1 package emulator 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "fmt" 7 8 "github.com/dylandreimerink/gobpfld/bpfsys" 9 "github.com/dylandreimerink/gobpfld/ebpf" 10 ) 11 12 type ArrayMap struct { 13 AbstractMap 14 Memory ByteMemory 15 InitialDataBO binary.ByteOrder 16 InitialData map[interface{}]interface{} 17 } 18 19 func (m *ArrayMap) Init() error { 20 m.Memory = ByteMemory{ 21 MemName: m.Name, 22 Backing: make([]byte, m.Def.ValueSize*m.Def.MaxEntries), 23 } 24 25 if m.InitialData != nil { 26 m.Memory.ByteOrder = m.InitialDataBO 27 28 for k, v := range m.InitialData { 29 keyInt, ok := k.(int) 30 if !ok { 31 return fmt.Errorf("the key type of the initial data must be an int") 32 } 33 34 vSlice, ok := v.([]byte) 35 if !ok { 36 return fmt.Errorf("the value type of the initial data must be an []byte") 37 } 38 39 copy(m.Memory.Backing[keyInt*int(m.Def.ValueSize):], vSlice) 40 } 41 } 42 43 return nil 44 } 45 46 func (m *ArrayMap) Keys() []RegisterValue { 47 keys := make([]RegisterValue, m.Def.MaxEntries) 48 for i := range keys { 49 imm := newIMM(int64(i)) 50 keys[i] = &MemoryPtr{ 51 Memory: &ValueMemory{ 52 MemName: fmt.Sprintf("%s[%d]", m.Name, m.Def.ValueSize), 53 Mapping: []RegisterValue{ 54 imm, 55 imm, 56 imm, 57 imm, 58 }, 59 }, 60 } 61 } 62 return keys 63 } 64 65 func (m *ArrayMap) Lookup(key RegisterValue) (RegisterValue, error) { 66 keyPtr, ok := key.(PointerValue) 67 if !ok { 68 return nil, errMapKeyNoPtr 69 } 70 71 keyValReg, err := keyPtr.Deref(0, ebpf.BPF_W) 72 if !ok { 73 return nil, fmt.Errorf("key pointer deref: %w", err) 74 } 75 76 kv := keyValReg.Value() 77 off := kv * int64(m.Def.ValueSize) 78 79 // Outside of map 80 if off >= int64(m.Memory.Size()) { 81 // Return NULL if key out of bounds 82 // https://elixir.bootlin.com/linux/v5.16.4/source/kernel/bpf/arraymap.c#L164 83 return newIMM(0), nil 84 } 85 86 return &MemoryPtr{Memory: &m.Memory, Offset: off}, nil 87 } 88 89 func (m *ArrayMap) Update( 90 key RegisterValue, 91 value RegisterValue, 92 flags bpfsys.BPFAttrMapElemFlags, 93 ) ( 94 RegisterValue, 95 error, 96 ) { 97 vPtr, ok := value.(*MemoryPtr) 98 if !ok { 99 return nil, errMapValNoPtr 100 } 101 102 keyPtr, ok := key.(*MemoryPtr) 103 if !ok { 104 return nil, errMapValNoPtr 105 } 106 107 keyVar, err := keyPtr.Deref(0, ebpf.BPF_W) 108 if err != nil { 109 return nil, err 110 } 111 112 kv := keyVar.Value() 113 // Outside of map 114 if kv >= int64(m.Memory.Size()) { 115 return nil, errMapOutOfMemory 116 } 117 118 for i := 0; i < int(m.Def.ValueSize); i++ { 119 v, err := vPtr.Memory.Read(i, ebpf.BPF_B) 120 if err != nil { 121 return nil, fmt.Errorf("memory read: %w", err) 122 } 123 124 err = m.Memory.Write(int(kv*int64(m.Def.ValueSize))+i, v, ebpf.BPF_B) 125 if err != nil { 126 return nil, fmt.Errorf("memory write: %w", err) 127 } 128 } 129 130 return newIMM(0), nil 131 } 132 133 func (m *ArrayMap) Delete(key RegisterValue, flags bpfsys.BPFAttrMapElemFlags) error { 134 return errors.New("not yet implemented") 135 }