github.com/cilium/cilium@v1.16.2/pkg/policy/policy.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package policy 5 6 import ( 7 "io" 8 stdlog "log" 9 "strconv" 10 "strings" 11 12 "github.com/cilium/cilium/api/v1/models" 13 "github.com/cilium/cilium/pkg/labels" 14 ) 15 16 type Tracing int 17 18 const ( 19 TRACE_DISABLED Tracing = iota 20 TRACE_ENABLED 21 TRACE_VERBOSE 22 ) 23 24 // TraceEnabled returns true if the SearchContext requests tracing. 25 func (s *SearchContext) TraceEnabled() bool { 26 return s.Trace != TRACE_DISABLED 27 } 28 29 // PolicyTrace logs the given message into the SearchContext logger only if 30 // TRACE_ENABLED or TRACE_VERBOSE is enabled in the receiver's SearchContext. 31 func (s *SearchContext) PolicyTrace(format string, a ...interface{}) { 32 if s.TraceEnabled() { 33 log.Debugf(format, a...) 34 if s.Logging != nil { 35 format = "%-" + s.CallDepth() + "s" + format 36 a = append([]interface{}{""}, a...) 37 s.Logging.Printf(format, a...) 38 } 39 } 40 } 41 42 // PolicyTraceVerbose logs the given message into the SearchContext logger only 43 // if TRACE_VERBOSE is enabled in the receiver's SearchContext. 44 func (s *SearchContext) PolicyTraceVerbose(format string, a ...interface{}) { 45 switch s.Trace { 46 case TRACE_VERBOSE: 47 log.Debugf(format, a...) 48 if s.Logging != nil { 49 s.Logging.Printf(format, a...) 50 } 51 } 52 } 53 54 // SearchContext defines the context while evaluating policy 55 type SearchContext struct { 56 Trace Tracing 57 Depth int 58 Logging *stdlog.Logger 59 From labels.LabelArray 60 To labels.LabelArray 61 DPorts []*models.Port 62 // rulesSelect specifies whether or not to check whether a rule which is 63 // being analyzed using this SearchContext matches either From or To. 64 // This is used to avoid using EndpointSelector.Matches() if possible, 65 // since it is costly in terms of performance. 66 rulesSelect bool 67 } 68 69 func (s *SearchContext) String() string { 70 from := make([]string, 0, len(s.From)) 71 to := make([]string, 0, len(s.To)) 72 dports := make([]string, 0, len(s.DPorts)) 73 for _, fromLabel := range s.From { 74 from = append(from, fromLabel.String()) 75 } 76 for _, toLabel := range s.To { 77 to = append(to, toLabel.String()) 78 } 79 // We should avoid to use `fmt.Sprintf()` since 80 // it is well-known for not being opimal in terms of 81 // CPU and memory allocations. 82 // See https://github.com/cilium/cilium/issues/19571 83 for _, dport := range s.DPorts { 84 dportStr := dport.Name 85 if dportStr == "" { 86 dportStr = strconv.FormatUint(uint64(dport.Port), 10) 87 } 88 dports = append(dports, dportStr+"/"+dport.Protocol) 89 } 90 fromStr := strings.Join(from, ", ") 91 toStr := strings.Join(to, ", ") 92 if len(dports) != 0 { 93 dportStr := strings.Join(dports, ", ") 94 return "From: [" + fromStr + "] => To: [" + toStr + "] Ports: [" + dportStr + "]" 95 } 96 return "From: [" + fromStr + "] => To: [" + toStr + "]" 97 } 98 99 func (s *SearchContext) CallDepth() string { 100 return strconv.Itoa(s.Depth * 2) 101 } 102 103 // WithLogger returns a shallow copy of the received SearchContext with the 104 // logging set to write to 'log'. 105 func (s *SearchContext) WithLogger(log io.Writer) *SearchContext { 106 result := *s 107 result.Logging = stdlog.New(log, "", 0) 108 if result.Trace == TRACE_DISABLED { 109 result.Trace = TRACE_ENABLED 110 } 111 return &result 112 }