github.com/cilium/cilium@v1.16.2/pkg/maps/lbmap/maglev_inner_map.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package lbmap 5 6 import ( 7 "fmt" 8 "unsafe" 9 10 "github.com/cilium/cilium/pkg/ebpf" 11 "github.com/cilium/cilium/pkg/loadbalancer" 12 ) 13 14 // maglevBackendLen represents the length of a single backend ID 15 // in a Maglev lookup table. 16 var maglevBackendLen = uint32(unsafe.Sizeof(loadbalancer.BackendID(0))) 17 18 // MaglevInnerMap represents a maglev inner map. 19 type MaglevInnerMap ebpf.Map 20 21 // TableSize returns the amount of backends this map can hold as a value. 22 func (m *MaglevInnerMap) TableSize() uint32 { 23 return m.Map.ValueSize() / uint32(maglevBackendLen) 24 } 25 26 // UpdateBackends updates the maglev inner map's list of backends. 27 func (m *MaglevInnerMap) UpdateBackends(backends []loadbalancer.BackendID) error { 28 // Backends are stored at inner map key zero. 29 var key MaglevInnerKey 30 return m.Map.Update(key, backends, 0) 31 } 32 33 // MaglevInnerKey is the key of a maglev inner map. 34 type MaglevInnerKey struct { 35 Zero uint32 36 } 37 38 // MaglevInnerVal is the value of a maglev inner map. 39 type MaglevInnerVal struct { 40 BackendIDs []loadbalancer.BackendID 41 } 42 43 // newMaglevInnerMapSpec returns the spec for a maglev inner map. 44 func newMaglevInnerMapSpec(tableSize uint32) *ebpf.MapSpec { 45 return &ebpf.MapSpec{ 46 Name: "cilium_maglev_inner", 47 Type: ebpf.Array, 48 KeySize: uint32(unsafe.Sizeof(MaglevInnerKey{})), 49 ValueSize: maglevBackendLen * tableSize, 50 MaxEntries: 1, 51 } 52 } 53 54 // createMaglevInnerMap creates a new Maglev inner map in the kernel 55 // using the given table size. 56 func createMaglevInnerMap(tableSize uint32) (*MaglevInnerMap, error) { 57 spec := newMaglevInnerMapSpec(tableSize) 58 59 m := ebpf.NewMap(spec) 60 if err := m.OpenOrCreate(); err != nil { 61 return nil, err 62 } 63 64 return (*MaglevInnerMap)(m), nil 65 } 66 67 // MaglevInnerMapFromID returns a new object representing the maglev inner map 68 // identified by an ID. 69 func MaglevInnerMapFromID(id uint32) (*MaglevInnerMap, error) { 70 m, err := ebpf.MapFromID(int(id)) 71 if err != nil { 72 return nil, err 73 } 74 75 return (*MaglevInnerMap)(m), nil 76 } 77 78 // Lookup returns the value associated with a given key for a maglev inner map. 79 func (m *MaglevInnerMap) Lookup(key *MaglevInnerKey) (*MaglevInnerVal, error) { 80 value := &MaglevInnerVal{ 81 BackendIDs: make([]loadbalancer.BackendID, m.TableSize()), 82 } 83 84 if err := m.Map.Lookup(key, &value.BackendIDs); err != nil { 85 return nil, err 86 } 87 88 return value, nil 89 } 90 91 // DumpBackends returns the first key of the map as stringified ints for dumping purposes. 92 func (m *MaglevInnerMap) DumpBackends() (string, error) { 93 // A service's backend array sits at the first key of the inner map. 94 var key MaglevInnerKey 95 val, err := m.Lookup(&key) 96 if err != nil { 97 return "", fmt.Errorf("lookup up first inner map key (backends): %w", err) 98 } 99 100 return fmt.Sprintf("%v", val.BackendIDs), nil 101 }