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  }