github.com/cilium/cilium@v1.16.2/pkg/maps/tunnel/tunnel.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package tunnel 5 6 import ( 7 "fmt" 8 "net" 9 "sync" 10 11 "github.com/sirupsen/logrus" 12 13 "github.com/cilium/cilium/pkg/bpf" 14 cmtypes "github.com/cilium/cilium/pkg/clustermesh/types" 15 "github.com/cilium/cilium/pkg/ebpf" 16 ippkg "github.com/cilium/cilium/pkg/ip" 17 "github.com/cilium/cilium/pkg/option" 18 "github.com/cilium/cilium/pkg/types" 19 ) 20 21 const ( 22 MapName = "cilium_tunnel_map" 23 24 // MaxEntries is the maximum entries in the tunnel endpoint map 25 MaxEntries = 65536 26 ) 27 28 var ( 29 // TunnelMap represents the BPF map for tunnels 30 tunnelMap *Map 31 tunnelMapInit = &sync.Once{} 32 ) 33 34 // SetTunnelMap sets the tunnel map. Only used for testing. 35 func SetTunnelMap(m *Map) { 36 if tunnelMap != nil { 37 tunnelMap.UnpinIfExists() 38 } 39 40 tunnelMap = m 41 } 42 43 func TunnelMap() *Map { 44 tunnelMapInit.Do(func() { 45 if tunnelMap == nil { 46 tunnelMap = NewTunnelMap(MapName) 47 } 48 }) 49 return tunnelMap 50 } 51 52 // Map implements tunnel connectivity configuration in the BPF datapath. 53 type Map struct { 54 *bpf.Map 55 } 56 57 // NewTunnelMap returns a new tunnel map. 58 func NewTunnelMap(mapName string) *Map { 59 return &Map{Map: bpf.NewMap( 60 mapName, 61 ebpf.Hash, 62 &TunnelKey{}, 63 &TunnelValue{}, 64 MaxEntries, 65 0, 66 ).WithCache().WithPressureMetric(). 67 WithEvents(option.Config.GetEventBufferConfig(MapName)), 68 } 69 } 70 71 // +k8s:deepcopy-gen=true 72 type TunnelIP struct { 73 // represents both IPv6 and IPv4 (in the lowest four bytes) 74 IP types.IPv6 `align:"$union0"` 75 Family uint8 `align:"family"` 76 } 77 78 type TunnelKey struct { 79 TunnelIP 80 Pad uint8 `align:"pad"` 81 ClusterID uint16 `align:"cluster_id"` 82 } 83 84 // String provides a string representation of the TunnelKey. 85 func (k TunnelKey) String() string { 86 if ip := k.toIP(); ip != nil { 87 addrCluster := cmtypes.AddrClusterFrom( 88 ippkg.MustAddrFromIP(ip), 89 uint32(k.ClusterID), 90 ) 91 return addrCluster.String() 92 } 93 return "nil" 94 } 95 96 func (k *TunnelKey) New() bpf.MapKey { return &TunnelKey{} } 97 98 type TunnelValue struct { 99 TunnelIP 100 Key uint8 `align:"key"` 101 Pad uint16 `align:"pad"` 102 } 103 104 // String provides a string representation of the TunnelValue. 105 func (k TunnelValue) String() string { 106 if ip := k.toIP(); ip != nil { 107 return ip.String() + ":" + fmt.Sprintf("%d", k.Key) 108 } 109 return "nil" 110 } 111 112 func (k *TunnelValue) New() bpf.MapValue { return &TunnelValue{} } 113 114 // ToIP converts the TunnelIP into a net.IP structure. 115 func (v TunnelIP) toIP() net.IP { 116 switch v.Family { 117 case bpf.EndpointKeyIPv4: 118 return v.IP[:4] 119 case bpf.EndpointKeyIPv6: 120 return v.IP[:] 121 } 122 return nil 123 } 124 125 func newTunnelKey(ip net.IP, clusterID uint32) (*TunnelKey, error) { 126 if clusterID > cmtypes.ClusterIDMax { 127 return nil, fmt.Errorf("ClusterID %d is too large. ClusterID > %d is not supported in TunnelMap", clusterID, cmtypes.ClusterIDMax) 128 } 129 130 result := TunnelKey{} 131 result.TunnelIP = newTunnelIP(ip) 132 result.ClusterID = uint16(clusterID) 133 return &result, nil 134 } 135 136 func newTunnelValue(ip net.IP, key uint8) *TunnelValue { 137 result := TunnelValue{} 138 result.TunnelIP = newTunnelIP(ip) 139 result.Key = key 140 return &result 141 } 142 143 func newTunnelIP(ip net.IP) TunnelIP { 144 result := TunnelIP{} 145 if ip4 := ip.To4(); ip4 != nil { 146 result.Family = bpf.EndpointKeyIPv4 147 copy(result.IP[:], ip4) 148 } else { 149 result.Family = bpf.EndpointKeyIPv6 150 copy(result.IP[:], ip) 151 } 152 return result 153 } 154 155 // SetTunnelEndpoint adds/replaces a prefix => tunnel-endpoint mapping 156 func (m *Map) SetTunnelEndpoint(encryptKey uint8, prefix cmtypes.AddrCluster, endpoint net.IP) error { 157 key, err := newTunnelKey(prefix.AsNetIP(), prefix.ClusterID()) 158 if err != nil { 159 return err 160 } 161 162 val := newTunnelValue(endpoint, encryptKey) 163 164 log.WithFields(logrus.Fields{ 165 fieldPrefix: prefix, 166 fieldEndpoint: endpoint, 167 fieldKey: encryptKey, 168 }).Debug("Updating tunnel map entry") 169 170 return m.Update(key, val) 171 } 172 173 // GetTunnelEndpoint retrieves a prefix => tunnel-endpoint mapping 174 func (m *Map) GetTunnelEndpoint(prefix cmtypes.AddrCluster) (net.IP, error) { 175 key, err := newTunnelKey(prefix.AsNetIP(), prefix.ClusterID()) 176 if err != nil { 177 return net.IP{}, err 178 } 179 180 val, err := m.Lookup(key) 181 if err != nil { 182 return net.IP{}, err 183 } 184 185 return val.(*TunnelValue).toIP(), nil 186 } 187 188 // DeleteTunnelEndpoint removes a prefix => tunnel-endpoint mapping 189 func (m *Map) DeleteTunnelEndpoint(prefix cmtypes.AddrCluster) error { 190 key, err := newTunnelKey(prefix.AsNetIP(), prefix.ClusterID()) 191 if err != nil { 192 return err 193 } 194 log.WithField(fieldPrefix, prefix).Debug("Deleting tunnel map entry") 195 return m.Delete(key) 196 } 197 198 // SilentDeleteTunnelEndpoint removes a prefix => tunnel-endpoint mapping. 199 // If the prefix is not found no error is returned. 200 func (m *Map) SilentDeleteTunnelEndpoint(prefix cmtypes.AddrCluster) error { 201 key, err := newTunnelKey(prefix.AsNetIP(), prefix.ClusterID()) 202 if err != nil { 203 return err 204 } 205 log.WithField(fieldPrefix, prefix).Debug("Silently deleting tunnel map entry") 206 _, err = m.SilentDelete(key) 207 return err 208 }