github.com/cilium/cilium@v1.16.2/pkg/maps/l2respondermap/l2_responder_map4.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package l2respondermap 5 6 import ( 7 "fmt" 8 "net" 9 "net/netip" 10 "unsafe" 11 12 "github.com/cilium/hive/cell" 13 "golang.org/x/sys/unix" 14 15 "github.com/cilium/cilium/pkg/ebpf" 16 "github.com/cilium/cilium/pkg/types" 17 ) 18 19 const ( 20 MapName = "cilium_l2_responder_v4" 21 DefaultMaxEntries = 4096 22 ) 23 24 var Cell = cell.Provide(NewMap) 25 26 type Map interface { 27 Create(ip netip.Addr, ifIndex uint32) error 28 Lookup(ip netip.Addr, ifIndex uint32) (*L2ResponderStats, error) 29 Delete(ip netip.Addr, ifIndex uint32) error 30 IterateWithCallback(cb IterateCallback) error 31 } 32 33 func NewMap(lifecycle cell.Lifecycle) (Map, error) { 34 return newMap(lifecycle, DefaultMaxEntries) 35 } 36 37 type l2ResponderMap struct { 38 *ebpf.Map 39 } 40 41 func newMap(lifecycle cell.Lifecycle, maxEntries int) (*l2ResponderMap, error) { 42 outerMap := &l2ResponderMap{} 43 44 lifecycle.Append(cell.Hook{ 45 OnStart: func(hc cell.HookContext) error { 46 var ( 47 m *ebpf.Map 48 err error 49 ) 50 51 if m, err = ebpf.LoadRegisterMap(MapName); err != nil { 52 m = ebpf.NewMap(&ebpf.MapSpec{ 53 Name: MapName, 54 Type: ebpf.Hash, 55 KeySize: uint32(unsafe.Sizeof(L2ResponderKey{})), 56 ValueSize: uint32(unsafe.Sizeof(L2ResponderStats{})), 57 MaxEntries: uint32(maxEntries), 58 Flags: unix.BPF_F_NO_PREALLOC, 59 Pinning: ebpf.PinByName, 60 }) 61 if err := m.OpenOrCreate(); err != nil { 62 return err 63 } 64 } 65 66 outerMap.Map = m 67 68 return nil 69 }, 70 }) 71 72 return outerMap, nil 73 } 74 75 // Create creates a new entry for the given IP and IfIndex tuple. 76 func (m *l2ResponderMap) Create(ip netip.Addr, ifIndex uint32) error { 77 key := newL2ResponderKey(ip, ifIndex) 78 return m.Map.Put(key, L2ResponderStats{}) 79 } 80 81 // Delete deletes the entry associated with the provided IP and IfIndex tuple. 82 func (m *l2ResponderMap) Delete(ip netip.Addr, ifIndex uint32) error { 83 key := newL2ResponderKey(ip, ifIndex) 84 return m.Map.Delete(key) 85 } 86 87 // Lookup returns the stats object associated with the provided IP and IfIndex tuple. 88 func (m *l2ResponderMap) Lookup(ip netip.Addr, ifIndex uint32) (*L2ResponderStats, error) { 89 key := newL2ResponderKey(ip, ifIndex) 90 val := L2ResponderStats{} 91 92 err := m.Map.Lookup(&key, &val) 93 94 return &val, err 95 } 96 97 // IterateCallback represents the signature of the callback function 98 // expected by the IterateWithCallback method, which in turn is used to iterate 99 // all the keys/values of a L2 responder map. 100 type IterateCallback func(*L2ResponderKey, *L2ResponderStats) 101 102 // IterateWithCallback iterates through all the keys/values of a L2 responder map, 103 // passing each key/value pair to the cb callback. 104 func (m *l2ResponderMap) IterateWithCallback(cb IterateCallback) error { 105 return m.Map.IterateWithCallback(&L2ResponderKey{}, &L2ResponderStats{}, 106 func(k, v interface{}) { 107 key := k.(*L2ResponderKey) 108 value := v.(*L2ResponderStats) 109 cb(key, value) 110 }, 111 ) 112 } 113 114 // L2ResponderKey implements the bpf.MapKey interface. 115 // 116 // Must be in sync with struct l2_responder_v4_key in <bpf/lib/maps.h> 117 type L2ResponderKey struct { 118 IP types.IPv4 `align:"ip"` 119 IfIndex uint32 `align:"ifindex"` 120 } 121 122 func (k *L2ResponderKey) String() string { 123 return fmt.Sprintf("ip=%s, ifIndex=%d", net.IP(k.IP[:]), k.IfIndex) 124 } 125 126 func newL2ResponderKey(ip netip.Addr, ifIndex uint32) L2ResponderKey { 127 return L2ResponderKey{ 128 IP: types.IPv4(ip.As4()), 129 IfIndex: ifIndex, 130 } 131 } 132 133 // L2ResponderStats implements the bpf.MapValue interface. 134 // 135 // Must be in sync with struct l2_responder_v4_stats in <bpf/lib/maps.h> 136 type L2ResponderStats struct { 137 ResponsesSent uint64 `align:"responses_sent"` 138 } 139 140 func (s *L2ResponderStats) String() string { 141 return fmt.Sprintf("responses_sent=%q", s.ResponsesSent) 142 }