github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/emulator/maps_queue.go (about) 1 package emulator 2 3 import ( 4 "fmt" 5 6 "github.com/dylandreimerink/gobpfld/ebpf" 7 ) 8 9 type QueueMap struct { 10 AbstractMap 11 12 // TODO this is a very slow an inefficient way to implement a queue. Should use a ringbuffer instread 13 Values []*ByteMemory 14 } 15 16 func (m *QueueMap) Init() error { 17 return nil 18 } 19 20 func (m *QueueMap) Keys() []RegisterValue { 21 keys := make([]RegisterValue, len(m.Values)) 22 for i := range keys { 23 imm := newIMM(int64(i)) 24 keys[i] = &MemoryPtr{ 25 Memory: &ValueMemory{ 26 MemName: fmt.Sprintf("%s[%d]", m.Name, m.Def.ValueSize), 27 Mapping: []RegisterValue{ 28 imm, 29 imm, 30 imm, 31 imm, 32 }, 33 }, 34 } 35 } 36 return keys 37 } 38 39 func (m *QueueMap) Lookup(key RegisterValue) (RegisterValue, error) { 40 keyPtr, ok := key.(PointerValue) 41 if !ok { 42 return nil, errMapKeyNoPtr 43 } 44 45 keyVal, err := keyPtr.Deref(0, ebpf.BPF_W) 46 if !ok { 47 return nil, fmt.Errorf("key read range: %w", err) 48 } 49 50 keyIndex := int(keyVal.Value()) 51 if keyIndex < 0 || keyIndex >= len(m.Values) { 52 return nil, errMapOutOfMemory 53 } 54 55 value := m.Values[keyIndex] 56 57 return &MemoryPtr{Memory: value, Offset: 0}, nil 58 } 59 60 func (m *QueueMap) Push(value RegisterValue, size int64) error { 61 valuePtr, ok := value.(PointerValue) 62 if !ok { 63 return errMapValNoPtr 64 } 65 66 valueVal, err := valuePtr.ReadRange(0, int(size)) 67 if !ok { 68 return fmt.Errorf("value read range: %w", err) 69 } 70 71 m.Values = append(m.Values, &ByteMemory{ 72 MemName: fmt.Sprintf("%s[?]", m.Name), 73 Backing: valueVal, 74 }) 75 76 return nil 77 } 78 79 func (m *QueueMap) Pop() (RegisterValue, error) { 80 if len(m.Values) == 0 { 81 return newIMM(0), nil 82 } 83 84 val := m.Values[0] 85 copy(m.Values, m.Values[1:]) 86 m.Values = m.Values[:len(m.Values)-1] 87 88 return &MemoryPtr{ 89 Memory: val, 90 }, nil 91 }