github.com/cilium/cilium@v1.16.2/pkg/maps/nodemap/node_map.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package nodemap 5 6 import ( 7 "fmt" 8 "net" 9 "unsafe" 10 11 "golang.org/x/sys/unix" 12 13 "github.com/cilium/cilium/pkg/bpf" 14 "github.com/cilium/cilium/pkg/ebpf" 15 "github.com/cilium/cilium/pkg/types" 16 ) 17 18 const ( 19 MapName = "cilium_node_map" 20 DefaultMaxEntries = 16384 21 ) 22 23 // Map provides access to the eBPF map node. 24 type Map interface { 25 // Update inserts or updates the node map object associated with the provided 26 // IP and node id. 27 Update(ip net.IP, nodeID uint16) error 28 29 // Delete deletes the node map object associated with the provided 30 // IP. 31 Delete(ip net.IP) error 32 33 // IterateWithCallback iterates through all the keys/values of a node map, 34 // passing each key/value pair to the cb callback. 35 IterateWithCallback(cb NodeIterateCallback) error 36 37 // Size returns what how many entries the node map is configured to hold. 38 Size() uint32 39 } 40 41 type nodeMap struct { 42 conf Config 43 bpfMap *ebpf.Map 44 } 45 46 func newMap(mapName string, conf Config) *nodeMap { 47 return &nodeMap{ 48 conf: conf, 49 bpfMap: ebpf.NewMap(&ebpf.MapSpec{ 50 Name: mapName, 51 Type: ebpf.Hash, 52 KeySize: uint32(unsafe.Sizeof(NodeKey{})), 53 ValueSize: uint32(unsafe.Sizeof(NodeValue{})), 54 MaxEntries: conf.NodeMapMax, 55 Flags: unix.BPF_F_NO_PREALLOC, 56 Pinning: ebpf.PinByName, 57 }), 58 } 59 } 60 61 type NodeKey struct { 62 Pad1 uint16 `align:"pad1"` 63 Pad2 uint8 `align:"pad2"` 64 Family uint8 `align:"family"` 65 // represents both IPv6 and IPv4 (in the lowest four bytes) 66 IP types.IPv6 `align:"$union0"` 67 } 68 69 func (k *NodeKey) String() string { 70 switch k.Family { 71 case bpf.EndpointKeyIPv4: 72 return net.IP(k.IP[:net.IPv4len]).String() 73 case bpf.EndpointKeyIPv6: 74 return k.IP.String() 75 } 76 return "<unknown>" 77 } 78 79 func newNodeKey(ip net.IP) NodeKey { 80 result := NodeKey{} 81 if ip4 := ip.To4(); ip4 != nil { 82 result.Family = bpf.EndpointKeyIPv4 83 copy(result.IP[:], ip4) 84 } else { 85 result.Family = bpf.EndpointKeyIPv6 86 copy(result.IP[:], ip) 87 } 88 return result 89 } 90 91 type NodeValue struct { 92 NodeID uint16 93 } 94 95 func (m *nodeMap) Update(ip net.IP, nodeID uint16) error { 96 key := newNodeKey(ip) 97 val := NodeValue{NodeID: nodeID} 98 return m.bpfMap.Update(key, val, 0) 99 } 100 101 func (m *nodeMap) Size() uint32 { 102 return m.conf.NodeMapMax 103 } 104 105 func (m *nodeMap) Delete(ip net.IP) error { 106 key := newNodeKey(ip) 107 return m.bpfMap.Map.Delete(key) 108 } 109 110 // NodeIterateCallback represents the signature of the callback function 111 // expected by the IterateWithCallback method, which in turn is used to iterate 112 // all the keys/values of a node map. 113 type NodeIterateCallback func(*NodeKey, *NodeValue) 114 115 func (m *nodeMap) IterateWithCallback(cb NodeIterateCallback) error { 116 return m.bpfMap.IterateWithCallback(&NodeKey{}, &NodeValue{}, 117 func(k, v interface{}) { 118 key := k.(*NodeKey) 119 value := v.(*NodeValue) 120 121 cb(key, value) 122 }) 123 } 124 125 // LoadNodeMap loads the pre-initialized node map for access. 126 // This should only be used from components which aren't capable of using hive - mainly the Cilium CLI. 127 // It needs to initialized beforehand via the Cilium Agent. 128 func LoadNodeMap() (Map, error) { 129 bpfMap, err := ebpf.LoadRegisterMap(MapName) 130 if err != nil { 131 return nil, fmt.Errorf("failed to load bpf map: %w", err) 132 } 133 134 return &nodeMap{bpfMap: bpfMap}, nil 135 } 136 137 func (m *nodeMap) init() error { 138 if err := m.bpfMap.OpenOrCreate(); err != nil { 139 return fmt.Errorf("failed to init bpf map: %w", err) 140 } 141 142 return nil 143 }