github.com/form3tech-oss/cilium@v1.6.3/daemon/loadbalancer.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 main
    16  
    17  import (
    18  	"fmt"
    19  	"time"
    20  
    21  	"github.com/cilium/cilium/api/v1/models"
    22  	. "github.com/cilium/cilium/api/v1/server/restapi/service"
    23  	"github.com/cilium/cilium/pkg/api"
    24  	"github.com/cilium/cilium/pkg/loadbalancer"
    25  	"github.com/cilium/cilium/pkg/logging/logfields"
    26  	"github.com/cilium/cilium/pkg/maps/lbmap"
    27  	"github.com/cilium/cilium/pkg/option"
    28  	"github.com/cilium/cilium/pkg/service"
    29  
    30  	"github.com/go-openapi/runtime/middleware"
    31  	"github.com/sirupsen/logrus"
    32  )
    33  
    34  // addSVC2BPFMap adds the given bpf service to the bpf maps. If addRevNAT is set, adds the
    35  // RevNAT value (feCilium.L3n4Addr) to the lb's RevNAT map for the given feCilium.ID.
    36  func (d *Daemon) addSVC2BPFMap(feCilium loadbalancer.L3n4AddrID, feBPF lbmap.ServiceKey,
    37  	besBPF []lbmap.ServiceValue,
    38  	svcKeyV2 lbmap.ServiceKeyV2, svcValuesV2 []lbmap.ServiceValueV2, backendsV2 []lbmap.Backend,
    39  	addRevNAT bool) error {
    40  	log.WithField(logfields.ServiceName, feCilium.String()).Debug("adding service to BPF maps")
    41  
    42  	revNATID := int(feCilium.ID)
    43  
    44  	if err := lbmap.UpdateService(feBPF, besBPF, addRevNAT, revNATID,
    45  		service.AcquireBackendID, service.DeleteBackendID); err != nil {
    46  		if addRevNAT {
    47  			delete(d.loadBalancer.RevNATMap, loadbalancer.ServiceID(feCilium.ID))
    48  		}
    49  		return err
    50  	}
    51  
    52  	if addRevNAT {
    53  		log.WithField(logfields.ServiceName, feCilium.String()).Debug("adding service to RevNATMap")
    54  		d.loadBalancer.RevNATMap[loadbalancer.ServiceID(feCilium.ID)] = *feCilium.L3n4Addr.DeepCopy()
    55  	}
    56  	return nil
    57  }
    58  
    59  // SVCAdd is the public method to add services. We assume the ID provided is not in
    60  // sync with the KVStore. If that's the, case the service won't be used and an error is
    61  // returned to the caller.
    62  //
    63  // Returns true if service was created.
    64  func (d *Daemon) SVCAdd(feL3n4Addr loadbalancer.L3n4AddrID, be []loadbalancer.LBBackEnd, addRevNAT bool) (bool, error) {
    65  	log.WithField(logfields.ServiceID, feL3n4Addr.String()).Debug("adding service")
    66  	if feL3n4Addr.ID == 0 {
    67  		return false, fmt.Errorf("invalid service ID 0")
    68  	}
    69  	// Check if the service is already registered with this ID.
    70  	feAddr, err := service.GetID(uint32(feL3n4Addr.ID))
    71  	if err != nil {
    72  		return false, fmt.Errorf("unable to get service %d: %s", feL3n4Addr.ID, err)
    73  	}
    74  	if feAddr == nil {
    75  		feAddr, err = service.AcquireID(feL3n4Addr.L3n4Addr, uint32(feL3n4Addr.ID))
    76  		if err != nil {
    77  			return false, fmt.Errorf("unable to store service %s in kvstore: %s", feL3n4Addr.String(), err)
    78  		}
    79  		// This won't be atomic so we need to check if the baseID, feL3n4Addr.ID was given to the service
    80  		if feAddr.ID != feL3n4Addr.ID {
    81  			return false, fmt.Errorf("the service provided %s is already registered with ID %d, please use that ID instead of %d", feL3n4Addr.L3n4Addr.String(), feAddr.ID, feL3n4Addr.ID)
    82  		}
    83  	}
    84  
    85  	feAddr256Sum := feAddr.L3n4Addr.SHA256Sum()
    86  	feL3n4Addr256Sum := feL3n4Addr.L3n4Addr.SHA256Sum()
    87  
    88  	if feAddr256Sum != feL3n4Addr256Sum {
    89  		return false, fmt.Errorf("service ID %d is already registered to L3n4Addr %s, please choose a different ID", feL3n4Addr.ID, feAddr.String())
    90  	}
    91  
    92  	return d.svcAdd(feL3n4Addr, be, addRevNAT, false)
    93  }
    94  
    95  // svcAdd adds a service from the given feL3n4Addr (frontend) and LBBackEnd (backends).
    96  // If addRevNAT is set, the RevNAT entry is also created for this particular service.
    97  // If any of the backend addresses set in bes have a different L3 address type than the
    98  // one set in fe, it returns an error without modifying the bpf LB map. If any backend
    99  // entry fails while updating the LB map, the frontend won't be inserted in the LB map
   100  // therefore there won't be any traffic going to the given backends.
   101  // All of the backends added will be DeepCopied to the internal load balancer map.
   102  func (d *Daemon) svcAdd(
   103  	feL3n4Addr loadbalancer.L3n4AddrID, bes []loadbalancer.LBBackEnd,
   104  	addRevNAT, nodePort bool) (bool, error) {
   105  
   106  	scopedLog := log.WithFields(logrus.Fields{
   107  		logfields.ServiceID: feL3n4Addr.String(),
   108  		logfields.Object:    logfields.Repr(bes),
   109  	})
   110  	scopedLog.Debug("adding service")
   111  
   112  	// Move the slice to the loadbalancer map which has a mutex. If we don't
   113  	// copy the slice we might risk changing memory that should be locked.
   114  	beCpy := []loadbalancer.LBBackEnd{}
   115  	for _, v := range bes {
   116  		beCpy = append(beCpy, v)
   117  	}
   118  
   119  	svc := loadbalancer.LBSVC{
   120  		FE:       feL3n4Addr,
   121  		BES:      beCpy,
   122  		Sha256:   feL3n4Addr.L3n4Addr.SHA256Sum(),
   123  		NodePort: nodePort,
   124  	}
   125  
   126  	fe, besValues, err := lbmap.LBSVC2ServiceKeynValue(svc)
   127  	if err != nil {
   128  		return false, err
   129  	}
   130  
   131  	svcKeyV2, svcValuesV2, backendsV2, err := lbmap.LBSVC2ServiceKeynValuenBackendV2(&svc)
   132  	if err != nil {
   133  		return false, err
   134  	}
   135  
   136  	d.loadBalancer.BPFMapMU.Lock()
   137  	defer d.loadBalancer.BPFMapMU.Unlock()
   138  
   139  	err = d.addSVC2BPFMap(feL3n4Addr, fe, besValues, svcKeyV2, svcValuesV2, backendsV2, addRevNAT)
   140  	if err != nil {
   141  		return false, err
   142  	}
   143  
   144  	// Fill the just acquired backend IDs to ensure the consistent ordering
   145  	// of the backends when listing services. This step will go away once
   146  	// we start acquiring backend IDs in this module.
   147  	for i, be := range svc.BES {
   148  		id, err := service.LookupBackendID(be.L3n4Addr)
   149  		if err != nil {
   150  			scopedLog.WithField(logfields.BackendName, be.L3n4Addr).WithError(err).
   151  				Warning("Unable to lookup backend ID")
   152  			continue
   153  		}
   154  		svc.BES[i].ID = id
   155  	}
   156  
   157  	return d.loadBalancer.AddService(svc), nil
   158  }
   159  
   160  type putServiceID struct {
   161  	d *Daemon
   162  }
   163  
   164  func NewPutServiceIDHandler(d *Daemon) PutServiceIDHandler {
   165  	return &putServiceID{d: d}
   166  }
   167  
   168  func (h *putServiceID) Handle(params PutServiceIDParams) middleware.Responder {
   169  	log.WithField(logfields.Params, logfields.Repr(params)).Debug("PUT /service/{id} request")
   170  
   171  	f, err := loadbalancer.NewL3n4AddrFromModel(params.Config.FrontendAddress)
   172  	if err != nil {
   173  		return api.Error(PutServiceIDInvalidFrontendCode, err)
   174  	}
   175  
   176  	frontend := loadbalancer.L3n4AddrID{
   177  		L3n4Addr: *f,
   178  		ID:       loadbalancer.ID(params.Config.ID),
   179  	}
   180  
   181  	backends := []loadbalancer.LBBackEnd{}
   182  	for _, v := range params.Config.BackendAddresses {
   183  		b, err := loadbalancer.NewLBBackEndFromBackendModel(v)
   184  		if err != nil {
   185  			return api.Error(PutServiceIDInvalidBackendCode, err)
   186  		}
   187  		backends = append(backends, *b)
   188  	}
   189  
   190  	revnat := false
   191  	if params.Config.Flags != nil {
   192  		revnat = params.Config.Flags.DirectServerReturn
   193  	}
   194  
   195  	// FIXME
   196  	// Add flag to indicate whether service should be registered in
   197  	// global key value store
   198  
   199  	if created, err := h.d.SVCAdd(frontend, backends, revnat); err != nil {
   200  		return api.Error(PutServiceIDFailureCode, err)
   201  	} else if created {
   202  		return NewPutServiceIDCreated()
   203  	} else {
   204  		return NewPutServiceIDOK()
   205  	}
   206  }
   207  
   208  type deleteServiceID struct {
   209  	d *Daemon
   210  }
   211  
   212  func NewDeleteServiceIDHandler(d *Daemon) DeleteServiceIDHandler {
   213  	return &deleteServiceID{d: d}
   214  }
   215  
   216  func (h *deleteServiceID) Handle(params DeleteServiceIDParams) middleware.Responder {
   217  	log.WithField(logfields.Params, logfields.Repr(params)).Debug("DELETE /service/{id} request")
   218  
   219  	d := h.d
   220  	d.loadBalancer.BPFMapMU.Lock()
   221  	defer d.loadBalancer.BPFMapMU.Unlock()
   222  
   223  	svc, ok := d.loadBalancer.SVCMapID[loadbalancer.ServiceID(params.ID)]
   224  
   225  	if !ok {
   226  		return NewDeleteServiceIDNotFound()
   227  	}
   228  
   229  	// FIXME: How to handle error?
   230  	err := service.DeleteID(uint32(params.ID))
   231  
   232  	if err != nil {
   233  		log.WithError(err).Warn("error, DeleteL3n4AddrIDByUUID failed")
   234  	}
   235  
   236  	if err := h.d.svcDelete(svc); err != nil {
   237  		log.WithError(err).WithField(logfields.Object, logfields.Repr(svc)).Warn("DELETE /service/{id}: error deleting service")
   238  		return api.Error(DeleteServiceIDFailureCode, err)
   239  	}
   240  
   241  	return NewDeleteServiceIDOK()
   242  }
   243  
   244  func (d *Daemon) svcDeleteByFrontendLocked(frontend *loadbalancer.L3n4AddrID) error {
   245  	svc, ok := d.loadBalancer.SVCMap[frontend.SHA256Sum()]
   246  	if !ok {
   247  		return fmt.Errorf("Service frontend not found %+v", frontend)
   248  	}
   249  	return d.svcDelete(&svc)
   250  }
   251  
   252  // Deletes a service by the frontend address
   253  func (d *Daemon) svcDeleteByFrontend(frontend *loadbalancer.L3n4AddrID) error {
   254  	d.loadBalancer.BPFMapMU.Lock()
   255  	defer d.loadBalancer.BPFMapMU.Unlock()
   256  
   257  	return d.svcDeleteByFrontendLocked(frontend)
   258  }
   259  
   260  func (d *Daemon) svcDelete(svc *loadbalancer.LBSVC) error {
   261  	if err := d.svcDeleteBPF(svc.FE); err != nil {
   262  		return err
   263  	}
   264  
   265  	d.loadBalancer.DeleteService(svc)
   266  
   267  	return nil
   268  }
   269  
   270  func (d *Daemon) svcDeleteBPF(svc loadbalancer.L3n4AddrID) error {
   271  	if err := lbmap.DeleteServiceV2(svc, service.DeleteBackendID); err != nil {
   272  		return fmt.Errorf("Deleting service from BPF maps failed: %s", err)
   273  	}
   274  
   275  	lbmap.DeleteServiceCache(svc)
   276  
   277  	return nil
   278  }
   279  
   280  type getServiceID struct {
   281  	daemon *Daemon
   282  }
   283  
   284  func NewGetServiceIDHandler(d *Daemon) GetServiceIDHandler {
   285  	return &getServiceID{daemon: d}
   286  }
   287  
   288  func (h *getServiceID) Handle(params GetServiceIDParams) middleware.Responder {
   289  	log.WithField(logfields.Params, logfields.Repr(params)).Debug("GET /service/{id} request")
   290  
   291  	d := h.daemon
   292  
   293  	d.loadBalancer.BPFMapMU.RLock()
   294  	defer d.loadBalancer.BPFMapMU.RUnlock()
   295  
   296  	if svc, ok := d.loadBalancer.SVCMapID[loadbalancer.ServiceID(params.ID)]; ok {
   297  		return NewGetServiceIDOK().WithPayload(svc.GetModel())
   298  	}
   299  	return NewGetServiceIDNotFound()
   300  }
   301  
   302  // SVCGetBySHA256Sum returns a DeepCopied frontend with its backends.
   303  func (d *Daemon) svcGetBySHA256Sum(feL3n4SHA256Sum string) *loadbalancer.LBSVC {
   304  	d.loadBalancer.BPFMapMU.RLock()
   305  	defer d.loadBalancer.BPFMapMU.RUnlock()
   306  
   307  	v, ok := d.loadBalancer.SVCMap[feL3n4SHA256Sum]
   308  	if !ok {
   309  		return nil
   310  	}
   311  	// We will move the slice from the loadbalancer map which has a mutex. If
   312  	// we don't copy the slice we might risk changing memory that should be
   313  	// locked.
   314  	beCpy := []loadbalancer.LBBackEnd{}
   315  	for _, v := range v.BES {
   316  		beCpy = append(beCpy, v)
   317  	}
   318  	return &loadbalancer.LBSVC{
   319  		FE:  *v.FE.DeepCopy(),
   320  		BES: beCpy,
   321  	}
   322  }
   323  
   324  type getService struct {
   325  	d *Daemon
   326  }
   327  
   328  func NewGetServiceHandler(d *Daemon) GetServiceHandler {
   329  	return &getService{d: d}
   330  }
   331  
   332  func (h *getService) Handle(params GetServiceParams) middleware.Responder {
   333  	log.WithField(logfields.Params, logfields.Repr(params)).Debug("GET /service request")
   334  	list := h.d.GetServiceList()
   335  	return NewGetServiceOK().WithPayload(list)
   336  }
   337  
   338  // RevNATAdd deep copies the given revNAT address to the cilium lbmap with the given id.
   339  func (d *Daemon) RevNATAdd(id loadbalancer.ServiceID, revNAT loadbalancer.L3n4Addr) error {
   340  	revNATK, revNATV := lbmap.L3n4Addr2RevNatKeynValue(id, revNAT)
   341  
   342  	d.loadBalancer.BPFMapMU.Lock()
   343  	defer d.loadBalancer.BPFMapMU.Unlock()
   344  
   345  	err := lbmap.UpdateRevNat(revNATK, revNATV)
   346  	if err != nil {
   347  		return err
   348  	}
   349  
   350  	d.loadBalancer.RevNATMap[id] = *revNAT.DeepCopy()
   351  	return nil
   352  }
   353  
   354  // RevNATDelete deletes the revNatKey from the local bpf map.
   355  func (d *Daemon) RevNATDelete(id loadbalancer.ServiceID) error {
   356  	d.loadBalancer.BPFMapMU.Lock()
   357  	defer d.loadBalancer.BPFMapMU.Unlock()
   358  
   359  	revNAT, ok := d.loadBalancer.RevNATMap[id]
   360  	if !ok {
   361  		return nil
   362  	}
   363  
   364  	err := lbmap.DeleteRevNATBPF(id, revNAT.IsIPv6())
   365  
   366  	// TODO should we delete even if err is != nil?
   367  	if err == nil {
   368  		delete(d.loadBalancer.RevNATMap, id)
   369  	}
   370  	return err
   371  }
   372  
   373  // RevNATDeleteAll deletes all RevNAT4, if IPv4 is enabled on daemon, and all RevNAT6
   374  // stored on the daemon and on the bpf maps.
   375  //
   376  // Must be called with d.loadBalancer.BPFMapMU locked.
   377  func (d *Daemon) RevNATDeleteAll() error {
   378  	if option.Config.EnableIPv4 {
   379  		if err := lbmap.RevNat4Map.DeleteAll(); err != nil {
   380  			return err
   381  		}
   382  	}
   383  
   384  	if option.Config.EnableIPv6 {
   385  		if err := lbmap.RevNat6Map.DeleteAll(); err != nil {
   386  			return err
   387  		}
   388  	}
   389  
   390  	// TODO should we delete even if err is != nil?
   391  	d.loadBalancer.RevNATMap = map[loadbalancer.ServiceID]loadbalancer.L3n4Addr{}
   392  	return nil
   393  }
   394  
   395  // RevNATGet returns a DeepCopy of the revNAT found with the given ID or nil if not found.
   396  func (d *Daemon) RevNATGet(id loadbalancer.ServiceID) (*loadbalancer.L3n4Addr, error) {
   397  	d.loadBalancer.BPFMapMU.RLock()
   398  	defer d.loadBalancer.BPFMapMU.RUnlock()
   399  
   400  	revNAT, ok := d.loadBalancer.RevNATMap[id]
   401  	if !ok {
   402  		return nil, nil
   403  	}
   404  	return revNAT.DeepCopy(), nil
   405  }
   406  
   407  // RevNATDump dumps a DeepCopy of the cilium's loadbalancer.
   408  func (d *Daemon) RevNATDump() ([]loadbalancer.L3n4AddrID, error) {
   409  	dump := []loadbalancer.L3n4AddrID{}
   410  
   411  	d.loadBalancer.BPFMapMU.RLock()
   412  	defer d.loadBalancer.BPFMapMU.RUnlock()
   413  
   414  	for k, v := range d.loadBalancer.RevNATMap {
   415  		dump = append(dump, loadbalancer.L3n4AddrID{
   416  			ID:       loadbalancer.ID(k),
   417  			L3n4Addr: *v.DeepCopy(),
   418  		})
   419  	}
   420  
   421  	return dump, nil
   422  }
   423  
   424  func openServiceMaps() error {
   425  	if err := lbmap.RemoveDeprecatedMaps(); err != nil {
   426  		return err
   427  	}
   428  
   429  	if option.Config.EnableIPv6 {
   430  		if _, err := lbmap.Service6MapV2.OpenOrCreate(); err != nil {
   431  			return err
   432  		}
   433  		if _, err := lbmap.Backend6Map.OpenOrCreate(); err != nil {
   434  			return err
   435  		}
   436  		if _, err := lbmap.RevNat6Map.OpenOrCreate(); err != nil {
   437  			return err
   438  		}
   439  		if _, err := lbmap.RRSeq6MapV2.OpenOrCreate(); err != nil {
   440  			return err
   441  		}
   442  	}
   443  
   444  	if option.Config.EnableIPv4 {
   445  		if _, err := lbmap.Service4MapV2.OpenOrCreate(); err != nil {
   446  			return err
   447  		}
   448  		if _, err := lbmap.Backend4Map.OpenOrCreate(); err != nil {
   449  			return err
   450  		}
   451  		if _, err := lbmap.RevNat4Map.OpenOrCreate(); err != nil {
   452  			return err
   453  		}
   454  		if _, err := lbmap.RRSeq4MapV2.OpenOrCreate(); err != nil {
   455  			return err
   456  		}
   457  	}
   458  
   459  	return nil
   460  }
   461  
   462  // SyncLBMap syncs the bpf lbmap with the daemon's lb map. All bpf entries will overwrite
   463  // the daemon's LB map. If the bpf lbmap entry has a different service ID than the
   464  // KVStore's ID, that entry will be updated on the bpf map accordingly with the new ID
   465  // retrieved from the KVStore.
   466  func (d *Daemon) SyncLBMap() error {
   467  	// Don't bother syncing if we are in dry mode.
   468  	if option.Config.DryMode {
   469  		return nil
   470  	}
   471  
   472  	log.Info("Restoring services from BPF maps...")
   473  
   474  	d.loadBalancer.BPFMapMU.Lock()
   475  	defer d.loadBalancer.BPFMapMU.Unlock()
   476  
   477  	newSVCMapID := loadbalancer.SVCMapID{}
   478  	newRevNATMap := loadbalancer.RevNATMap{}
   479  	failedSyncSVC := []loadbalancer.LBSVC{}
   480  	failedSyncRevNAT := map[loadbalancer.ServiceID]loadbalancer.L3n4Addr{}
   481  
   482  	addSVC2BPFMap := func(oldID loadbalancer.ServiceID, svc loadbalancer.LBSVC) error {
   483  		scopedLog := log.WithFields(logrus.Fields{
   484  			logfields.ServiceID: oldID,
   485  			logfields.SHA:       svc.FE.SHA256Sum(),
   486  		})
   487  		scopedLog.Debug("adding service ID with SHA")
   488  
   489  		// check if the ID for revNat is present in the bpf map, update the
   490  		// reverse nat key, delete the old one.
   491  		revNAT, ok := newRevNATMap[oldID]
   492  		if ok {
   493  			scopedLog.Debug("Service ID is present in BPF map, updating revnat key")
   494  			revNATK, revNATV := lbmap.L3n4Addr2RevNatKeynValue(
   495  				loadbalancer.ServiceID(svc.FE.ID), revNAT)
   496  			err := lbmap.UpdateRevNat(revNATK, revNATV)
   497  			if err != nil {
   498  				return fmt.Errorf("Unable to add revNAT: %s: %s."+
   499  					" This entry will be removed from the bpf's LB map.", revNAT.String(), err)
   500  			}
   501  
   502  			// Remove the old entry from the bpf map.
   503  			revNATK, _ = lbmap.L3n4Addr2RevNatKeynValue(oldID, revNAT)
   504  			if err := lbmap.DeleteRevNat(revNATK); err != nil {
   505  				scopedLog.WithError(err).Warn("Unable to remove old rev NAT entry")
   506  			}
   507  
   508  			scopedLog.Debug("deleting old ID from newRevNATMap")
   509  			delete(newRevNATMap, oldID)
   510  
   511  			log.WithFields(logrus.Fields{
   512  				logfields.ServiceName: svc.FE.String(),
   513  				"revNAT":              revNAT,
   514  			}).Debug("adding service --> revNAT to newRevNATMap")
   515  			newRevNATMap[loadbalancer.ServiceID(svc.FE.ID)] = revNAT
   516  		}
   517  
   518  		fe, besValues, err := lbmap.LBSVC2ServiceKeynValue(svc)
   519  		if err != nil {
   520  			return fmt.Errorf("Unable to create a BPF key and values for service FE: %s and backends: %+v. Error: %s."+
   521  				" This entry will be removed from the bpf's LB map.", svc.FE.String(), svc.BES, err)
   522  		}
   523  
   524  		svcKeyV2, svcValuesV2, backendsV2, err := lbmap.LBSVC2ServiceKeynValuenBackendV2(&svc)
   525  		if err != nil {
   526  			return fmt.Errorf("Unable to create a BPF key and values for service v2 FE: %s and backends: %+v. Error: %s."+
   527  				" This entry will be removed from the bpf's LB map.", svc.FE.String(), svc.BES, err)
   528  		}
   529  
   530  		err = d.addSVC2BPFMap(svc.FE, fe, besValues, svcKeyV2, svcValuesV2, backendsV2, false)
   531  		if err != nil {
   532  			return fmt.Errorf("Unable to add service FE: %s: %s."+
   533  				" This entry will be removed from the bpf's LB map.", svc.FE.String(), err)
   534  		}
   535  		return nil
   536  	}
   537  
   538  	newSVCMap, newSVCList, lbmapDumpErrors := lbmap.DumpServiceMapsToUserspaceV2()
   539  	for _, err := range lbmapDumpErrors {
   540  		log.WithError(err).Warn("Unable to list services in services BPF map")
   541  	}
   542  	newRevNATMap, revNATMapDumpErrors := lbmap.DumpRevNATMapsToUserspace()
   543  	for _, err := range revNATMapDumpErrors {
   544  		log.WithError(err).Warn("Unable to list services in RevNat BPF map")
   545  	}
   546  
   547  	// Need to do this outside of parseSVCEntries to avoid deadlock, because we
   548  	// are modifying the BPF maps, and calling Dump on a Map RLocks the maps.
   549  	for _, svc := range newSVCList {
   550  		scopedLog := log.WithField(logfields.Object, logfields.Repr(svc))
   551  		kvL3n4AddrID, err := service.RestoreID(svc.FE.L3n4Addr, uint32(svc.FE.ID))
   552  		if err != nil {
   553  			scopedLog.WithError(err).Error("Unable to restore service ID")
   554  			failedSyncSVC = append(failedSyncSVC, *svc)
   555  			delete(newSVCMap, svc.Sha256)
   556  			// Don't update the maps of services since the service failed to
   557  			// sync.
   558  			continue
   559  		}
   560  
   561  		// Mismatch detected between BPF Maps and KVstore, so we need to update
   562  		// the ID in the BPF Maps to reflect the ID of the KVstore.
   563  		if svc.FE.ID != kvL3n4AddrID.ID {
   564  			scopedLog = scopedLog.WithField(logfields.ServiceID+".new", kvL3n4AddrID.ID)
   565  			scopedLog.WithError(err).Warning("Service ID in BPF map is out of sync with KVStore. Acquired new ID")
   566  
   567  			oldID := loadbalancer.ServiceID(svc.FE.ID)
   568  			svc.FE.ID = kvL3n4AddrID.ID
   569  			// If we cannot add the service to the BPF maps, update the list of
   570  			// services that failed to sync.
   571  			if err := addSVC2BPFMap(oldID, *svc); err != nil {
   572  				scopedLog.WithError(err).Error("Unable to synchronize service to BPF map")
   573  
   574  				failedSyncSVC = append(failedSyncSVC, *svc)
   575  				delete(newSVCMap, svc.Sha256)
   576  
   577  				revNAT, ok := newRevNATMap[loadbalancer.ServiceID(svc.FE.ID)]
   578  				if ok {
   579  					// Revert the old revNAT
   580  					newRevNATMap[oldID] = revNAT
   581  					failedSyncRevNAT[loadbalancer.ServiceID(svc.FE.ID)] = revNAT
   582  					delete(newRevNATMap, loadbalancer.ServiceID(svc.FE.ID))
   583  				}
   584  				// Don't update the maps of services since the service failed to
   585  				// sync.
   586  				continue
   587  			}
   588  		}
   589  		newSVCMapID[loadbalancer.ServiceID(svc.FE.ID)] = svc
   590  	}
   591  
   592  	// Clean services and rev nats from BPF maps that failed to be restored.
   593  	for _, svc := range failedSyncSVC {
   594  		if err := d.svcDeleteBPF(svc.FE); err != nil {
   595  			log.WithError(err).WithField(logfields.Object, logfields.Repr(svc)).
   596  				Warn("Unable to remove unrestorable service from BPF map")
   597  		}
   598  	}
   599  
   600  	for id, revNAT := range failedSyncRevNAT {
   601  		var revNATK lbmap.RevNatKey
   602  		if !revNAT.IsIPv6() {
   603  			revNATK = lbmap.NewRevNat4Key(uint16(id))
   604  		} else {
   605  			revNATK = lbmap.NewRevNat6Key(uint16(id))
   606  		}
   607  
   608  		if err := lbmap.DeleteRevNat(revNATK); err != nil {
   609  			log.WithError(err).WithFields(logrus.Fields{
   610  				logfields.ServiceID: id,
   611  				"revNAT":            revNAT,
   612  			}).Warn("Unable to clean rev NAT from BPF map")
   613  		}
   614  	}
   615  
   616  	log.WithFields(logrus.Fields{
   617  		"restoredServices": len(newSVCMap),
   618  		"restoredRevNat":   len(newRevNATMap),
   619  		"failedServices":   len(failedSyncSVC),
   620  		"failedRevNat":     len(failedSyncRevNAT),
   621  	}).Info("Restored services from BPF maps")
   622  
   623  	d.loadBalancer.SVCMap = newSVCMap
   624  	d.loadBalancer.SVCMapID = newSVCMapID
   625  	d.loadBalancer.RevNATMap = newRevNATMap
   626  
   627  	return nil
   628  }
   629  
   630  // syncLBMapsWithK8s ensures that the only contents of all BPF maps related to
   631  // services (loadbalancer, RevNAT - for IPv4 and IPv6) are those that are
   632  // sent to Cilium via K8s. This function is intended to be ran as part of a
   633  // controller by the daemon when bootstrapping, although it could be called
   634  // elsewhere it needed. Returns an error if any issues occur dumping BPF maps
   635  // or deleting entries from BPF maps.
   636  func (d *Daemon) syncLBMapsWithK8s() error {
   637  	k8sDeletedServices := map[string]loadbalancer.L3n4AddrID{}
   638  	alreadyChecked := map[string]struct{}{}
   639  
   640  	// Maps service IDs to whether they are IPv6 (true) or IPv4 (false).
   641  	k8sDeletedRevNATS := make(map[loadbalancer.ServiceID]bool)
   642  
   643  	// Set of L3n4Addrs in string form for storage as a key in map.
   644  	k8sServicesFrontendAddresses := d.k8sSvcCache.UniqueServiceFrontends()
   645  
   646  	// NOTE: loadBalancer.BPFMapMU should be taken after k8sSvcCache.Mutex
   647  	// has been released, otherwise a deadlock can happen: See GH-8764.
   648  	d.loadBalancer.BPFMapMU.Lock()
   649  	defer d.loadBalancer.BPFMapMU.Unlock()
   650  
   651  	log.Debugf("dumping BPF service maps to userspace")
   652  	// At this point the creation of the v2 svc from the corresponding legacy
   653  	// one has already happened, so it's safe to rely on the v2 when dumping
   654  	_, newSVCList, lbmapDumpErrors := lbmap.DumpServiceMapsToUserspaceV2()
   655  
   656  	if len(lbmapDumpErrors) > 0 {
   657  		errorStrings := ""
   658  		for _, err := range lbmapDumpErrors {
   659  			errorStrings = fmt.Sprintf("%s, %s", err, errorStrings)
   660  		}
   661  		return fmt.Errorf("error(s): %s", errorStrings)
   662  	}
   663  
   664  	newRevNATMap, revNATMapDumpErrors := lbmap.DumpRevNATMapsToUserspace()
   665  	if len(revNATMapDumpErrors) > 0 {
   666  		errorStrings := ""
   667  		for _, err := range revNATMapDumpErrors {
   668  			errorStrings = fmt.Sprintf("%s, %s", err, errorStrings)
   669  		}
   670  		return fmt.Errorf("error(s): %s", errorStrings)
   671  	}
   672  
   673  	// Check whether services in service and revNAT BPF maps exist in the
   674  	// in-memory K8s service maps. If not, mark them for deletion.
   675  	for _, svc := range newSVCList {
   676  		id := svc.FE.L3n4Addr.StringWithProtocol()
   677  		if _, ok := alreadyChecked[id]; ok {
   678  			continue
   679  		}
   680  
   681  		alreadyChecked[id] = struct{}{}
   682  
   683  		scopedLog := log.WithFields(logrus.Fields{
   684  			logfields.ServiceID: svc.FE.ID,
   685  			logfields.L3n4Addr:  logfields.Repr(svc.FE.L3n4Addr)})
   686  
   687  		if !k8sServicesFrontendAddresses.LooseMatch(svc.FE.L3n4Addr) {
   688  			scopedLog.Warning("Deleting no longer present service in datapath")
   689  			k8sDeletedServices[id] = svc.FE
   690  			continue
   691  		}
   692  
   693  		scopedLog.Debug("Found matching k8s service for service in BPF map")
   694  	}
   695  
   696  	for serviceID, serviceInfo := range newRevNATMap {
   697  		if _, ok := d.loadBalancer.RevNATMap[serviceID]; !ok {
   698  			log.WithFields(logrus.Fields{
   699  				logfields.ServiceID: serviceID,
   700  				logfields.L3n4Addr:  logfields.Repr(serviceInfo)}).Debug("revNAT ID read from BPF maps is not managed by K8s; will delete it from BPF maps")
   701  			// Map service ID to whether service is IPv4 or IPv6.
   702  			if serviceInfo.IP.To4() == nil {
   703  				k8sDeletedRevNATS[serviceID] = true
   704  			} else {
   705  				k8sDeletedRevNATS[serviceID] = false
   706  			}
   707  		}
   708  	}
   709  
   710  	bpfDeleteErrors := []error{}
   711  
   712  	// Delete map entries from BPF which don't exist in list of Kubernetes
   713  	// services.
   714  	for _, svc := range k8sDeletedServices {
   715  		svcLogger := log.WithField(logfields.Object, logfields.Repr(svc))
   716  		svcLogger.Debug("removing service because it was not synced from Kubernetes")
   717  		if err := d.svcDeleteBPF(svc); err != nil {
   718  			bpfDeleteErrors = append(bpfDeleteErrors, err)
   719  		}
   720  	}
   721  
   722  	for serviceID, isIPv6 := range k8sDeletedRevNATS {
   723  		log.WithFields(logrus.Fields{logfields.ServiceID: serviceID, "isIPv6": isIPv6}).Debug("removing revNAT because it was not synced from Kubernetes")
   724  		if err := lbmap.DeleteRevNATBPF(serviceID, isIPv6); err != nil {
   725  			bpfDeleteErrors = append(bpfDeleteErrors, err)
   726  		}
   727  	}
   728  
   729  	if len(bpfDeleteErrors) > 0 {
   730  		bpfErrorsString := ""
   731  		for _, err := range bpfDeleteErrors {
   732  			bpfErrorsString = fmt.Sprintf("%s, %s", err, bpfErrorsString)
   733  		}
   734  		return fmt.Errorf("Errors deleting BPF map entries: %s", bpfErrorsString)
   735  	}
   736  
   737  	log.Debugf("successfully synced BPF loadbalancer and revNAT maps with in-memory Kubernetes service maps")
   738  
   739  	return nil
   740  }
   741  
   742  func restoreBackendIDs() (map[lbmap.BackendAddrID]lbmap.BackendKey, error) {
   743  	lbBackends, err := lbmap.DumpBackendMapsToUserspace()
   744  	if err != nil {
   745  		return nil, fmt.Errorf("Unable to dump LB backend maps: %s", err)
   746  	}
   747  
   748  	restoredBackendIDs := map[lbmap.BackendAddrID]lbmap.BackendKey{}
   749  
   750  	for addrID, lbBackend := range lbBackends {
   751  		err := service.RestoreBackendID(lbBackend.L3n4Addr, lbBackend.ID)
   752  		if err != nil {
   753  			return nil, err
   754  		}
   755  		be, err := lbmap.LBBackEnd2Backend(*lbBackend)
   756  		if err != nil {
   757  			return nil, err
   758  		}
   759  		restoredBackendIDs[addrID] = be.GetKey()
   760  	}
   761  
   762  	log.WithField(logfields.BackendIDs, restoredBackendIDs).
   763  		Debug("Restored backend IDs")
   764  
   765  	return restoredBackendIDs, nil
   766  }
   767  
   768  func restoreServices() {
   769  	before := time.Now()
   770  
   771  	// Restore Backend IDs first, otherwise they can get taken by subsequent
   772  	// calls to UpdateService
   773  	restoredBackendIDs, err := restoreBackendIDs()
   774  	if err != nil {
   775  		log.WithError(err).Warning("Error occurred while restoring backend IDs")
   776  	}
   777  	lbmap.AddBackendIDsToCache(restoredBackendIDs)
   778  
   779  	failed, restored, skipped, removed := 0, 0, 0, 0
   780  	svcIDs := make(map[loadbalancer.ID]struct{})
   781  
   782  	svcMapV2, _, errors := lbmap.DumpServiceMapsToUserspaceV2()
   783  	for _, err := range errors {
   784  		log.WithError(err).Warning("Error occurred while dumping service v2 table from datapath")
   785  	}
   786  
   787  	for _, svc := range svcMapV2 {
   788  		scopedLog := log.WithFields(logrus.Fields{
   789  			logfields.ServiceID: svc.FE.ID,
   790  			logfields.ServiceIP: svc.FE.L3n4Addr.String(),
   791  		})
   792  		// Services where the service ID was missing in the BPF map
   793  		// cannot be restored
   794  		if uint32(svc.FE.ID) == uint32(0) {
   795  			skipped++
   796  			continue
   797  		}
   798  
   799  		svcIDs[svc.FE.ID] = struct{}{}
   800  
   801  		// The service ID can only be restored when global service IDs
   802  		// are disabled. Global service IDs require kvstore access but
   803  		// service load-balancing needs to be enabled before the
   804  		// kvstore is guaranteed to be connected
   805  		if option.Config.LBInterface == "" {
   806  			_, err := service.RestoreID(svc.FE.L3n4Addr, uint32(svc.FE.ID))
   807  			if err != nil {
   808  				failed++
   809  				scopedLog.WithError(err).Warning("Unable to restore service ID from datapath")
   810  			} else {
   811  				restored++
   812  				scopedLog.Debug("Restored service ID from datapath")
   813  			}
   814  		}
   815  
   816  		// Restore the service cache to guarantee backend ordering
   817  		// across restarts
   818  		if err := lbmap.RestoreService(svc); err != nil {
   819  			scopedLog.WithError(err).Warning("Unable to restore service in cache")
   820  			failed++
   821  			continue
   822  		}
   823  	}
   824  
   825  	// Remove backend entries which are not used by any service.
   826  	if errs := lbmap.DeleteOrphanBackends(service.DeleteBackendID); errs != nil && len(errs) > 0 {
   827  		for _, err := range errs {
   828  			log.WithError(err).Warning("Unable to remove orphan backend")
   829  		}
   830  	}
   831  
   832  	log.WithFields(logrus.Fields{
   833  		logfields.Duration: time.Now().Sub(before),
   834  		"restored":         restored,
   835  		"failed":           failed,
   836  		"skipped":          skipped,
   837  		"removed":          removed,
   838  	}).Info("Restore service IDs from BPF maps")
   839  }
   840  
   841  // GetServiceList returns list of services
   842  func (d *Daemon) GetServiceList() []*models.Service {
   843  	list := []*models.Service{}
   844  
   845  	d.loadBalancer.BPFMapMU.RLock()
   846  	defer d.loadBalancer.BPFMapMU.RUnlock()
   847  
   848  	for _, v := range d.loadBalancer.SVCMap {
   849  		list = append(list, v.GetModel())
   850  	}
   851  	return list
   852  }