diff --git a/libbpfgo.go b/libbpfgo.go index 7cb6d500..50200d09 100644 --- a/libbpfgo.go +++ b/libbpfgo.go @@ -182,6 +182,15 @@ const ( MapTypeBloomFilter ) +type MapFlag uint32 + +const ( + MapFlagUpdateAny MapFlag = iota // create new element or update existing + MapFlagUpdateNoExist // create new element if it didn't exist + MapFlagUpdateExist // update existing element + MapFlagFLock // spin_lock-ed map_lookup/map_update +) + func (m MapType) String() string { x := map[MapType]string{ MapTypeUnspec: "BPF_MAP_TYPE_UNSPEC", @@ -679,6 +688,17 @@ func (b *BPFMap) GetValue(key unsafe.Pointer) ([]byte, error) { return value, nil } +func (b *BPFMap) GetValueFlags(key unsafe.Pointer, flags MapFlag) ([]byte, error) { + value := make([]byte, b.ValueSize()) + valuePtr := unsafe.Pointer(&value[0]) + + errC := C.bpf_map_lookup_elem_flags(b.fd, key, valuePtr, C.ulonglong(flags)) + if errC != 0 { + return nil, fmt.Errorf("failed to lookup value %v in map %s: %w", key, b.name, syscall.Errno(-errC)) + } + return value, nil +} + // BPFMapBatchOpts mirrors the C structure bpf_map_batch_opts. type BPFMapBatchOpts struct { Sz uint64 @@ -902,9 +922,13 @@ func (b *BPFMap) DeleteKey(key unsafe.Pointer) error { // bpfmap.Update(keyPtr, valuePtr) // func (b *BPFMap) Update(key, value unsafe.Pointer) error { - ret, errC := C.bpf_map_update_elem(b.fd, key, value, C.BPF_ANY) - if ret != 0 { - return fmt.Errorf("failed to update map %s: %w", b.name, errC) + return b.UpdateValueFlags(key, value, MapFlagUpdateAny) +} + +func (b *BPFMap) UpdateValueFlags(key, value unsafe.Pointer, flags MapFlag) error { + errC := C.bpf_map_update_elem(b.fd, key, value, C.ulonglong(flags)) + if errC != 0 { + return fmt.Errorf("failed to update map %s: %w", b.name, syscall.Errno(-errC)) } return nil }