github.com/cilium/cilium@v1.16.2/pkg/maps/lbmap/ipv6.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package lbmap 5 6 import ( 7 "fmt" 8 "net" 9 "unsafe" 10 11 "github.com/cilium/ebpf" 12 13 "github.com/cilium/cilium/pkg/bpf" 14 "github.com/cilium/cilium/pkg/byteorder" 15 cmtypes "github.com/cilium/cilium/pkg/clustermesh/types" 16 "github.com/cilium/cilium/pkg/loadbalancer" 17 "github.com/cilium/cilium/pkg/option" 18 "github.com/cilium/cilium/pkg/types" 19 "github.com/cilium/cilium/pkg/u8proto" 20 ) 21 22 const ( 23 // HealthProbe6MapName is the health datapath map name 24 HealthProbe6MapName = "cilium_lb6_health" 25 26 // SockRevNat6MapName is the BPF map name. 27 SockRevNat6MapName = "cilium_lb6_reverse_sk" 28 29 // SockRevNat6MapSize is the maximum number of entries in the BPF map. 30 SockRevNat6MapSize = 256 * 1024 31 32 // Service6MapV2Name is the name of the IPv6 LB Services v2 BPF map. 33 Service6MapV2Name = "cilium_lb6_services_v2" 34 // Backend6MapName is the name of the IPv6 LB backends BPF map. 35 Backend6MapName = "cilium_lb6_backends" 36 // Backend6MapV2Name is the name of the IPv6 LB backends v2 BPF map. 37 Backend6MapV2Name = "cilium_lb6_backends_v2" 38 // Backend6MapV3Name is the name of the IPv6 LB backends v3 BPF map. 39 Backend6MapV3Name = "cilium_lb6_backends_v3" 40 // RevNat6MapName is the name of the IPv6 LB reverse NAT BPF map. 41 RevNat6MapName = "cilium_lb6_reverse_nat" 42 ) 43 44 var ( 45 // MaxSockRevNat6MapEntries is the maximum number of entries in the BPF 46 // map. It is set by Init(), but unit tests use the initial value below. 47 MaxSockRevNat6MapEntries = SockRevNat6MapSize 48 49 // The following BPF maps are initialized in initSVC(). 50 51 // Service6MapV2 is the IPv6 LB Services v2 BPF map. 52 Service6MapV2 *bpf.Map 53 // Backend6Map is the IPv6 LB backends BPF map. 54 Backend6Map *bpf.Map 55 // Backend6MapV2 is the IPv6 LB backends v2 BPF map. 56 Backend6MapV2 *bpf.Map 57 // Backend6MapV3 is the IPv6 LB backends v3 BPF map. 58 Backend6MapV3 *bpf.Map 59 // RevNat6Map is the IPv6 LB reverse NAT BPF map. 60 RevNat6Map *bpf.Map 61 // SockRevNat6Map is the IPv6 LB sock reverse NAT BPF map. 62 SockRevNat6Map *bpf.Map 63 ) 64 65 // The compile-time check for whether the structs implement the interfaces 66 var _ RevNatKey = (*RevNat6Key)(nil) 67 var _ RevNatValue = (*RevNat6Value)(nil) 68 var _ ServiceKey = (*Service6Key)(nil) 69 var _ ServiceValue = (*Service6Value)(nil) 70 var _ BackendKey = (*Backend6Key)(nil) 71 var _ BackendValue = (*Backend6Value)(nil) 72 var _ Backend = (*Backend6)(nil) 73 74 type RevNat6Key struct { 75 Key uint16 76 } 77 78 func NewRevNat6Key(value uint16) *RevNat6Key { 79 return &RevNat6Key{value} 80 } 81 82 func (v *RevNat6Key) Map() *bpf.Map { return RevNat6Map } 83 func (v *RevNat6Key) String() string { return fmt.Sprintf("%d", v.ToHost().(*RevNat6Key).Key) } 84 func (v *RevNat6Key) New() bpf.MapKey { return &RevNat6Key{} } 85 func (v *RevNat6Key) GetKey() uint16 { return v.Key } 86 87 // ToNetwork converts RevNat6Key to network byte order. 88 func (v *RevNat6Key) ToNetwork() RevNatKey { 89 n := *v 90 n.Key = byteorder.HostToNetwork16(n.Key) 91 return &n 92 } 93 94 // ToNetwork converts RevNat6Key to host byte order. 95 func (v *RevNat6Key) ToHost() RevNatKey { 96 h := *v 97 h.Key = byteorder.NetworkToHost16(h.Key) 98 return &h 99 } 100 101 type RevNat6Value struct { 102 Address types.IPv6 `align:"address"` 103 Port uint16 `align:"port"` 104 } 105 106 func (v *RevNat6Value) String() string { 107 vHost := v.ToHost().(*RevNat6Value) 108 return net.JoinHostPort(vHost.Address.String(), fmt.Sprintf("%d", vHost.Port)) 109 } 110 111 func (v *RevNat6Value) New() bpf.MapValue { return &RevNat6Value{} } 112 113 // ToNetwork converts RevNat6Value to network byte order. 114 func (v *RevNat6Value) ToNetwork() RevNatValue { 115 n := *v 116 n.Port = byteorder.HostToNetwork16(n.Port) 117 return &n 118 } 119 120 // ToNetwork converts RevNat6Value to Host byte order. 121 func (v *RevNat6Value) ToHost() RevNatValue { 122 h := *v 123 h.Port = byteorder.NetworkToHost16(h.Port) 124 return &h 125 } 126 127 // Service6Key must match 'struct lb6_key' in "bpf/lib/common.h". 128 type Service6Key struct { 129 Address types.IPv6 `align:"address"` 130 Port uint16 `align:"dport"` 131 BackendSlot uint16 `align:"backend_slot"` 132 Proto uint8 `align:"proto"` 133 Scope uint8 `align:"scope"` 134 Pad pad2uint8 `align:"pad"` 135 } 136 137 func NewService6Key(ip net.IP, port uint16, proto u8proto.U8proto, scope uint8, slot uint16) *Service6Key { 138 key := Service6Key{ 139 Port: port, 140 Proto: uint8(proto), 141 Scope: scope, 142 BackendSlot: slot, 143 } 144 145 copy(key.Address[:], ip.To16()) 146 147 return &key 148 } 149 150 func (k *Service6Key) String() string { 151 kHost := k.ToHost().(*Service6Key) 152 if kHost.Scope == loadbalancer.ScopeInternal { 153 return fmt.Sprintf("[%s]:%d/i (%d)", kHost.Address, kHost.Port, kHost.BackendSlot) 154 } else { 155 return fmt.Sprintf("[%s]:%d (%d)", kHost.Address, kHost.Port, kHost.BackendSlot) 156 } 157 } 158 159 func (k *Service6Key) New() bpf.MapKey { return &Service6Key{} } 160 161 func (k *Service6Key) IsIPv6() bool { return true } 162 func (k *Service6Key) IsSurrogate() bool { return k.GetAddress().IsUnspecified() } 163 func (k *Service6Key) Map() *bpf.Map { return Service6MapV2 } 164 func (k *Service6Key) SetBackendSlot(slot int) { k.BackendSlot = uint16(slot) } 165 func (k *Service6Key) GetBackendSlot() int { return int(k.BackendSlot) } 166 func (k *Service6Key) SetScope(scope uint8) { k.Scope = scope } 167 func (k *Service6Key) GetScope() uint8 { return k.Scope } 168 func (k *Service6Key) GetAddress() net.IP { return k.Address.IP() } 169 func (k *Service6Key) GetPort() uint16 { return k.Port } 170 func (k *Service6Key) MapDelete() error { return k.Map().Delete(k.ToNetwork()) } 171 172 func (k *Service6Key) RevNatValue() RevNatValue { 173 return &RevNat6Value{ 174 Address: k.Address, 175 Port: k.Port, 176 } 177 } 178 179 func (k *Service6Key) ToNetwork() ServiceKey { 180 n := *k 181 n.Port = byteorder.HostToNetwork16(n.Port) 182 return &n 183 } 184 185 // ToHost converts Service6Key to host byte order. 186 func (k *Service6Key) ToHost() ServiceKey { 187 h := *k 188 h.Port = byteorder.NetworkToHost16(h.Port) 189 return &h 190 } 191 192 // Service6Value must match 'struct lb6_service' in "bpf/lib/common.h". 193 type Service6Value struct { 194 BackendID uint32 `align:"$union0"` 195 Count uint16 `align:"count"` 196 RevNat uint16 `align:"rev_nat_index"` 197 Flags uint8 `align:"flags"` 198 Flags2 uint8 `align:"flags2"` 199 Pad pad2uint8 `align:"pad"` 200 } 201 202 func (s *Service6Value) New() bpf.MapValue { return &Service6Value{} } 203 204 func (s *Service6Value) String() string { 205 sHost := s.ToHost().(*Service6Value) 206 return fmt.Sprintf("%d %d (%d) [0x%x 0x%x]", sHost.BackendID, sHost.Count, sHost.RevNat, sHost.Flags, sHost.Flags2) 207 } 208 209 func (s *Service6Value) SetCount(count int) { s.Count = uint16(count) } 210 func (s *Service6Value) GetCount() int { return int(s.Count) } 211 func (s *Service6Value) SetRevNat(id int) { s.RevNat = uint16(id) } 212 func (s *Service6Value) GetRevNat() int { return int(s.RevNat) } 213 func (s *Service6Value) RevNatKey() RevNatKey { return &RevNat6Key{s.RevNat} } 214 func (s *Service6Value) SetFlags(flags uint16) { 215 s.Flags = uint8(flags & 0xff) 216 s.Flags2 = uint8(flags >> 8) 217 } 218 219 func (s *Service6Value) GetFlags() uint16 { 220 return (uint16(s.Flags2) << 8) | uint16(s.Flags) 221 } 222 223 func (s *Service6Value) SetSessionAffinityTimeoutSec(t uint32) { 224 // See (* Service4Value).SetSessionAffinityTimeoutSec() for comment 225 s.BackendID = t 226 } 227 228 func (s *Service6Value) SetL7LBProxyPort(port uint16) { 229 // Go doesn't support union types, so we use BackendID to access the 230 // lb6_service.l7_lb_proxy_port field 231 s.BackendID = uint32(byteorder.HostToNetwork16(port)) 232 } 233 234 func (s *Service6Value) SetBackendID(id loadbalancer.BackendID) { 235 s.BackendID = uint32(id) 236 } 237 func (s *Service6Value) GetBackendID() loadbalancer.BackendID { 238 return loadbalancer.BackendID(s.BackendID) 239 } 240 241 func (s *Service6Value) ToNetwork() ServiceValue { 242 n := *s 243 n.RevNat = byteorder.HostToNetwork16(n.RevNat) 244 return &n 245 } 246 247 // ToHost converts Service6Value to host byte order. 248 func (s *Service6Value) ToHost() ServiceValue { 249 h := *s 250 h.RevNat = byteorder.NetworkToHost16(h.RevNat) 251 return &h 252 } 253 254 type Backend6KeyV3 struct { 255 ID loadbalancer.BackendID 256 } 257 258 func NewBackend6KeyV3(id loadbalancer.BackendID) *Backend6KeyV3 { 259 return &Backend6KeyV3{ID: id} 260 } 261 262 func (k *Backend6KeyV3) String() string { return fmt.Sprintf("%d", k.ID) } 263 func (k *Backend6KeyV3) New() bpf.MapKey { return &Backend6KeyV3{} } 264 func (k *Backend6KeyV3) Map() *bpf.Map { return Backend6MapV3 } 265 func (k *Backend6KeyV3) SetID(id loadbalancer.BackendID) { k.ID = id } 266 func (k *Backend6KeyV3) GetID() loadbalancer.BackendID { return k.ID } 267 268 type Backend6Key struct { 269 ID uint16 270 } 271 272 func (k *Backend6Key) String() string { return fmt.Sprintf("%d", k.ID) } 273 func (k *Backend6Key) New() bpf.MapKey { return &Backend6Key{} } 274 func (k *Backend6Key) Map() *bpf.Map { return Backend6Map } 275 func (k *Backend6Key) SetID(id loadbalancer.BackendID) { k.ID = uint16(id) } 276 func (k *Backend6Key) GetID() loadbalancer.BackendID { return loadbalancer.BackendID(k.ID) } 277 278 // Backend6Value must match 'struct lb6_backend' in "bpf/lib/common.h". 279 type Backend6Value struct { 280 Address types.IPv6 `align:"address"` 281 Port uint16 `align:"port"` 282 Proto u8proto.U8proto `align:"proto"` 283 Flags uint8 `align:"flags"` 284 } 285 286 func NewBackend6Value(ip net.IP, port uint16, proto u8proto.U8proto, state loadbalancer.BackendState) (*Backend6Value, error) { 287 ip6 := ip.To16() 288 if ip6 == nil { 289 return nil, fmt.Errorf("Not an IPv6 address") 290 } 291 flags := loadbalancer.NewBackendFlags(state) 292 293 val := Backend6Value{ 294 Port: port, 295 Proto: proto, 296 Flags: flags, 297 } 298 copy(val.Address[:], ip.To16()) 299 300 return &val, nil 301 } 302 303 func (v *Backend6Value) String() string { 304 vHost := v.ToHost().(*Backend6Value) 305 return fmt.Sprintf("%s://[%s]:%d", vHost.Proto, vHost.Address, vHost.Port) 306 } 307 func (v *Backend6Value) New() bpf.MapValue { return &Backend6Value{} } 308 309 func (b *Backend6Value) GetAddress() net.IP { return b.Address.IP() } 310 func (b *Backend6Value) GetIPCluster() cmtypes.AddrCluster { 311 return cmtypes.AddrClusterFrom(b.Address.Addr(), 0) 312 } 313 func (b *Backend6Value) GetPort() uint16 { return b.Port } 314 func (b *Backend6Value) GetFlags() uint8 { return b.Flags } 315 func (b *Backend6Value) GetZone() uint8 { return 0 } 316 317 func (v *Backend6Value) ToNetwork() BackendValue { 318 n := *v 319 n.Port = byteorder.HostToNetwork16(n.Port) 320 return &n 321 } 322 323 // ToHost converts Backend6Value to host byte order. 324 func (v *Backend6Value) ToHost() BackendValue { 325 h := *v 326 h.Port = byteorder.NetworkToHost16(h.Port) 327 return &h 328 } 329 330 type Backend6ValueV3 struct { 331 Address types.IPv6 `align:"address"` 332 Port uint16 `align:"port"` 333 Proto u8proto.U8proto `align:"proto"` 334 Flags uint8 `align:"flags"` 335 ClusterID uint16 `align:"cluster_id"` 336 Zone uint8 `align:"zone"` 337 Pad uint8 `align:"pad"` 338 } 339 340 func NewBackend6ValueV3(addrCluster cmtypes.AddrCluster, port uint16, proto u8proto.U8proto, state loadbalancer.BackendState, zone uint8) (*Backend6ValueV3, error) { 341 addr := addrCluster.Addr() 342 343 // It is possible to have IPv4 backend in IPv6. We have NAT46/64. 344 if !addr.Is4() && !addr.Is6() { 345 return nil, fmt.Errorf("Not a valid IP address") 346 } 347 348 if addrCluster.ClusterID() > cmtypes.ClusterIDMax { 349 return nil, fmt.Errorf("ClusterID %d is too large. ClusterID > %d is not supported with Backend6ValueV3", addrCluster.ClusterID(), cmtypes.ClusterIDMax) 350 } 351 352 flags := loadbalancer.NewBackendFlags(state) 353 354 val := Backend6ValueV3{ 355 Port: port, 356 Proto: proto, 357 Flags: flags, 358 Zone: zone, 359 } 360 361 ipv6Array := addr.As16() 362 copy(val.Address[:], ipv6Array[:]) 363 364 return &val, nil 365 } 366 367 func (v *Backend6ValueV3) String() string { 368 vHost := v.ToHost().(*Backend6ValueV3) 369 if v.Zone != 0 { 370 return fmt.Sprintf("%s://%s[%s]", vHost.Proto, cmtypes.AddrClusterFrom(vHost.Address.Addr(), uint32(vHost.ClusterID)), option.Config.GetZone(v.Zone)) 371 } 372 return fmt.Sprintf("%s://%s", vHost.Proto, cmtypes.AddrClusterFrom(vHost.Address.Addr(), uint32(vHost.ClusterID))) 373 } 374 375 func (v *Backend6ValueV3) New() bpf.MapValue { return &Backend6ValueV3{} } 376 377 func (b *Backend6ValueV3) GetAddress() net.IP { return b.Address.IP() } 378 func (b *Backend6ValueV3) GetIPCluster() cmtypes.AddrCluster { 379 return cmtypes.AddrClusterFrom(b.Address.Addr(), uint32(b.ClusterID)) 380 } 381 func (b *Backend6ValueV3) GetPort() uint16 { return b.Port } 382 func (b *Backend6ValueV3) GetFlags() uint8 { return b.Flags } 383 func (b *Backend6ValueV3) GetZone() uint8 { return b.Zone } 384 385 func (v *Backend6ValueV3) ToNetwork() BackendValue { 386 n := *v 387 n.Port = byteorder.HostToNetwork16(n.Port) 388 return &n 389 } 390 391 // ToHost converts Backend6ValueV3 to host byte order. 392 func (v *Backend6ValueV3) ToHost() BackendValue { 393 h := *v 394 h.Port = byteorder.NetworkToHost16(h.Port) 395 return &h 396 } 397 398 type Backend6V3 struct { 399 Key *Backend6KeyV3 400 Value *Backend6ValueV3 401 } 402 403 func NewBackend6V3(id loadbalancer.BackendID, addrCluster cmtypes.AddrCluster, port uint16, 404 proto u8proto.U8proto, state loadbalancer.BackendState, zone uint8) (*Backend6V3, error) { 405 val, err := NewBackend6ValueV3(addrCluster, port, proto, state, zone) 406 if err != nil { 407 return nil, err 408 } 409 410 return &Backend6V3{ 411 Key: NewBackend6KeyV3(id), 412 Value: val, 413 }, nil 414 } 415 416 func (b *Backend6V3) Map() *bpf.Map { return Backend6MapV3 } 417 func (b *Backend6V3) GetKey() BackendKey { return b.Key } 418 func (b *Backend6V3) GetValue() BackendValue { return b.Value } 419 420 type Backend6V2 struct { 421 Key *Backend6KeyV3 422 Value *Backend6Value 423 } 424 425 func NewBackend6V2(id loadbalancer.BackendID, ip net.IP, port uint16, proto u8proto.U8proto, 426 state loadbalancer.BackendState) (*Backend6V2, error) { 427 val, err := NewBackend6Value(ip, port, proto, state) 428 if err != nil { 429 return nil, err 430 } 431 432 return &Backend6V2{ 433 Key: NewBackend6KeyV3(id), 434 Value: val, 435 }, nil 436 } 437 438 func (b *Backend6V2) Map() *bpf.Map { return Backend6MapV2 } 439 func (b *Backend6V2) GetKey() BackendKey { return b.Key } 440 func (b *Backend6V2) GetValue() BackendValue { return b.Value } 441 442 type Backend6 struct { 443 Key *Backend6Key 444 Value *Backend6Value 445 } 446 447 func (b *Backend6) Map() *bpf.Map { return Backend6Map } 448 func (b *Backend6) GetKey() BackendKey { return b.Key } 449 func (b *Backend6) GetValue() BackendValue { return b.Value } 450 451 // SockRevNat6Key is the tuple with address, port and cookie used as key in 452 // the reverse NAT sock map. 453 type SockRevNat6Key struct { 454 Cookie uint64 `align:"cookie"` 455 Address types.IPv6 `align:"address"` 456 Port int16 `align:"port"` 457 _ [6]byte 458 } 459 460 // SizeofSockRevNat6Key is the size of type SockRevNat6Key. 461 const SizeofSockRevNat6Key = int(unsafe.Sizeof(SockRevNat6Key{})) 462 463 // SockRevNat6Value is an entry in the reverse NAT sock map. 464 type SockRevNat6Value struct { 465 address types.IPv6 `align:"address"` 466 port int16 `align:"port"` 467 revNatIndex uint16 `align:"rev_nat_index"` 468 } 469 470 // SizeofSockRevNat6Value is the size of type SockRevNat6Value. 471 const SizeofSockRevNat6Value = int(unsafe.Sizeof(SockRevNat6Value{})) 472 473 func (k *SockRevNat6Key) Map() *bpf.Map { return SockRevNat6Map } 474 475 func NewSockRevNat6Key(cookie uint64, addr net.IP, port uint16) *SockRevNat6Key { 476 var key SockRevNat6Key 477 478 key.Cookie = cookie 479 key.Port = int16(byteorder.NetworkToHost16(port)) 480 ipv6Array := addr.To16() 481 copy(key.Address[:], ipv6Array[:]) 482 483 return &key 484 } 485 486 // String converts the key into a human readable string format. 487 func (k *SockRevNat6Key) String() string { 488 return fmt.Sprintf("[%s]:%d, %d", k.Address, k.Port, k.Cookie) 489 } 490 491 func (k *SockRevNat6Key) New() bpf.MapKey { return &SockRevNat6Key{} } 492 493 // String converts the value into a human readable string format. 494 func (v *SockRevNat6Value) String() string { 495 return fmt.Sprintf("[%s]:%d, %d", v.address, v.port, v.revNatIndex) 496 } 497 498 func (v *SockRevNat6Value) New() bpf.MapValue { return &SockRevNat6Value{} } 499 500 // CreateSockRevNat6Map creates the reverse NAT sock map. 501 func CreateSockRevNat6Map() error { 502 SockRevNat6Map = bpf.NewMap(SockRevNat6MapName, 503 ebpf.LRUHash, 504 &SockRevNat6Key{}, 505 &SockRevNat6Value{}, 506 MaxSockRevNat6MapEntries, 507 0, 508 ).WithPressureMetric() 509 return SockRevNat6Map.OpenOrCreate() 510 }