github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/maps/lbmap/lbmap.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 20 "github.com/cilium/cilium/pkg/bpf" 21 "github.com/cilium/cilium/pkg/loadbalancer" 22 "github.com/cilium/cilium/pkg/lock" 23 "github.com/cilium/cilium/pkg/logging" 24 "github.com/cilium/cilium/pkg/logging/logfields" 25 "github.com/cilium/cilium/pkg/option" 26 "github.com/cilium/cilium/pkg/u8proto" 27 28 "github.com/sirupsen/logrus" 29 ) 30 31 var ( 32 log = logging.DefaultLogger.WithField(logfields.LogSubsys, "map-lb") 33 34 // mutex protects access to the BPF map to guarantee atomicity if a 35 // transaction must be split across multiple map access operations. 36 mutex lock.RWMutex 37 ) 38 39 const ( 40 // Maximum number of entries in each hashtable 41 MaxEntries = 65536 42 maxFrontEnds = 256 43 // MaxSeq is used by daemon for generating bpf define LB_RR_MAX_SEQ. 44 MaxSeq = 31 45 ) 46 47 var ( 48 // cache contains *all* services of both IPv4 and IPv6 based maps 49 // combined 50 cache = newLBMapCache() 51 ) 52 53 func updateRevNatLocked(key RevNatKey, value RevNatValue) error { 54 log.WithFields(logrus.Fields{ 55 logfields.BPFMapKey: key, 56 logfields.BPFMapValue: value, 57 }).Debug("adding revNat to lbmap") 58 59 if key.GetKey() == 0 { 60 return fmt.Errorf("invalid RevNat ID (0)") 61 } 62 if _, err := key.Map().OpenOrCreate(); err != nil { 63 return err 64 } 65 66 return key.Map().Update(key.ToNetwork(), value.ToNetwork()) 67 } 68 69 func UpdateRevNat(key RevNatKey, value RevNatValue) error { 70 mutex.Lock() 71 defer mutex.Unlock() 72 73 return updateRevNatLocked(key, value) 74 } 75 76 func deleteRevNatLocked(key RevNatKey) error { 77 log.WithField(logfields.BPFMapKey, key).Debug("deleting RevNatKey") 78 79 return key.Map().Delete(key.ToNetwork()) 80 } 81 82 func DeleteRevNat(key RevNatKey) error { 83 mutex.Lock() 84 defer mutex.Unlock() 85 86 return deleteRevNatLocked(key) 87 } 88 89 // gcd computes the gcd of two numbers. 90 func gcd(x, y uint16) uint16 { 91 for y != 0 { 92 x, y = y, x%y 93 } 94 return x 95 } 96 97 // generateWrrSeq generates a wrr sequence based on provided weights. 98 func generateWrrSeq(weights []uint16) (*RRSeqValue, error) { 99 svcRRSeq := RRSeqValue{} 100 101 n := len(weights) 102 if n < 2 { 103 return nil, fmt.Errorf("needs at least 2 weights") 104 } 105 106 g := uint16(0) 107 for i := 0; i < n; i++ { 108 if weights[i] != 0 { 109 g = gcd(g, weights[i]) 110 } 111 } 112 113 // This means all the weights are 0. 114 if g == 0 { 115 return nil, fmt.Errorf("all specified weights are 0") 116 } 117 118 sum := uint16(0) 119 for i := range weights { 120 // Normalize the weights. 121 weights[i] = weights[i] / g 122 sum += weights[i] 123 } 124 125 // Check if Generated seq fits in our array. 126 if int(sum) > len(svcRRSeq.Idx) { 127 return nil, fmt.Errorf("sum of normalized weights exceeds %d", len(svcRRSeq.Idx)) 128 } 129 130 // Generate the Sequence. 131 i := uint16(0) 132 k := uint16(0) 133 for { 134 j := uint16(0) 135 for j < weights[k] { 136 svcRRSeq.Idx[i] = k 137 i++ 138 j++ 139 } 140 if i >= sum { 141 break 142 } 143 k++ 144 } 145 svcRRSeq.Count = sum 146 return &svcRRSeq, nil 147 } 148 149 // UpdateService adds or updates the given service in the bpf maps. 150 func UpdateService(fe ServiceKey, backends []ServiceValue, 151 addRevNAT bool, revNATID int, 152 acquireBackendID func(loadbalancer.L3n4Addr) (loadbalancer.BackendID, error), 153 releaseBackendID func(loadbalancer.BackendID)) error { 154 155 scopedLog := log.WithFields(logrus.Fields{ 156 "frontend": fe, 157 "backends": backends, 158 }) 159 160 mutex.Lock() 161 defer mutex.Unlock() 162 163 var ( 164 weights []uint16 165 nNonZeroWeights uint16 166 ) 167 168 // Find out which backends are new (i.e. the ones which do not exist yet and 169 // will be created in this function) and acquire IDs for them 170 newBackendIDs, err := acquireNewBackendIDs(backends, acquireBackendID) 171 if err != nil { 172 return err 173 } 174 175 // Store mapping of backend addr ID => backend ID in the cache 176 cache.addBackendIDs(newBackendIDs) 177 178 // Prepare the service cache for the updates 179 svc, addedBackends, removedBackendIDs, err := cache.prepareUpdate(fe, backends) 180 if err != nil { 181 return err 182 } 183 184 // FIXME(brb) Uncomment the following code after we have enabled weights 185 // in the BPF datapath code. 186 //for _, be := range besValues { 187 // weights = append(weights, be.GetWeight()) 188 // if be.GetWeight() != 0 { 189 // nNonZeroWeights++ 190 // } 191 //} 192 193 besValuesV2 := svc.getBackendsV2() 194 195 scopedLog.Debug("Updating BPF representation of service") 196 197 // Add the new backends to the BPF maps 198 if err := updateBackendsLocked(addedBackends); err != nil { 199 return err 200 } 201 202 // Update the v2 service BPF maps 203 if err := updateServiceV2Locked(fe, besValuesV2, svc, addRevNAT, revNATID, weights, nNonZeroWeights); err != nil { 204 return err 205 } 206 207 // Delete no longer needed backends 208 if err := removeBackendsLocked(removedBackendIDs, releaseBackendID); err != nil { 209 return err 210 } 211 212 return nil 213 } 214 215 func acquireNewBackendIDs(backends []ServiceValue, 216 acquireBackendID func(loadbalancer.L3n4Addr) (loadbalancer.BackendID, error)) ( 217 map[BackendAddrID]BackendKey, error) { 218 219 newBackendsByAddrID := serviceValueMap{} 220 for _, b := range backends { 221 newBackendsByAddrID[b.BackendAddrID()] = b 222 } 223 newBackendsByAddrID = cache.filterNewBackends(newBackendsByAddrID) 224 newBackendIDs := map[BackendAddrID]BackendKey{} 225 226 for addrID, value := range newBackendsByAddrID { 227 addr := *serviceValue2L3n4Addr(newBackendsByAddrID[addrID]) 228 backendID, err := acquireBackendID(addr) 229 if err != nil { 230 return nil, fmt.Errorf("Unable to acquire backend ID for %s: %s", addrID, err) 231 } 232 if value.IsIPv6() { 233 newBackendIDs[addrID] = NewBackend6Key(backendID) 234 } else { 235 newBackendIDs[addrID] = NewBackend4Key(backendID) 236 } 237 log.WithFields(logrus.Fields{ 238 logfields.BackendName: addrID, 239 logfields.BackendID: backendID, 240 }).Debug("Acquired backend ID") 241 } 242 return newBackendIDs, nil 243 } 244 245 func updateBackendsLocked(addedBackends map[loadbalancer.BackendID]ServiceValue) error { 246 var err error 247 248 // Create new backends 249 for backendID, svcVal := range addedBackends { 250 var b Backend 251 252 if svcVal.IsIPv6() { 253 svc6Val := svcVal.(*Service6Value) 254 b, err = NewBackend6(backendID, svc6Val.Address.IP(), svc6Val.Port, u8proto.ANY) 255 } else { 256 svc4Val := svcVal.(*Service4Value) 257 b, err = NewBackend4(backendID, svc4Val.Address.IP(), svc4Val.Port, u8proto.ANY) 258 } 259 if err != nil { 260 return err 261 } 262 if err := updateBackend(b); err != nil { 263 return err 264 } 265 } 266 return nil 267 268 } 269 270 func updateServiceV2Locked(fe ServiceKey, backends serviceValueMap, 271 svc *bpfService, 272 addRevNAT bool, revNATID int, 273 weights []uint16, nNonZeroWeights uint16) error { 274 275 var ( 276 existingCount int 277 svcKeyV2 ServiceKeyV2 278 ) 279 280 if fe.IsIPv6() { 281 svc6Key := fe.(*Service6Key) 282 svcKeyV2 = NewService6KeyV2(svc6Key.Address.IP(), svc6Key.Port, u8proto.ANY, 0) 283 } else { 284 svc4Key := fe.(*Service4Key) 285 svcKeyV2 = NewService4KeyV2(svc4Key.Address.IP(), svc4Key.Port, u8proto.ANY, 0) 286 } 287 288 svcValV2, err := lookupServiceV2(svcKeyV2) 289 if err == nil { 290 existingCount = svcValV2.GetCount() 291 } 292 293 svcValV2 = svcKeyV2.NewValue().(ServiceValueV2) 294 slot := 1 295 for addrID, svcVal := range backends { 296 backendKey := cache.getBackendKey(addrID) 297 svcValV2.SetBackendID(backendKey.GetID()) 298 svcValV2.SetRevNat(revNATID) 299 svcValV2.SetWeight(svcVal.GetWeight()) 300 svcKeyV2.SetSlave(slot) 301 if err := updateServiceEndpointV2(svcKeyV2, svcValV2); err != nil { 302 return fmt.Errorf("Unable to update service %+v with the value %+v: %s", 303 svcKeyV2, svcValV2, err) 304 } 305 log.WithFields(logrus.Fields{ 306 logfields.ServiceKey: svcKeyV2, 307 logfields.ServiceValue: svcValV2, 308 logfields.SlaveSlot: slot, 309 }).Debug("Upserted service entry") 310 slot++ 311 } 312 313 if addRevNAT { 314 zeroValue := fe.NewValue().(ServiceValue) 315 zeroValue.SetRevNat(revNATID) 316 revNATKey := zeroValue.RevNatKey() 317 revNATValue := fe.RevNatValue() 318 319 if err := updateRevNatLocked(revNATKey, revNATValue); err != nil { 320 return fmt.Errorf("unable to update reverse NAT %+v with value %+v, %s", revNATKey, revNATValue, err) 321 } 322 defer func() { 323 if err != nil { 324 deleteRevNatLocked(revNATKey) 325 } 326 }() 327 } 328 329 err = updateMasterServiceV2(svcKeyV2, len(svc.backendsV2), nNonZeroWeights, revNATID) 330 if err != nil { 331 return fmt.Errorf("unable to update service %+v: %s", svcKeyV2, err) 332 } 333 334 err = updateWrrSeqV2(svcKeyV2, weights) 335 if err != nil { 336 return fmt.Errorf("unable to update service weights for %s with value %+v: %s", svcKeyV2.String(), weights, err) 337 } 338 339 for i := slot; i <= existingCount; i++ { 340 svcKeyV2.SetSlave(i) 341 if err := deleteServiceLockedV2(svcKeyV2); err != nil { 342 return fmt.Errorf("unable to delete service %+v: %s", svcKeyV2, err) 343 } 344 log.WithFields(logrus.Fields{ 345 logfields.SlaveSlot: i, 346 logfields.ServiceKey: svcKeyV2, 347 }).Debug("Deleted service entry") 348 } 349 350 return nil 351 } 352 353 func removeBackendsLocked(removedBackendIDs []BackendKey, 354 releaseBackendID func(loadbalancer.BackendID)) error { 355 356 for _, backendKey := range removedBackendIDs { 357 if err := deleteBackendLocked(backendKey); err != nil { 358 return fmt.Errorf("Unable to delete backend with ID %d: %s", backendKey, err) 359 } 360 releaseBackendID(backendKey.GetID()) 361 log.WithField(logfields.BackendID, backendKey).Debug("Deleted backend") 362 } 363 364 return nil 365 } 366 367 // DeleteRevNATBPF deletes the revNAT entry from its corresponding BPF map 368 // (IPv4 or IPv6) with ID id. Returns an error if the deletion operation failed. 369 func DeleteRevNATBPF(id loadbalancer.ServiceID, isIPv6 bool) error { 370 var revNATK RevNatKey 371 if isIPv6 { 372 revNATK = NewRevNat6Key(uint16(id)) 373 } else { 374 revNATK = NewRevNat4Key(uint16(id)) 375 } 376 err := DeleteRevNat(revNATK) 377 return err 378 } 379 380 // DumpServiceMapsToUserspaceV2 dumps the services in the same way as 381 // DumpServiceMapsToUserspace. 382 func DumpServiceMapsToUserspaceV2() (loadbalancer.SVCMap, []*loadbalancer.LBSVC, []error) { 383 mutex.RLock() 384 defer mutex.RUnlock() 385 386 newSVCMap := loadbalancer.SVCMap{} 387 newSVCList := []*loadbalancer.LBSVC{} 388 errors := []error{} 389 idCache := map[string]loadbalancer.ServiceID{} 390 backendValueMap := map[loadbalancer.BackendID]BackendValue{} 391 392 parseBackendEntries := func(key bpf.MapKey, value bpf.MapValue) { 393 backendKey := key.(BackendKey) 394 backendValue := value.DeepCopyMapValue().(BackendValue) 395 backendValueMap[backendKey.GetID()] = backendValue 396 } 397 398 parseSVCEntries := func(key bpf.MapKey, value bpf.MapValue) { 399 svcKey := key.DeepCopyMapKey().(ServiceKeyV2) 400 svcValue := value.DeepCopyMapValue().(ServiceValueV2) 401 402 // Skip master service 403 if svcKey.GetSlave() == 0 { 404 return 405 } 406 407 backendID := svcValue.GetBackendID() 408 409 scopedLog := log.WithFields(logrus.Fields{ 410 logfields.BPFMapKey: svcKey, 411 logfields.BPFMapValue: svcValue, 412 }) 413 414 backendValue, found := backendValueMap[backendID] 415 if !found { 416 errors = append(errors, fmt.Errorf("backend %d not found", backendID)) 417 return 418 } 419 420 scopedLog.Debug("parsing service mapping v2") 421 fe, be := serviceKeynValuenBackendValue2FEnBE(svcKey, svcValue, backendID, backendValue) 422 423 // Build a cache to map frontend IP to service ID. The master 424 // service key does not have the service ID set so the cache 425 // needs to be built based on backend key entries. 426 if k := svcValue.RevNatKey().GetKey(); k != uint16(0) { 427 idCache[fe.String()] = loadbalancer.ServiceID(k) 428 } 429 430 svc := newSVCMap.AddFEnBE(fe, be, svcKey.GetSlave()) 431 newSVCList = append(newSVCList, svc) 432 } 433 434 if option.Config.EnableIPv4 { 435 // TODO(brb) optimization: instead of dumping the backend map, we can 436 // pass its content to the function. 437 err := Backend4Map.DumpWithCallback(parseBackendEntries) 438 if err != nil { 439 errors = append(errors, err) 440 } 441 err = Service4MapV2.DumpWithCallback(parseSVCEntries) 442 if err != nil { 443 errors = append(errors, err) 444 } 445 } 446 447 if option.Config.EnableIPv6 { 448 // TODO(brb) same ^^ optimization applies here as well. 449 err := Backend6Map.DumpWithCallback(parseBackendEntries) 450 if err != nil { 451 errors = append(errors, err) 452 } 453 err = Service6MapV2.DumpWithCallback(parseSVCEntries) 454 if err != nil { 455 errors = append(errors, err) 456 } 457 } 458 459 // serviceKeynValue2FEnBE() cannot fill in the service ID reliably as 460 // not all BPF map entries contain the service ID. Do a pass over all 461 // parsed entries and fill in the service ID 462 for i := range newSVCList { 463 newSVCList[i].FE.ID = loadbalancer.ID(idCache[newSVCList[i].FE.String()]) 464 } 465 466 // Do the same for the svcMap 467 for key, svc := range newSVCMap { 468 svc.FE.ID = loadbalancer.ID(idCache[svc.FE.String()]) 469 newSVCMap[key] = svc 470 } 471 472 return newSVCMap, newSVCList, errors 473 } 474 475 // DumpBackendMapsToUserspace dumps the backend entries from the BPF maps. 476 func DumpBackendMapsToUserspace() (map[BackendAddrID]*loadbalancer.LBBackEnd, error) { 477 mutex.RLock() 478 defer mutex.RUnlock() 479 480 backendValueMap := map[loadbalancer.BackendID]BackendValue{} 481 lbBackends := map[BackendAddrID]*loadbalancer.LBBackEnd{} 482 483 parseBackendEntries := func(key bpf.MapKey, value bpf.MapValue) { 484 // No need to deep copy the key because we are using the ID which 485 // is a value. 486 backendKey := key.(BackendKey) 487 backendValue := value.DeepCopyMapValue().(BackendValue) 488 backendValueMap[backendKey.GetID()] = backendValue 489 } 490 491 if option.Config.EnableIPv4 { 492 err := Backend4Map.DumpWithCallback(parseBackendEntries) 493 if err != nil { 494 return nil, fmt.Errorf("Unable to dump lb4 backends map: %s", err) 495 } 496 } 497 498 if option.Config.EnableIPv6 { 499 err := Backend6Map.DumpWithCallback(parseBackendEntries) 500 if err != nil { 501 return nil, fmt.Errorf("Unable to dump lb6 backends map: %s", err) 502 } 503 } 504 505 for backendID, backendVal := range backendValueMap { 506 ip := backendVal.GetAddress() 507 port := backendVal.GetPort() 508 weight := uint16(0) // FIXME(brb): set weight when we support it 509 proto := loadbalancer.NONE 510 lbBackend := loadbalancer.NewLBBackEnd(backendID, proto, ip, port, weight) 511 lbBackends[backendVal.BackendAddrID()] = lbBackend 512 } 513 514 return lbBackends, nil 515 } 516 517 // DumpRevNATMapsToUserspace dumps the contents of both the IPv6 and IPv4 518 // revNAT BPF maps, and stores the contents of said dumps in a RevNATMap. 519 // Returns the errors that occurred while dumping the maps. 520 func DumpRevNATMapsToUserspace() (loadbalancer.RevNATMap, []error) { 521 mutex.RLock() 522 defer mutex.RUnlock() 523 524 newRevNATMap := loadbalancer.RevNATMap{} 525 errors := []error{} 526 527 parseRevNATEntries := func(key bpf.MapKey, value bpf.MapValue) { 528 revNatK := key.DeepCopyMapKey().(RevNatKey) 529 revNatV := value.DeepCopyMapValue().(RevNatValue) 530 scopedLog := log.WithFields(logrus.Fields{ 531 logfields.BPFMapKey: revNatK, 532 logfields.BPFMapValue: revNatV, 533 }) 534 535 scopedLog.Debug("parsing BPF revNAT mapping") 536 fe := revNatValue2L3n4AddrID(revNatK, revNatV) 537 newRevNATMap[loadbalancer.ServiceID(fe.ID)] = fe.L3n4Addr 538 } 539 540 if option.Config.EnableIPv4 { 541 if err := RevNat4Map.DumpWithCallback(parseRevNATEntries); err != nil { 542 err = fmt.Errorf("error dumping RevNat4Map: %s", err) 543 errors = append(errors, err) 544 } 545 } 546 547 if option.Config.EnableIPv6 { 548 if err := RevNat6Map.DumpWithCallback(parseRevNATEntries); err != nil { 549 err = fmt.Errorf("error dumping RevNat6Map: %s", err) 550 errors = append(errors, err) 551 } 552 } 553 554 return newRevNATMap, errors 555 } 556 557 // RestoreService restores a single service in the cache. This is required to 558 // guarantee consistent backend ordering, slave slot and backend by backend 559 // address ID lookups. 560 func RestoreService(svc loadbalancer.LBSVC) error { 561 mutex.Lock() 562 defer mutex.Unlock() 563 564 return cache.restoreService(svc) 565 } 566 567 func lookupServiceV2(key ServiceKeyV2) (ServiceValueV2, error) { 568 val, err := key.Map().Lookup(key.ToNetwork()) 569 if err != nil { 570 return nil, err 571 } 572 svc := val.(ServiceValueV2) 573 574 return svc.ToNetwork(), nil 575 } 576 577 func updateMasterServiceV2(fe ServiceKeyV2, nbackends int, nonZeroWeights uint16, revNATID int) error { 578 fe.SetSlave(0) 579 zeroValue := fe.NewValue().(ServiceValueV2) 580 zeroValue.SetCount(nbackends) 581 zeroValue.SetWeight(nonZeroWeights) 582 zeroValue.SetRevNat(revNATID) 583 584 return updateServiceEndpointV2(fe, zeroValue) 585 } 586 587 // updateWrrSeq updates bpf map with the generated wrr sequence. 588 func updateWrrSeqV2(fe ServiceKeyV2, weights []uint16) error { 589 sum := uint16(0) 590 for _, v := range weights { 591 sum += v 592 } 593 if sum == 0 { 594 return nil 595 } 596 svcRRSeq, err := generateWrrSeq(weights) 597 if err != nil { 598 return fmt.Errorf("unable to generate weighted round robin seq for %s with value %+v: %s", fe.String(), weights, err) 599 } 600 return updateServiceWeightsV2(fe, svcRRSeq) 601 } 602 603 // updateServiceWeightsV2 updates cilium_lb6_rr_seq_v2 or cilium_lb4_rr_seq_v2 bpf maps. 604 func updateServiceWeightsV2(key ServiceKeyV2, value *RRSeqValue) error { 605 if _, err := key.RRMap().OpenOrCreate(); err != nil { 606 return err 607 } 608 609 return key.RRMap().Update(key.ToNetwork(), value) 610 } 611 612 func deleteServiceLockedV2(key ServiceKeyV2) error { 613 err := key.Map().Delete(key.ToNetwork()) 614 if err != nil { 615 return err 616 } 617 return lookupAndDeleteServiceWeightsV2(key) 618 } 619 620 // lookupAndDeleteServiceWeightsV2 deletes entry from cilium_lb6_rr_seq or cilium_lb4_rr_seq 621 func lookupAndDeleteServiceWeightsV2(key ServiceKeyV2) error { 622 _, err := key.RRMap().Lookup(key.ToNetwork()) 623 if err != nil { 624 // Ignore if entry is not found. 625 return nil 626 } 627 628 return key.RRMap().Delete(key.ToNetwork()) 629 } 630 631 func updateBackend(backend Backend) error { 632 if _, err := backend.Map().OpenOrCreate(); err != nil { 633 return err 634 } 635 return backend.Map().Update(backend.GetKey(), backend.GetValue().ToNetwork()) 636 } 637 638 func deleteBackendLocked(key BackendKey) error { 639 return key.Map().Delete(key) 640 } 641 642 func updateServiceEndpointV2(key ServiceKeyV2, value ServiceValueV2) error { 643 log.WithFields(logrus.Fields{ 644 logfields.ServiceKey: key, 645 logfields.ServiceValue: value, 646 logfields.SlaveSlot: key.GetSlave(), 647 }).Debug("Upserting service entry") 648 649 if key.GetSlave() != 0 && value.RevNatKey().GetKey() == 0 { 650 return fmt.Errorf("invalid RevNat ID (0) in the Service Value") 651 } 652 if _, err := key.Map().OpenOrCreate(); err != nil { 653 return err 654 } 655 656 return key.Map().Update(key.ToNetwork(), value.ToNetwork()) 657 } 658 659 // AddBackendIDsToCache populates the given backend IDs to the lbmap local cache. 660 func AddBackendIDsToCache(backendIDs map[BackendAddrID]BackendKey) { 661 mutex.Lock() 662 defer mutex.Unlock() 663 664 cache.addBackendIDs(backendIDs) 665 } 666 667 // DeleteServiceV2 deletes a service from the lbmap and deletes backends of it if 668 // they are not used by any other service. 669 // 670 //The given key has to be of the master service. 671 func DeleteServiceV2(svc loadbalancer.L3n4AddrID, releaseBackendID func(loadbalancer.BackendID)) error { 672 mutex.Lock() 673 defer mutex.Unlock() 674 675 var ( 676 svcKey ServiceKeyV2 677 ) 678 679 isIPv6 := svc.IsIPv6() 680 681 log.WithField(logfields.ServiceName, svc).Debug("Deleting service") 682 683 if isIPv6 { 684 svcKey = NewService6KeyV2(svc.IP, svc.Port, u8proto.ANY, 0) 685 } else { 686 svcKey = NewService4KeyV2(svc.IP, svc.Port, u8proto.ANY, 0) 687 } 688 689 backendsToRemove, backendsCount, err := cache.removeServiceV2(svcKey) 690 if err != nil { 691 return err 692 } 693 694 for slot := 0; slot <= backendsCount; slot++ { 695 svcKey.SetSlave(slot) 696 if err := svcKey.MapDelete(); err != nil { 697 return err 698 } 699 } 700 701 for _, backendKey := range backendsToRemove { 702 if err := deleteBackendLocked(backendKey); err != nil { 703 return fmt.Errorf("Unable to delete backend with ID %d: %s", backendKey, err) 704 } 705 releaseBackendID(backendKey.GetID()) 706 log.WithField(logfields.BackendID, backendKey).Debug("Deleted backend") 707 } 708 709 return nil 710 } 711 712 // DeleteServiceCache deletes the service cache. 713 func DeleteServiceCache(svc loadbalancer.L3n4AddrID) { 714 mutex.Lock() 715 defer mutex.Unlock() 716 717 var svcKey ServiceKey 718 719 if !svc.IsIPv6() { 720 svcKey = NewService4Key(svc.IP, svc.Port, 0) 721 } else { 722 svcKey = NewService6Key(svc.IP, svc.Port, 0) 723 } 724 725 cache.delete(svcKey) 726 } 727 728 func DeleteOrphanBackends(releaseBackendID func(loadbalancer.BackendID)) []error { 729 mutex.Lock() 730 defer mutex.Unlock() 731 732 errors := make([]error, 0) 733 toRemove := cache.removeBackendsWithRefCountZero() 734 735 for _, key := range toRemove { 736 log.WithField(logfields.BackendID, key).Debug("Removing orphan backend") 737 if err := deleteBackendLocked(key); err != nil { 738 errors = append(errors, 739 fmt.Errorf("Unable to remove backend from the BPF map %d: %s", key, err)) 740 } 741 releaseBackendID(key.GetID()) 742 } 743 744 return errors 745 } 746 747 // RemoveDeprecatedMaps removes the maps for legacy services, left over from 748 // previous installations. 749 // 750 // Safe to remove in Cilium 1.7. 751 func RemoveDeprecatedMaps() error { 752 if err := Service6Map.UnpinIfExists(); err != nil { 753 return err 754 } 755 if err := RRSeq6Map.UnpinIfExists(); err != nil { 756 return err 757 } 758 if err := Service4Map.UnpinIfExists(); err != nil { 759 return err 760 } 761 if err := RRSeq4Map.UnpinIfExists(); err != nil { 762 return err 763 } 764 return nil 765 }