github.com/imran-kn/cilium-fork@v1.6.9/pkg/policy/selectorcache.go (about)

     1  // Copyright 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 policy
    16  
    17  import (
    18  	"sort"
    19  	"strings"
    20  	"sync/atomic"
    21  	"unsafe"
    22  
    23  	"github.com/cilium/cilium/api/v1/models"
    24  	"github.com/cilium/cilium/pkg/identity"
    25  	"github.com/cilium/cilium/pkg/identity/cache"
    26  	k8sConst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io"
    27  	"github.com/cilium/cilium/pkg/labels"
    28  	"github.com/cilium/cilium/pkg/lock"
    29  	"github.com/cilium/cilium/pkg/logging/logfields"
    30  	"github.com/cilium/cilium/pkg/policy/api"
    31  
    32  	"github.com/sirupsen/logrus"
    33  )
    34  
    35  // CachedSelector represents an identity selector owned by the selector cache
    36  type CachedSelector interface {
    37  	// GetSelections returns the cached set of numeric identities
    38  	// selected by the CachedSelector.  The retuned slice must NOT
    39  	// be modified, as it is shared among multiple users.
    40  	GetSelections() []identity.NumericIdentity
    41  
    42  	// Selects return 'true' if the CachedSelector selects the given
    43  	// numeric identity.
    44  	Selects(nid identity.NumericIdentity) bool
    45  
    46  	// IsWildcard returns true if the endpoint selector selects
    47  	// all endpoints.
    48  	IsWildcard() bool
    49  
    50  	// String returns the string representation of this selector.
    51  	// Used as a map key.
    52  	String() string
    53  }
    54  
    55  // CachedSelectorSlice is a slice of CachedSelectors that can be sorted.
    56  type CachedSelectorSlice []CachedSelector
    57  
    58  func (s CachedSelectorSlice) Len() int      { return len(s) }
    59  func (s CachedSelectorSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    60  
    61  func (s CachedSelectorSlice) Less(i, j int) bool {
    62  	return strings.Compare(s[i].String(), s[j].String()) < 0
    63  }
    64  
    65  // SelectsAllEndpoints returns whether the CachedSelectorSlice selects all
    66  // endpoints, which is true if the wildcard endpoint selector is present in the
    67  // slice.
    68  func (s CachedSelectorSlice) SelectsAllEndpoints() bool {
    69  	for _, selector := range s {
    70  		if selector.IsWildcard() {
    71  			return true
    72  		}
    73  	}
    74  	return false
    75  }
    76  
    77  // Insert in a sorted order? Returns true if inserted, false if cs was already in
    78  func (s *CachedSelectorSlice) Insert(cs CachedSelector) bool {
    79  	for _, selector := range *s {
    80  		if selector == cs {
    81  			return false
    82  		}
    83  	}
    84  	*s = append(*s, cs)
    85  	return true
    86  }
    87  
    88  // CachedSelectionUser inserts selectors into the cache and gets update
    89  // callbacks whenever the set of selected numeric identities change for
    90  // the CachedSelectors pushed by it.
    91  type CachedSelectionUser interface {
    92  	// IdentitySelectionUpdated implementations MUST NOT call back
    93  	// to the name manager or the selector cache while executing this function!
    94  	//
    95  	// The caller is responsible for making sure the same identity is not
    96  	// present in both 'added' and 'deleted'.
    97  	IdentitySelectionUpdated(selector CachedSelector, selections, added, deleted []identity.NumericIdentity)
    98  }
    99  
   100  // identitySelector is the internal interface for all selectors in the
   101  // selector cache.
   102  //
   103  // identitySelector represents the mapping of an EndpointSelector
   104  // to a slice of identities. These mappings are updated via two
   105  // different processes:
   106  //
   107  // 1. When policy rules are changed these are added and/or deleted
   108  // depending on what selectors the rules contain. Cached selections of
   109  // new identitySelectors are pre-populated from the set of currently
   110  // known identities.
   111  //
   112  // 2. When reachacble identities appear or disappear, either via local
   113  // allocation (CIDRs), or via the KV-store (remote endpoints). In this
   114  // case all existing identitySelectors are walked through and their
   115  // cached selections are updated as necessary.
   116  //
   117  // In both of the above cases the set of existing identitySelectors is
   118  // write locked.
   119  //
   120  // To minimize the upkeep the identity selectors are shared across
   121  // all IdentityPolicies, so that only one copy exists for each
   122  // identitySelector. Users of the SelectorCache take care of creating
   123  // identitySelectors as needed by identity policies. The set of
   124  // identitySelectors is read locked during an IdentityPolicy update so
   125  // that the the policy is always updated using a coherent set of
   126  // cached selections.
   127  //
   128  // identitySelector is used as a map key, so it must not be implemented by a
   129  // map, slice, or a func, or a runtime panic will be triggered. In all
   130  // cases below identitySelector is being implemented by structs.
   131  type identitySelector interface {
   132  	CachedSelector
   133  	addUser(CachedSelectionUser) (added bool)
   134  
   135  	// Called with NameManager and SelectorCache locks held
   136  	removeUser(CachedSelectionUser, identityNotifier) (last bool)
   137  
   138  	// This may be called while the NameManager lock is held
   139  	notifyUsers(added, deleted []identity.NumericIdentity)
   140  
   141  	numUsers() int
   142  }
   143  
   144  // scIdentity is the information we need about a an identity that rules can select
   145  type scIdentity struct {
   146  	NID       identity.NumericIdentity
   147  	lbls      labels.LabelArray
   148  	namespace string // value of the namespace label, or ""
   149  }
   150  
   151  // scIdentityCache is a cache of Identities keyed by the numeric identity
   152  type scIdentityCache map[identity.NumericIdentity]scIdentity
   153  
   154  func newIdentity(nid identity.NumericIdentity, lbls labels.LabelArray) scIdentity {
   155  	return scIdentity{
   156  		NID:       nid,
   157  		lbls:      lbls,
   158  		namespace: lbls.Get(labels.LabelSourceK8sKeyPrefix + k8sConst.PodNamespaceLabel),
   159  	}
   160  }
   161  
   162  func getIdentityCache(ids cache.IdentityCache) scIdentityCache {
   163  	idCache := make(map[identity.NumericIdentity]scIdentity, len(ids))
   164  	for nid, lbls := range ids {
   165  		idCache[nid] = newIdentity(nid, lbls)
   166  	}
   167  	return idCache
   168  }
   169  
   170  // SelectorCache caches identities, identity selectors, and the
   171  // subsets of identities each selector selects.
   172  type SelectorCache struct {
   173  	mutex lock.RWMutex
   174  
   175  	// idCache contains all known identities as informed by the
   176  	// kv-store and the local identity facility via our
   177  	// UpdateIdentities() function.
   178  	idCache scIdentityCache
   179  
   180  	// map key is the string representation of the selector being cached.
   181  	selectors map[string]identitySelector
   182  
   183  	localIdentityNotifier identityNotifier
   184  }
   185  
   186  // GetModel returns the API model of the SelectorCache.
   187  func (sc *SelectorCache) GetModel() models.SelectorCache {
   188  	sc.mutex.RLock()
   189  	defer sc.mutex.RUnlock()
   190  
   191  	selCacheMdl := make(models.SelectorCache, 0, len(sc.selectors))
   192  
   193  	for selector, idSel := range sc.selectors {
   194  		selections := idSel.GetSelections()
   195  		ids := make([]int64, 0, len(selections))
   196  		for i := range selections {
   197  			ids = append(ids, int64(selections[i]))
   198  		}
   199  		selMdl := &models.SelectorIdentityMapping{
   200  			Selector:   selector,
   201  			Identities: ids,
   202  			Users:      int64(idSel.numUsers()),
   203  		}
   204  		selCacheMdl = append(selCacheMdl, selMdl)
   205  	}
   206  
   207  	return selCacheMdl
   208  }
   209  
   210  // NewSelectorCache creates a new SelectorCache with the given identities.
   211  func NewSelectorCache(ids cache.IdentityCache) *SelectorCache {
   212  	return &SelectorCache{
   213  		idCache:   getIdentityCache(ids),
   214  		selectors: make(map[string]identitySelector),
   215  	}
   216  }
   217  
   218  // SetLocalIdentityNotifier injects the provided identityNotifier into the
   219  // SelectorCache. Currently, this is used to inject the FQDN subsystem into
   220  // the SelectorCache so the SelectorCache can notify the FQDN subsystem when
   221  // it should be aware of a given FQDNSelector for which CIDR identities need
   222  // to be provided upon DNS lookups which corespond to said FQDNSelector.
   223  func (sc *SelectorCache) SetLocalIdentityNotifier(pop identityNotifier) {
   224  	sc.localIdentityNotifier = pop
   225  }
   226  
   227  var (
   228  	// Empty slice of numeric identities used for all selectors that select nothing
   229  	emptySelection []identity.NumericIdentity
   230  	// wildcardSelectorKey is used to compare if a key is for a wildcard
   231  	wildcardSelectorKey = api.WildcardEndpointSelector.LabelSelector.String()
   232  )
   233  
   234  type selectorManager struct {
   235  	key              string
   236  	selections       unsafe.Pointer // *[]identity.NumericIdentity
   237  	users            map[CachedSelectionUser]struct{}
   238  	cachedSelections map[identity.NumericIdentity]struct{}
   239  }
   240  
   241  // Equal is used by checker.Equals, and only considers the identity of the selector,
   242  // ignoring the internal state!
   243  func (s *selectorManager) Equal(b *selectorManager) bool {
   244  	return s.key == b.key
   245  }
   246  
   247  //
   248  // CachedSelector implementation (== Public API)
   249  //
   250  // No locking needed.
   251  //
   252  
   253  // GetSelections returns the set of numeric identities currently
   254  // selected.  The cached selections can be concurrently updated. In
   255  // that case GetSelections() will return either the old or new version
   256  // of the selections. If the old version is returned, the user is
   257  // guaranteed to receive a notification including the update.
   258  func (s *selectorManager) GetSelections() []identity.NumericIdentity {
   259  	return *(*[]identity.NumericIdentity)(atomic.LoadPointer(&s.selections))
   260  }
   261  
   262  // Selects return 'true' if the CachedSelector selects the given
   263  // numeric identity.
   264  func (s *selectorManager) Selects(nid identity.NumericIdentity) bool {
   265  	if s.IsWildcard() {
   266  		return true
   267  	}
   268  	nids := s.GetSelections()
   269  	idx := sort.Search(len(nids), func(i int) bool { return nids[i] >= nid })
   270  	return idx < len(nids) && nids[idx] == nid
   271  }
   272  
   273  // IsWildcard returns true if the endpoint selector selects all
   274  // endpoints.
   275  func (s *selectorManager) IsWildcard() bool {
   276  	return s.key == wildcardSelectorKey
   277  }
   278  
   279  // String returns the map key for this selector
   280  func (s *selectorManager) String() string {
   281  	return s.key
   282  }
   283  
   284  //
   285  // identitySelector implementation (== internal API)
   286  //
   287  
   288  // lock must be held
   289  func (s *selectorManager) addUser(user CachedSelectionUser) (added bool) {
   290  	if _, exists := s.users[user]; exists {
   291  		return false
   292  	}
   293  	s.users[user] = struct{}{}
   294  	return true
   295  }
   296  
   297  // lock must be held
   298  func (s *selectorManager) removeUser(user CachedSelectionUser, dnsProxy identityNotifier) (last bool) {
   299  	delete(s.users, user)
   300  	return len(s.users) == 0
   301  }
   302  
   303  // locks must be held for the dnsProxy and the SelectorCache
   304  func (f *fqdnSelector) removeUser(user CachedSelectionUser, dnsProxy identityNotifier) (last bool) {
   305  	delete(f.users, user)
   306  	if len(f.users) == 0 {
   307  		dnsProxy.UnregisterForIdentityUpdatesLocked(f.selector)
   308  		return true
   309  	}
   310  	return false
   311  }
   312  
   313  // lock must be held
   314  //
   315  // The caller is responsible for making sure the same identity is not
   316  // present in both 'added' and 'deleted'.
   317  func (s *selectorManager) notifyUsers(added, deleted []identity.NumericIdentity) {
   318  	for user := range s.users {
   319  		user.IdentitySelectionUpdated(s, s.GetSelections(), added, deleted)
   320  	}
   321  }
   322  
   323  // lock must be held
   324  func (s *selectorManager) numUsers() int {
   325  	return len(s.users)
   326  }
   327  
   328  // updateSelections updates the immutable slice representation of the
   329  // cached selections after the cached selections have been changed.
   330  //
   331  // lock must be held
   332  func (s *selectorManager) updateSelections() {
   333  	selections := make([]identity.NumericIdentity, len(s.cachedSelections))
   334  	i := 0
   335  	for nid := range s.cachedSelections {
   336  		selections[i] = nid
   337  		i++
   338  	}
   339  	// Sort the numeric identities so that the map iteration order
   340  	// does not matter. This makes testing easier, but may help
   341  	// identifying changes easier also otherwise.
   342  	sort.Slice(selections, func(i, j int) bool {
   343  		return selections[i] < selections[j]
   344  	})
   345  	s.setSelections(&selections)
   346  }
   347  
   348  func (s *selectorManager) setSelections(selections *[]identity.NumericIdentity) {
   349  	if len(*selections) > 0 {
   350  		atomic.StorePointer(&s.selections, unsafe.Pointer(selections))
   351  	} else {
   352  		atomic.StorePointer(&s.selections, unsafe.Pointer(&emptySelection))
   353  	}
   354  }
   355  
   356  type fqdnSelector struct {
   357  	selectorManager
   358  	selector api.FQDNSelector
   359  }
   360  
   361  // identityNotifier provides a means for other subsystems to be made aware of a
   362  // given FQDNSelector (currently pkg/fqdn) so that said subsystems can notify
   363  // the SelectorCache about new IPs (via CIDR Identities) which correspond to
   364  // said FQDNSelector. This is necessary since there is nothing intrinsic to a
   365  // CIDR Identity that says that it corresponds to a given FQDNSelector; this
   366  // relationship is contained only via DNS responses, which are handled
   367  // externally.
   368  type identityNotifier interface {
   369  	// Lock must be held during any calls to RegisterForIdentityUpdatesLocked or
   370  	// UnregisterForIdentityUpdatesLocked.
   371  	Lock()
   372  
   373  	// Unlock must be called after calls to RegisterForIdentityUpdatesLocked or
   374  	// UnregisterForIdentityUpdatesLocked are done.
   375  	Unlock()
   376  
   377  	// RegisterForIdentityUpdatesLocked exposes this FQDNSelector so that identities
   378  	// for IPs contained in a DNS response that matches said selector can be
   379  	// propagated back to the SelectorCache via `UpdateFQDNSelector`. When called,
   380  	// implementers (currently `pkg/fqdn/RuleGen`) should iterate over all DNS
   381  	// names that they are aware of, and see if they match the FQDNSelector.
   382  	// All IPs which correspond to the DNS names which match this Selector will
   383  	// be returned as CIDR identities, as other DNS Names which have already
   384  	// been resolved may match this FQDNSelector.
   385  	// Once this function is called, the SelectorCache will be updated any time
   386  	// new IPs are resolved for DNS names which match this FQDNSelector.
   387  	// This function is only called when the SelectorCache has been made aware
   388  	// of this FQDNSelector for the first time, since we only need to get the
   389  	// set of CIDR identities which match this FQDNSelector already from the
   390  	// identityNotifier on the first pass; any subsequent updates will eventually
   391  	// call `UpdateFQDNSelector`.
   392  	RegisterForIdentityUpdatesLocked(selector api.FQDNSelector) (identities []identity.NumericIdentity)
   393  
   394  	// UnregisterForIdentityUpdatesLocked removes this FQDNSelector from the set of
   395  	// FQDNSelectors which are being tracked by the identityNotifier. The result
   396  	// of this is that no more updates for IPs which correspond to said selector
   397  	// are propagated back to the SelectorCache via `UpdateFQDNSelector`.
   398  	// This occurs when there are no more users of a given FQDNSelector for the
   399  	// SelectorCache.
   400  	UnregisterForIdentityUpdatesLocked(selector api.FQDNSelector)
   401  }
   402  
   403  type labelIdentitySelector struct {
   404  	selectorManager
   405  	selector   api.EndpointSelector
   406  	namespaces []string // allowed namespaces, or ""
   407  }
   408  
   409  // xxxMatches returns true if the CachedSelector matches given labels.
   410  // This is slow, but only used for policy tracing, so it's OK.
   411  func (l *labelIdentitySelector) xxxMatches(labels labels.LabelArray) bool {
   412  	return l.selector.Matches(labels)
   413  }
   414  
   415  func (l *labelIdentitySelector) matchesNamespace(ns string) bool {
   416  	if len(l.namespaces) > 0 {
   417  		if ns != "" {
   418  			for i := range l.namespaces {
   419  				if ns == l.namespaces[i] {
   420  					return true
   421  				}
   422  			}
   423  		}
   424  		// namespace required, but no match
   425  		return false
   426  	}
   427  	// no namespace required, match
   428  	return true
   429  }
   430  
   431  func (l *labelIdentitySelector) matches(identity scIdentity) bool {
   432  	return l.matchesNamespace(identity.namespace) && l.selector.Matches(identity.lbls)
   433  }
   434  
   435  //
   436  // CachedSelector implementation (== Public API)
   437  //
   438  // No locking needed.
   439  //
   440  
   441  // UpdateFQDNSelector updates the mapping of fqdnKey (the FQDNSelector from a
   442  // policy rule as a string) to to the provided list of identities. If the contents
   443  // of the cachedSelections differ from those in the identities slice, all
   444  // users are notified.
   445  func (sc *SelectorCache) UpdateFQDNSelector(fqdnSelec api.FQDNSelector, identities []identity.NumericIdentity) {
   446  	sc.mutex.Lock()
   447  	sc.updateFQDNSelector(fqdnSelec, identities)
   448  	sc.mutex.Unlock()
   449  }
   450  
   451  func (sc *SelectorCache) updateFQDNSelector(fqdnSelec api.FQDNSelector, identities []identity.NumericIdentity) {
   452  	fqdnKey := fqdnSelec.String()
   453  
   454  	var fqdnSel *fqdnSelector
   455  
   456  	selector, exists := sc.selectors[fqdnKey]
   457  	if !exists || selector == nil {
   458  		fqdnSel = &fqdnSelector{
   459  			selectorManager: selectorManager{
   460  				key:              fqdnKey,
   461  				users:            make(map[CachedSelectionUser]struct{}),
   462  				cachedSelections: make(map[identity.NumericIdentity]struct{}),
   463  			},
   464  			selector: fqdnSelec,
   465  		}
   466  		sc.selectors[fqdnKey] = fqdnSel
   467  	} else {
   468  		fqdnSel = selector.(*fqdnSelector)
   469  	}
   470  
   471  	// Convert identity slice to map for comparison with cachedSelections map.
   472  	idsAsMap := make(map[identity.NumericIdentity]struct{}, len(identities))
   473  	for _, v := range identities {
   474  		idsAsMap[v] = struct{}{}
   475  	}
   476  
   477  	// Note that 'added' and 'deleted' are guaranteed to be
   478  	// disjoint, as one of them is left as nil, or an identity
   479  	// being in 'identities' is a precondition for an
   480  	// identity to be appended to 'added', while the inverse is
   481  	// true for 'deleted'.
   482  	var added, deleted []identity.NumericIdentity
   483  
   484  	/* TODO - the FQDN side should expose what was changed (IPs added, and removed)
   485  	*  not all IPs corresponding to an FQDN - this will make this diff much
   486  	*  cheaper, but will require more plumbing on the FQDN side. for now, this
   487  	*  is good enough.
   488  	*
   489  	*  Case 1: identities did correspond to this FQDN, but no longer do. Reset
   490  	*  the map
   491  	 */
   492  	if len(identities) == 0 && len(fqdnSel.cachedSelections) != 0 {
   493  		// Need to update deleted to be all in cached selections
   494  		for k := range fqdnSel.cachedSelections {
   495  			deleted = append(deleted, k)
   496  		}
   497  		fqdnSel.cachedSelections = make(map[identity.NumericIdentity]struct{})
   498  	} else if len(identities) != 0 && len(fqdnSel.cachedSelections) == 0 {
   499  		// Case 2: identities now correspond to this FQDN, but didn't before.
   500  		// We don't have to do any comparison of the maps to see what changed
   501  		// and what didn't.
   502  		added = identities
   503  		fqdnSel.cachedSelections = idsAsMap
   504  	} else {
   505  		// Case 3: Something changed resulting in some identities being added
   506  		// and / or removed. Figure out what these sets are (new identities
   507  		// added, or identities deleted).
   508  		for k := range fqdnSel.cachedSelections {
   509  			// If identity in cached selectors isn't in identities which were
   510  			// passed in, mark it as being deleted, and remove it from
   511  			// cachedSelectors.
   512  			if _, ok := idsAsMap[k]; !ok {
   513  				deleted = append(deleted, k)
   514  				delete(fqdnSel.cachedSelections, k)
   515  			}
   516  		}
   517  
   518  		// Now iterate over the provided identities to update the
   519  		// cachedSelections accordingly, and so we can see which identities
   520  		// were actually added (removing those which were added already).
   521  		for _, allowedIdentity := range identities {
   522  			if _, ok := fqdnSel.cachedSelections[allowedIdentity]; !ok {
   523  				// This identity was actually added and not already in the map.
   524  				added = append(added, allowedIdentity)
   525  				fqdnSel.cachedSelections[allowedIdentity] = struct{}{}
   526  			}
   527  		}
   528  	}
   529  
   530  	// Note: we don't need to go through the identity cache to see what
   531  	// identities match" this selector. This has to be updated via whatever is
   532  	// getting the CIDR identities which correspond to this FQDNSelector. This
   533  	// is the primary difference here between FQDNSelector and IdentitySelector.
   534  	fqdnSel.updateSelections()
   535  	fqdnSel.notifyUsers(added, deleted) // disjoint sets, see the comment above
   536  }
   537  
   538  // AddFQDNSelector adds the given api.FQDNSelector in to the selector cache. If
   539  // an identical EndpointSelector has already been cached, the corresponding
   540  // CachedSelector is returned, otherwise one is created and added to the cache.
   541  func (sc *SelectorCache) AddFQDNSelector(user CachedSelectionUser, fqdnSelec api.FQDNSelector) (cachedSelector CachedSelector, added bool) {
   542  	key := fqdnSelec.String()
   543  
   544  	// Lock NameManager before the SelectorCache
   545  	sc.localIdentityNotifier.Lock()
   546  	defer sc.localIdentityNotifier.Unlock()
   547  
   548  	// If the selector already exists, use it.
   549  	sc.mutex.Lock()
   550  	fqdnSel, exists := sc.selectors[key]
   551  	if exists {
   552  		added := fqdnSel.addUser(user)
   553  		sc.mutex.Unlock()
   554  		return fqdnSel, added
   555  	}
   556  	sc.mutex.Unlock()
   557  
   558  	// Create the new selector. Pulling the identities it selects could
   559  	// cause allocation of new CIDR identities, so we do this while not
   560  	// holding the 'sc.mutex'.
   561  	newFQDNSel := &fqdnSelector{
   562  		selectorManager: selectorManager{
   563  			key:              key,
   564  			users:            make(map[CachedSelectionUser]struct{}),
   565  			cachedSelections: make(map[identity.NumericIdentity]struct{}),
   566  		},
   567  		selector: fqdnSelec,
   568  	}
   569  
   570  	// Make the FQDN subsystem aware of this selector and fetch identities
   571  	// that the FQDN subsystem is aware of.
   572  	//
   573  	// If the same 'fqdnSelec' is registered twice here from different
   574  	// goroutines, we do *NOT* need to unregister the second one because
   575  	// 'fqdnSelec' is just a struct passed by value. The call below doesn't
   576  	// retain any references/pointers.
   577  	//
   578  	// If this is called twice, one of the results will arbitrarily contain
   579  	// a real slice of ids, while the other will receive nil. We must fold
   580  	// them together below.
   581  	ids := sc.localIdentityNotifier.RegisterForIdentityUpdatesLocked(newFQDNSel.selector)
   582  
   583  	// Do not go through the identity cache to see what identities "match" this
   584  	// selector. This has to be updated via whatever is getting the CIDR identities
   585  	// which correspond go this FQDNSelector.
   586  	// Alternatively , we could go through the CIDR identities in the cache
   587  	// provided they have some 'field' which shows which FQDNs they correspond
   588  	// to? This would require we keep some set in the Identity for the CIDR.
   589  	// Is this feasible?
   590  
   591  	// Note: No notifications are sent for the existing
   592  	// identities. Caller must use GetSelections() to get the
   593  	// current selections after adding a selector. This way the
   594  	// behavior is the same between the two cases here (selector
   595  	// is already cached, or is a new one).
   596  
   597  	sc.mutex.Lock()
   598  	defer sc.mutex.Unlock()
   599  
   600  	// Check whether the selectorCache was updated while 'newFQDNSel' was
   601  	// being registered without the 'sc.mutex'. If so, use it. Otherwise
   602  	// we can use the one we just created/configured above.
   603  	if sel, exists := sc.selectors[key]; exists {
   604  		newFQDNSel = sel.(*fqdnSelector)
   605  	} else {
   606  		sc.selectors[key] = newFQDNSel
   607  	}
   608  
   609  	// Add the ids from the slice above to the FQDN selector in the cache.
   610  	// This could plausibly happen twice, once with an empty 'ids' slice
   611  	// and once with the real 'ids' slice. Either way, they are added to
   612  	// the selector that is stored in 'sc.selectors[]'
   613  	for _, id := range ids {
   614  		newFQDNSel.cachedSelections[id] = struct{}{}
   615  	}
   616  	newFQDNSel.updateSelections()
   617  
   618  	return newFQDNSel, newFQDNSel.addUser(user)
   619  }
   620  
   621  // FindCachedIdentitySelector finds the given api.EndpointSelector in the
   622  // selector cache, returning nil if one can not be found.
   623  func (sc *SelectorCache) FindCachedIdentitySelector(selector api.EndpointSelector) CachedSelector {
   624  	key := selector.CachedString()
   625  	sc.mutex.Lock()
   626  	idSel := sc.selectors[key]
   627  	sc.mutex.Unlock()
   628  	return idSel
   629  }
   630  
   631  // AddIdentitySelector adds the given api.EndpointSelector in to the
   632  // selector cache. If an identical EndpointSelector has already been
   633  // cached, the corresponding CachedSelector is returned, otherwise one
   634  // is created and added to the cache.
   635  func (sc *SelectorCache) AddIdentitySelector(user CachedSelectionUser, selector api.EndpointSelector) (cachedSelector CachedSelector, added bool) {
   636  	// The key returned here may be different for equivalent
   637  	// labelselectors, if the selector's requirements are stored
   638  	// in different orders. When this happens we'll be tracking
   639  	// essentially two copies of the same selector.
   640  	key := selector.CachedString()
   641  	sc.mutex.Lock()
   642  	defer sc.mutex.Unlock()
   643  	idSel, exists := sc.selectors[key]
   644  	if exists {
   645  		return idSel, idSel.addUser(user)
   646  	}
   647  
   648  	// Selectors are never modified once a rule is placed in the policy repository,
   649  	// so no need to deep copy.
   650  
   651  	newIDSel := &labelIdentitySelector{
   652  		selectorManager: selectorManager{
   653  			key:              key,
   654  			users:            make(map[CachedSelectionUser]struct{}),
   655  			cachedSelections: make(map[identity.NumericIdentity]struct{}),
   656  		},
   657  		selector: selector,
   658  	}
   659  	// check is selector has a namespace match or requirement
   660  	if namespaces, ok := selector.GetMatch(labels.LabelSourceK8sKeyPrefix + k8sConst.PodNamespaceLabel); ok {
   661  		newIDSel.namespaces = namespaces
   662  	}
   663  
   664  	// Add the initial user
   665  	newIDSel.users[user] = struct{}{}
   666  
   667  	// Find all matching identities from the identity cache.
   668  	for numericID, identity := range sc.idCache {
   669  		if newIDSel.matches(identity) {
   670  			newIDSel.cachedSelections[numericID] = struct{}{}
   671  		}
   672  	}
   673  	// Create the immutable slice representation of the selected
   674  	// numeric identities
   675  	newIDSel.updateSelections()
   676  
   677  	// Note: No notifications are sent for the existing
   678  	// identities. Caller must use GetSelections() to get the
   679  	// current selections after adding a selector. This way the
   680  	// behavior is the same between the two cases here (selector
   681  	// is already cached, or is a new one).
   682  
   683  	sc.selectors[key] = newIDSel
   684  	return newIDSel, true
   685  }
   686  
   687  // lock must be held
   688  func (sc *SelectorCache) removeSelectorLocked(selector CachedSelector, user CachedSelectionUser) {
   689  	key := selector.String()
   690  	sel, exists := sc.selectors[key]
   691  	if exists {
   692  		if sel.removeUser(user, sc.localIdentityNotifier) {
   693  			delete(sc.selectors, key)
   694  		}
   695  	}
   696  }
   697  
   698  // RemoveSelector removes CachedSelector for the user.
   699  func (sc *SelectorCache) RemoveSelector(selector CachedSelector, user CachedSelectionUser) {
   700  	sc.localIdentityNotifier.Lock()
   701  	sc.mutex.Lock()
   702  	sc.removeSelectorLocked(selector, user)
   703  	sc.mutex.Unlock()
   704  	sc.localIdentityNotifier.Unlock()
   705  }
   706  
   707  // RemoveSelectors removes CachedSelectorSlice for the user.
   708  func (sc *SelectorCache) RemoveSelectors(selectors CachedSelectorSlice, user CachedSelectionUser) {
   709  	sc.localIdentityNotifier.Lock()
   710  	sc.mutex.Lock()
   711  	for _, selector := range selectors {
   712  		sc.removeSelectorLocked(selector, user)
   713  	}
   714  	sc.mutex.Unlock()
   715  	sc.localIdentityNotifier.Unlock()
   716  }
   717  
   718  // ChangeUser changes the CachedSelectionUser that gets updates on the
   719  // updates on the cached selector.
   720  func (sc *SelectorCache) ChangeUser(selector CachedSelector, from, to CachedSelectionUser) {
   721  	key := selector.String()
   722  	sc.mutex.Lock()
   723  	idSel, exists := sc.selectors[key]
   724  	if exists {
   725  		// Add before remove so that the count does not dip to zero in between,
   726  		// as this causes FQDN unregistration (if applicable).
   727  		idSel.addUser(to)
   728  		// ignoring the return value as we have just added a user above
   729  		idSel.removeUser(from, sc.localIdentityNotifier)
   730  	}
   731  	sc.mutex.Unlock()
   732  }
   733  
   734  // UpdateIdentities propagates identity updates to selectors
   735  //
   736  // The caller is responsible for making sure the same identity is not
   737  // present in both 'added' and 'deleted'.
   738  func (sc *SelectorCache) UpdateIdentities(added, deleted cache.IdentityCache) {
   739  	sc.mutex.Lock()
   740  	defer sc.mutex.Unlock()
   741  
   742  	// Update idCache so that newly added selectors get
   743  	// prepopulated with all matching numeric identities.
   744  	for numericID := range deleted {
   745  		if old, exists := sc.idCache[numericID]; exists {
   746  			log.WithFields(logrus.Fields{logfields.Identity: numericID, logfields.Labels: old.lbls}).Debug("UpdateIdentities: Deleting identity")
   747  			delete(sc.idCache, numericID)
   748  		} else {
   749  			log.WithFields(logrus.Fields{logfields.Identity: numericID}).Warning("UpdateIdentities: Skipping Delete of a non-existing identity")
   750  			delete(deleted, numericID)
   751  		}
   752  	}
   753  	for numericID, lbls := range added {
   754  		if old, exists := sc.idCache[numericID]; exists {
   755  			// Skip if no change. Not skipping if label
   756  			// order is different, but identity labels are
   757  			// sorted for the kv-store, so there should
   758  			// not be too many false negatives.
   759  			if lbls.Same(old.lbls) {
   760  				log.WithFields(logrus.Fields{logfields.Identity: numericID}).Debug("UpdateIdentities: Skipping add of an existing identical identity")
   761  				delete(added, numericID)
   762  				continue
   763  			}
   764  			log.WithFields(logrus.Fields{logfields.Identity: numericID, logfields.Labels: old.lbls, logfields.Labels + "(new)": lbls}).Warning("UpdateIdentities: Updating an existing identity")
   765  		} else {
   766  			log.WithFields(logrus.Fields{logfields.Identity: numericID, logfields.Labels: lbls}).Debug("UpdateIdentities: Adding a new identity")
   767  		}
   768  		sc.idCache[numericID] = newIdentity(numericID, lbls)
   769  	}
   770  
   771  	if len(deleted)+len(added) > 0 {
   772  		// Iterate through all locally used identity selectors and
   773  		// update the cached numeric identities as required.
   774  		for _, sel := range sc.selectors {
   775  			var adds, dels []identity.NumericIdentity
   776  			switch idSel := sel.(type) {
   777  			case *labelIdentitySelector:
   778  				for numericID := range deleted {
   779  					if _, exists := idSel.cachedSelections[numericID]; exists {
   780  						dels = append(dels, numericID)
   781  						delete(idSel.cachedSelections, numericID)
   782  					}
   783  				}
   784  				for numericID := range added {
   785  					if _, exists := idSel.cachedSelections[numericID]; !exists {
   786  						if idSel.matches(sc.idCache[numericID]) {
   787  							adds = append(adds, numericID)
   788  							idSel.cachedSelections[numericID] = struct{}{}
   789  						}
   790  					}
   791  				}
   792  				if len(dels)+len(adds) > 0 {
   793  					idSel.updateSelections()
   794  					idSel.notifyUsers(adds, dels)
   795  				}
   796  			case *fqdnSelector:
   797  				// This is a no-op right now. We don't encode in the identities
   798  				// which FQDNs they correspond to.
   799  			}
   800  		}
   801  	}
   802  }
   803  
   804  // RemoveIdentitiesFQDNSelectors removes all identities from being mapped to the
   805  // set of FQDNSelectors.
   806  func (sc *SelectorCache) RemoveIdentitiesFQDNSelectors(fqdnSels []api.FQDNSelector) {
   807  	sc.mutex.Lock()
   808  	noIdentities := []identity.NumericIdentity{}
   809  
   810  	for i := range fqdnSels {
   811  		sc.updateFQDNSelector(fqdnSels[i], noIdentities)
   812  	}
   813  	sc.mutex.Unlock()
   814  }