github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/maps/lbmap/ipv6.go (about) 1 // Copyright 2016-2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package lbmap 16 17 import ( 18 "fmt" 19 "net" 20 "unsafe" 21 22 "github.com/cilium/cilium/common/types" 23 "github.com/cilium/cilium/pkg/bpf" 24 "github.com/cilium/cilium/pkg/byteorder" 25 "github.com/cilium/cilium/pkg/loadbalancer" 26 "github.com/cilium/cilium/pkg/u8proto" 27 ) 28 29 var ( 30 // Service6Map represents the BPF map for services in IPv6 load balancer 31 Service6Map = bpf.NewMap("cilium_lb6_services", 32 bpf.MapTypeHash, 33 &Service6Key{}, 34 int(unsafe.Sizeof(Service6Key{})), 35 &Service6Value{}, 36 int(unsafe.Sizeof(Service6Value{})), 37 MaxEntries, 38 0, 0, 39 func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) { 40 svcKey, svcVal := mapKey.(*Service6Key), mapValue.(*Service6Value) 41 42 if _, _, err := bpf.ConvertKeyValue(key, value, svcKey, svcVal); err != nil { 43 return nil, nil, err 44 } 45 46 return svcKey.ToNetwork(), svcVal.ToNetwork(), nil 47 }).WithCache() 48 Service6MapV2 = bpf.NewMap("cilium_lb6_services_v2", 49 bpf.MapTypeHash, 50 &Service6KeyV2{}, 51 int(unsafe.Sizeof(Service6KeyV2{})), 52 &Service6ValueV2{}, 53 int(unsafe.Sizeof(Service6ValueV2{})), 54 MaxEntries, 55 0, 0, 56 func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) { 57 svcKey, svcVal := mapKey.(*Service6KeyV2), mapValue.(*Service6ValueV2) 58 59 if _, _, err := bpf.ConvertKeyValue(key, value, svcKey, svcVal); err != nil { 60 return nil, nil, err 61 } 62 63 return svcKey.ToNetwork(), svcVal.ToNetwork(), nil 64 }).WithCache() 65 Backend6Map = bpf.NewMap("cilium_lb6_backends", 66 bpf.MapTypeHash, 67 &Backend6Key{}, 68 int(unsafe.Sizeof(Backend6Key{})), 69 &Backend6Value{}, 70 int(unsafe.Sizeof(Backend6Value{})), 71 MaxEntries, 72 0, 0, 73 func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) { 74 backendVal := mapValue.(*Backend6Value) 75 76 if _, _, err := bpf.ConvertKeyValue(key, value, mapKey, backendVal); err != nil { 77 return nil, nil, err 78 } 79 80 return mapKey, backendVal.ToNetwork(), nil 81 }).WithCache() 82 // RevNat6Map represents the BPF map for reverse NAT in IPv6 load balancer 83 RevNat6Map = bpf.NewMap("cilium_lb6_reverse_nat", 84 bpf.MapTypeHash, 85 &RevNat6Key{}, 86 int(unsafe.Sizeof(RevNat6Key{})), 87 &RevNat6Value{}, 88 int(unsafe.Sizeof(RevNat6Value{})), 89 MaxEntries, 90 0, 0, 91 func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) { 92 revKey, revNat := mapKey.(*RevNat6Key), mapValue.(*RevNat6Value) 93 94 if _, _, err := bpf.ConvertKeyValue(key, value, revKey, revNat); err != nil { 95 return nil, nil, err 96 } 97 98 return revKey.ToNetwork(), revNat.ToNetwork(), nil 99 }).WithCache() 100 // RRSeq6Map represents the BPF map for wrr sequences in IPv6 load balancer 101 RRSeq6Map = bpf.NewMap("cilium_lb6_rr_seq", 102 bpf.MapTypeHash, 103 &Service6Key{}, 104 int(unsafe.Sizeof(Service6Key{})), 105 &RRSeqValue{}, 106 int(unsafe.Sizeof(RRSeqValue{})), 107 maxFrontEnds, 108 0, 0, 109 func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) { 110 svcKey := mapKey.(*Service6Key) 111 112 if _, _, err := bpf.ConvertKeyValue(key, value, svcKey, mapValue); err != nil { 113 return nil, nil, err 114 } 115 116 return svcKey.ToNetwork(), mapValue, nil 117 }).WithCache() 118 // RRSeq6MapV2 represents the BPF map for wrr sequences in IPv6 load balancer 119 RRSeq6MapV2 = bpf.NewMap("cilium_lb6_rr_seq_v2", 120 bpf.MapTypeHash, 121 &Service6KeyV2{}, 122 int(unsafe.Sizeof(Service6KeyV2{})), 123 &RRSeqValue{}, 124 int(unsafe.Sizeof(RRSeqValue{})), 125 maxFrontEnds, 126 0, 0, 127 func(key []byte, value []byte, mapKey bpf.MapKey, mapValue bpf.MapValue) (bpf.MapKey, bpf.MapValue, error) { 128 svcKey := mapKey.(*Service6KeyV2) 129 130 if _, _, err := bpf.ConvertKeyValue(key, value, svcKey, mapValue); err != nil { 131 return nil, nil, err 132 } 133 134 return svcKey.ToNetwork(), mapValue, nil 135 }).WithCache() 136 ) 137 138 // Service6Key must match 'struct lb6_key' in "bpf/lib/common.h". 139 // +k8s:deepcopy-gen=true 140 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey 141 type Service6Key struct { 142 Address types.IPv6 `align:"address"` 143 Port uint16 `align:"dport"` 144 Slave uint16 `align:"slave"` 145 } 146 147 func NewService6Key(ip net.IP, port uint16, slave uint16) *Service6Key { 148 key := Service6Key{ 149 Port: port, 150 Slave: slave, 151 } 152 153 copy(key.Address[:], ip.To16()) 154 155 return &key 156 } 157 158 func (k Service6Key) IsIPv6() bool { return true } 159 func (k Service6Key) Map() *bpf.Map { return Service6Map } 160 func (k Service6Key) RRMap() *bpf.Map { return RRSeq6Map } 161 func (k Service6Key) NewValue() bpf.MapValue { return &Service6Value{} } 162 func (k *Service6Key) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) } 163 func (k *Service6Key) GetPort() uint16 { return k.Port } 164 func (k *Service6Key) SetPort(port uint16) { k.Port = port } 165 func (k *Service6Key) SetBackend(backend int) { k.Slave = uint16(backend) } 166 func (k *Service6Key) GetBackend() int { return int(k.Slave) } 167 168 // ToNetwork converts Service6Key to network byte order. 169 func (k *Service6Key) ToNetwork() ServiceKey { 170 n := *k 171 n.Port = byteorder.HostToNetwork(n.Port).(uint16) 172 return &n 173 } 174 175 // ToHost converts Service6Key to host byte order. 176 func (k *Service6Key) ToHost() ServiceKey { 177 n := *k 178 n.Port = byteorder.NetworkToHost(n.Port).(uint16) 179 return &n 180 } 181 182 func (k *Service6Key) String() string { 183 return fmt.Sprintf("[%s]:%d", k.Address, k.Port) 184 } 185 186 func (k *Service6Key) RevNatValue() RevNatValue { 187 return &RevNat6Value{ 188 Address: k.Address, 189 Port: k.Port, 190 } 191 } 192 193 // Service6Value must match 'struct lb6_service' in "bpf/lib/common.h". 194 // +k8s:deepcopy-gen=true 195 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue 196 type Service6Value struct { 197 Address types.IPv6 `align:"target"` 198 Port uint16 `align:"port"` 199 Count uint16 `align:"count"` 200 RevNat uint16 `align:"rev_nat_index"` 201 Weight uint16 `align:"weight"` 202 } 203 204 func NewService6Value(count uint16, target net.IP, port uint16, revNat uint16, weight uint16) *Service6Value { 205 svc := Service6Value{ 206 Count: count, 207 Port: port, 208 RevNat: revNat, 209 Weight: weight, 210 } 211 212 copy(svc.Address[:], target.To16()) 213 214 return &svc 215 } 216 217 func (s *Service6Value) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(s) } 218 func (s *Service6Value) SetPort(port uint16) { s.Port = port } 219 func (s *Service6Value) GetPort() uint16 { return s.Port } 220 func (s *Service6Value) SetCount(count int) { s.Count = uint16(count) } 221 func (s *Service6Value) GetCount() int { return int(s.Count) } 222 func (s *Service6Value) SetRevNat(id int) { s.RevNat = uint16(id) } 223 func (s *Service6Value) RevNatKey() RevNatKey { return &RevNat6Key{s.RevNat} } 224 func (s *Service6Value) SetWeight(weight uint16) { s.Weight = weight } 225 func (s *Service6Value) GetWeight() uint16 { return s.Weight } 226 func (s *Service6Value) IsIPv6() bool { return true } 227 228 func (s *Service6Value) SetAddress(ip net.IP) error { 229 if ip.To4() != nil { 230 return fmt.Errorf("Not an IPv6 address") 231 } 232 233 copy(s.Address[:], ip.To16()) 234 return nil 235 } 236 237 func (s *Service6Value) GetAddress() net.IP { 238 return s.Address.IP() 239 } 240 241 // ToNetwork converts Service6Value ports to network byte order. 242 func (s *Service6Value) ToNetwork() ServiceValue { 243 n := *s 244 n.RevNat = byteorder.HostToNetwork(n.RevNat).(uint16) 245 n.Port = byteorder.HostToNetwork(n.Port).(uint16) 246 n.Weight = byteorder.HostToNetwork(n.Weight).(uint16) 247 return &n 248 } 249 250 // ToHost converts Service6Value ports to host byte order. 251 func (s *Service6Value) ToHost() ServiceValue { 252 n := *s 253 n.RevNat = byteorder.NetworkToHost(n.RevNat).(uint16) 254 n.Port = byteorder.NetworkToHost(n.Port).(uint16) 255 n.Weight = byteorder.NetworkToHost(n.Weight).(uint16) 256 return &n 257 } 258 259 func (s *Service6Value) String() string { 260 return fmt.Sprintf("[%s]:%d (%d)", s.Address, s.Port, s.RevNat) 261 } 262 263 func (s *Service6Value) BackendAddrID() BackendAddrID { 264 return BackendAddrID(fmt.Sprintf("[%s]:%d", s.Address, s.Port)) 265 } 266 267 // +k8s:deepcopy-gen=true 268 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey 269 type RevNat6Key struct { 270 Key uint16 271 } 272 273 func NewRevNat6Key(value uint16) *RevNat6Key { 274 return &RevNat6Key{value} 275 } 276 277 func (v *RevNat6Key) IsIPv6() bool { return true } 278 func (v *RevNat6Key) Map() *bpf.Map { return RevNat6Map } 279 func (v *RevNat6Key) NewValue() bpf.MapValue { return &RevNat6Value{} } 280 func (v *RevNat6Key) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(v) } 281 func (v *RevNat6Key) String() string { return fmt.Sprintf("%d", v.Key) } 282 func (v *RevNat6Key) GetKey() uint16 { return v.Key } 283 284 // ToNetwork converts RevNat6Key to network byte order. 285 func (v *RevNat6Key) ToNetwork() RevNatKey { 286 n := *v 287 n.Key = byteorder.HostToNetwork(n.Key).(uint16) 288 return &n 289 } 290 291 // +k8s:deepcopy-gen=true 292 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue 293 type RevNat6Value struct { 294 Address types.IPv6 295 Port uint16 296 } 297 298 func NewRevNat6Value(ip net.IP, port uint16) *RevNat6Value { 299 revNat := RevNat6Value{ 300 Port: port, 301 } 302 303 copy(revNat.Address[:], ip.To16()) 304 305 return &revNat 306 } 307 308 func (v *RevNat6Value) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(v) } 309 func (v *RevNat6Value) String() string { return fmt.Sprintf("%s:%d", v.Address, v.Port) } 310 311 // ToNetwork converts RevNat6Value to network byte order. 312 func (v *RevNat6Value) ToNetwork() RevNatValue { 313 n := *v 314 n.Port = byteorder.HostToNetwork(n.Port).(uint16) 315 return &n 316 } 317 318 // Service6KeyV2 must match 'struct lb6_key_v2' in "bpf/lib/common.h". 319 // +k8s:deepcopy-gen=true 320 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey 321 type Service6KeyV2 struct { 322 Address types.IPv6 `align:"address"` 323 Port uint16 `align:"dport"` 324 Slave uint16 `align:"slave"` 325 Proto uint8 `align:"proto"` 326 Pad pad3uint8 327 } 328 329 func NewService6KeyV2(ip net.IP, port uint16, proto u8proto.U8proto, slave uint16) *Service6KeyV2 { 330 key := Service6KeyV2{ 331 Port: port, 332 Proto: uint8(proto), 333 Slave: slave, 334 } 335 336 copy(key.Address[:], ip.To16()) 337 338 return &key 339 } 340 341 func (k *Service6KeyV2) String() string { 342 return fmt.Sprintf("[%s]:%d", k.Address, k.Port) 343 } 344 345 func (k *Service6KeyV2) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) } 346 func (k *Service6KeyV2) NewValue() bpf.MapValue { return &Service6ValueV2{} } 347 func (k *Service6KeyV2) IsIPv6() bool { return true } 348 func (k *Service6KeyV2) Map() *bpf.Map { return Service6MapV2 } 349 func (k *Service6KeyV2) RRMap() *bpf.Map { return RRSeq6MapV2 } 350 func (k *Service6KeyV2) SetSlave(slave int) { k.Slave = uint16(slave) } 351 func (k *Service6KeyV2) GetSlave() int { return int(k.Slave) } 352 func (k *Service6KeyV2) GetAddress() net.IP { return k.Address.IP() } 353 func (k *Service6KeyV2) GetPort() uint16 { return k.Port } 354 func (k *Service6KeyV2) MapDelete() error { return k.Map().Delete(k.ToNetwork()) } 355 356 func (k *Service6KeyV2) ToNetwork() ServiceKeyV2 { 357 n := *k 358 n.Port = byteorder.HostToNetwork(n.Port).(uint16) 359 return &n 360 } 361 362 // Service6ValueV2 must match 'struct lb6_service_v2' in "bpf/lib/common.h". 363 // +k8s:deepcopy-gen=true 364 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue 365 type Service6ValueV2 struct { 366 BackendID uint32 `align:"backend_id"` 367 Count uint16 `align:"count"` 368 RevNat uint16 `align:"rev_nat_index"` 369 Weight uint16 `align:"weight"` 370 Pad uint16 371 } 372 373 func NewService6ValueV2(count uint16, backendID loadbalancer.BackendID, revNat uint16, weight uint16) *Service6ValueV2 { 374 svc := Service6ValueV2{ 375 Count: count, 376 BackendID: uint32(backendID), 377 RevNat: revNat, 378 Weight: weight, 379 } 380 381 return &svc 382 } 383 384 func (s *Service6ValueV2) String() string { 385 return fmt.Sprintf("%d (%d)", s.BackendID, s.RevNat) 386 } 387 388 func (s *Service6ValueV2) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(s) } 389 390 func (s *Service6ValueV2) SetCount(count int) { s.Count = uint16(count) } 391 func (s *Service6ValueV2) GetCount() int { return int(s.Count) } 392 func (s *Service6ValueV2) SetRevNat(id int) { s.RevNat = uint16(id) } 393 func (s *Service6ValueV2) GetRevNat() int { return int(s.RevNat) } 394 func (s *Service6ValueV2) SetWeight(weight uint16) { s.Weight = weight } 395 func (s *Service6ValueV2) GetWeight() uint16 { return s.Weight } 396 func (s *Service6ValueV2) RevNatKey() RevNatKey { return &RevNat6Key{s.RevNat} } 397 398 func (s *Service6ValueV2) SetBackendID(id loadbalancer.BackendID) { 399 s.BackendID = uint32(id) 400 } 401 func (s *Service6ValueV2) GetBackendID() loadbalancer.BackendID { 402 return loadbalancer.BackendID(s.BackendID) 403 } 404 405 func (s *Service6ValueV2) ToNetwork() ServiceValueV2 { 406 n := *s 407 n.RevNat = byteorder.HostToNetwork(n.RevNat).(uint16) 408 n.Weight = byteorder.HostToNetwork(n.Weight).(uint16) 409 return &n 410 } 411 412 // +k8s:deepcopy-gen=true 413 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey 414 type Backend6Key struct { 415 ID loadbalancer.BackendID 416 } 417 418 func NewBackend6Key(id loadbalancer.BackendID) *Backend6Key { 419 return &Backend6Key{ID: id} 420 } 421 422 func (k *Backend6Key) String() string { return fmt.Sprintf("%d", k.ID) } 423 func (k *Backend6Key) GetKeyPtr() unsafe.Pointer { return unsafe.Pointer(k) } 424 func (k *Backend6Key) NewValue() bpf.MapValue { return &Backend6Value{} } 425 func (k *Backend6Key) Map() *bpf.Map { return Backend6Map } 426 func (k *Backend6Key) SetID(id loadbalancer.BackendID) { k.ID = id } 427 func (k *Backend6Key) GetID() loadbalancer.BackendID { return k.ID } 428 429 // Backend6Value must match 'struct lb6_backend' in "bpf/lib/common.h". 430 // +k8s:deepcopy-gen=true 431 // +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue 432 type Backend6Value struct { 433 Address types.IPv6 `align:"address"` 434 Port uint16 `align:"port"` 435 Proto u8proto.U8proto `align:"proto"` 436 Pad uint8 437 } 438 439 func NewBackend6Value(ip net.IP, port uint16, proto u8proto.U8proto) (*Backend6Value, error) { 440 ip6 := ip.To16() 441 if ip6 == nil { 442 return nil, fmt.Errorf("Not an IPv6 address") 443 } 444 445 val := Backend6Value{ 446 Port: port, 447 Proto: proto, 448 } 449 copy(val.Address[:], ip.To16()) 450 451 return &val, nil 452 } 453 454 func (v *Backend6Value) String() string { 455 return fmt.Sprintf("%s://[%s]:%d", v.Proto, v.Address, v.Port) 456 } 457 458 func (v *Backend6Value) GetValuePtr() unsafe.Pointer { return unsafe.Pointer(v) } 459 460 func (b *Backend6Value) GetAddress() net.IP { return b.Address.IP() } 461 func (b *Backend6Value) GetPort() uint16 { return b.Port } 462 463 func (b *Backend6Value) BackendAddrID() BackendAddrID { 464 return BackendAddrID(fmt.Sprintf("[%s]:%d", b.Address, b.Port)) 465 } 466 467 func (v *Backend6Value) ToNetwork() BackendValue { 468 n := *v 469 n.Port = byteorder.HostToNetwork(n.Port).(uint16) 470 return &n 471 } 472 473 type Backend6 struct { 474 Key *Backend6Key 475 Value *Backend6Value 476 } 477 478 func NewBackend6(id loadbalancer.BackendID, ip net.IP, port uint16, proto u8proto.U8proto) (*Backend6, error) { 479 val, err := NewBackend6Value(ip, port, proto) 480 if err != nil { 481 return nil, err 482 } 483 484 return &Backend6{ 485 Key: NewBackend6Key(id), 486 Value: val, 487 }, nil 488 } 489 490 func (b *Backend6) IsIPv6() bool { return true } 491 func (b *Backend6) Map() *bpf.Map { return Backend6Map } 492 func (b *Backend6) GetID() loadbalancer.BackendID { return b.Key.GetID() } 493 func (b *Backend6) GetKey() BackendKey { return b.Key } 494 func (b *Backend6) GetValue() BackendValue { return b.Value }