github.com/cilium/cilium@v1.16.2/pkg/fqdn/re/re.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  // Package re provides a simple function to access compile regex objects for
     5  // the FQDN subsystem.
     6  package re
     7  
     8  import (
     9  	"errors"
    10  	"fmt"
    11  	"regexp"
    12  	"sync/atomic"
    13  
    14  	lru "github.com/golang/groupcache/lru"
    15  
    16  	"github.com/cilium/cilium/pkg/lock"
    17  	"github.com/cilium/cilium/pkg/logging"
    18  	"github.com/cilium/cilium/pkg/logging/logfields"
    19  	"github.com/cilium/cilium/pkg/option"
    20  )
    21  
    22  var (
    23  	log = logging.DefaultLogger.WithField(logfields.LogSubsys, "fqdn/re")
    24  )
    25  
    26  // CompileRegex compiles a pattern p into a regex and returns the regex object.
    27  // The regex object will be cached by an LRU. If p has already been compiled
    28  // and cached, this function will return the cached regex object. If not
    29  // already cached, it will compile p into a regex object and cache it in the
    30  // LRU. This function will return an error if the LRU has not already been
    31  // initialized.
    32  func CompileRegex(p string) (*regexp.Regexp, error) {
    33  	lru := regexCompileLRU.Load()
    34  	if lru == nil {
    35  		return nil, errors.New("FQDN regex compilation LRU not yet initialized")
    36  	}
    37  	lru.Lock()
    38  	r, ok := lru.Get(p)
    39  	lru.Unlock()
    40  	if ok {
    41  		return r.(*regexp.Regexp), nil
    42  	}
    43  	n, err := regexp.Compile(p)
    44  	if err != nil {
    45  		return nil, fmt.Errorf("failed to compile regex: %w", err)
    46  	}
    47  	lru.Lock()
    48  	lru.Add(p, n)
    49  	lru.Unlock()
    50  	return n, nil
    51  }
    52  
    53  // InitRegexCompileLRU creates a new instance of the regex compilation LRU.
    54  func InitRegexCompileLRU(size int) error {
    55  	if size < 0 {
    56  		return fmt.Errorf("failed to initialize FQDN regex compilation LRU due to invalid size %d", size)
    57  	} else if size == 0 {
    58  		log.Warnf(
    59  			"FQDN regex compilation LRU size is unlimited, which can grow unbounded potentially consuming too much memory. Consider passing a maximum size via --%s.",
    60  			option.FQDNRegexCompileLRUSize)
    61  	}
    62  	regexCompileLRU.Store(&RegexCompileLRU{
    63  		Mutex: &lock.Mutex{},
    64  		Cache: lru.New(size),
    65  	})
    66  	return nil
    67  }
    68  
    69  // regexCompileLRU is the singleton instance of the LRU that's shared
    70  // throughout Cilium.
    71  var regexCompileLRU atomic.Pointer[RegexCompileLRU]
    72  
    73  // RegexCompileLRU is an LRU cache for storing compiled regex objects of FQDN
    74  // names or patterns, used in CiliumNetworkPolicy or
    75  // ClusterwideCiliumNetworkPolicy.
    76  type RegexCompileLRU struct {
    77  	// The lru package doesn't provide any concurrency guarantees so we must
    78  	// provide our own locking.
    79  	*lock.Mutex
    80  	*lru.Cache
    81  }