github.com/cilium/cilium@v1.16.2/pkg/monitor/api/types.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package api
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"net"
    10  	"sort"
    11  	"strconv"
    12  	"strings"
    13  	"time"
    14  
    15  	"github.com/cilium/cilium/pkg/monitor/notifications"
    16  )
    17  
    18  // Must be synchronized with <bpf/lib/common.h>
    19  const (
    20  	// 0-128 are reserved for BPF datapath events
    21  	MessageTypeUnspec = iota
    22  
    23  	// MessageTypeDrop is a BPF datapath notification carrying a DropNotify
    24  	// which corresponds to drop_notify defined in bpf/lib/drop.h
    25  	MessageTypeDrop
    26  
    27  	// MessageTypeDebug is a BPF datapath notification carrying a DebugMsg
    28  	// which corresponds to debug_msg defined in bpf/lib/dbg.h
    29  	MessageTypeDebug
    30  
    31  	// MessageTypeCapture is a BPF datapath notification carrying a DebugCapture
    32  	// which corresponds to debug_capture_msg defined in bpf/lib/dbg.h
    33  	MessageTypeCapture
    34  
    35  	// MessageTypeTrace is a BPF datapath notification carrying a TraceNotify
    36  	// which corresponds to trace_notify defined in bpf/lib/trace.h
    37  	MessageTypeTrace
    38  
    39  	// MessageTypePolicyVerdict is a BPF datapath notification carrying a PolicyVerdictNotify
    40  	// which corresponds to policy_verdict_notify defined in bpf/lib/policy_log.h
    41  	MessageTypePolicyVerdict
    42  
    43  	// MessageTypeRecCapture is a BPF datapath notification carrying a RecorderCapture
    44  	// which corresponds to capture_msg defined in bpf/lib/pcap.h
    45  	MessageTypeRecCapture
    46  
    47  	// MessageTypeTraceSock is a BPF datapath notification carrying a TraceNotifySock
    48  	// which corresponds to trace_sock_notify defined in bpf/lib/trace_sock.h
    49  	MessageTypeTraceSock
    50  
    51  	// 129-255 are reserved for agent level events
    52  
    53  	// MessageTypeAccessLog contains a pkg/proxy/accesslog.LogRecord
    54  	MessageTypeAccessLog = 129
    55  
    56  	// MessageTypeAgent is an agent notification carrying a AgentNotify
    57  	MessageTypeAgent = 130
    58  )
    59  
    60  const (
    61  	MessageTypeNameDrop          = "drop"
    62  	MessageTypeNameDebug         = "debug"
    63  	MessageTypeNameCapture       = "capture"
    64  	MessageTypeNameTrace         = "trace"
    65  	MessageTypeNameL7            = "l7"
    66  	MessageTypeNameAgent         = "agent"
    67  	MessageTypeNamePolicyVerdict = "policy-verdict"
    68  	MessageTypeNameRecCapture    = "recorder"
    69  	MessageTypeNameTraceSock     = "trace-sock"
    70  )
    71  
    72  type MessageTypeFilter []int
    73  
    74  var (
    75  	// MessageTypeNames is a map of all type names
    76  	MessageTypeNames = map[string]int{
    77  		MessageTypeNameDrop:          MessageTypeDrop,
    78  		MessageTypeNameDebug:         MessageTypeDebug,
    79  		MessageTypeNameCapture:       MessageTypeCapture,
    80  		MessageTypeNameTrace:         MessageTypeTrace,
    81  		MessageTypeNameL7:            MessageTypeAccessLog,
    82  		MessageTypeNameAgent:         MessageTypeAgent,
    83  		MessageTypeNamePolicyVerdict: MessageTypePolicyVerdict,
    84  		MessageTypeNameRecCapture:    MessageTypeRecCapture,
    85  		MessageTypeNameTraceSock:     MessageTypeTraceSock,
    86  	}
    87  )
    88  
    89  // AllMessageTypeNames returns a slice of MessageTypeNames
    90  func AllMessageTypeNames() []string {
    91  	names := make([]string, 0, len(MessageTypeNames))
    92  	for name := range MessageTypeNames {
    93  		names = append(names, name)
    94  	}
    95  
    96  	// Sort by the underlying MessageType
    97  	sort.SliceStable(names, func(i, j int) bool {
    98  		return MessageTypeNames[names[i]] < MessageTypeNames[names[j]]
    99  	})
   100  
   101  	return names
   102  }
   103  
   104  // MessageTypeName returns the name for a message type or the numeric value if
   105  // the name can't be found
   106  func MessageTypeName(typ int) string {
   107  	for name, value := range MessageTypeNames {
   108  		if value == typ {
   109  			return name
   110  		}
   111  	}
   112  
   113  	return strconv.Itoa(typ)
   114  }
   115  
   116  func (m *MessageTypeFilter) String() string {
   117  	pieces := make([]string, 0, len(*m))
   118  	for _, typ := range *m {
   119  		pieces = append(pieces, MessageTypeName(typ))
   120  	}
   121  
   122  	return strings.Join(pieces, ",")
   123  }
   124  
   125  func (m *MessageTypeFilter) Set(value string) error {
   126  	i, err := MessageTypeNames[value]
   127  	if !err {
   128  		return fmt.Errorf("Unknown type (%s). Please use one of the following ones %v",
   129  			value, MessageTypeNames)
   130  	}
   131  
   132  	*m = append(*m, i)
   133  	return nil
   134  }
   135  
   136  func (m *MessageTypeFilter) Type() string {
   137  	return "[]string"
   138  }
   139  
   140  func (m *MessageTypeFilter) Contains(typ int) bool {
   141  	for _, v := range *m {
   142  		if v == typ {
   143  			return true
   144  		}
   145  	}
   146  
   147  	return false
   148  }
   149  
   150  // Must be synchronized with <bpf/lib/trace.h>
   151  const (
   152  	TraceToLxc = iota
   153  	TraceToProxy
   154  	TraceToHost
   155  	TraceToStack
   156  	TraceToOverlay
   157  	TraceFromLxc
   158  	TraceFromProxy
   159  	TraceFromHost
   160  	TraceFromStack
   161  	TraceFromOverlay
   162  	TraceFromNetwork
   163  	TraceToNetwork
   164  )
   165  
   166  // TraceObservationPoints is a map of all supported trace observation points
   167  var TraceObservationPoints = map[uint8]string{
   168  	TraceToLxc:       "to-endpoint",
   169  	TraceToProxy:     "to-proxy",
   170  	TraceToHost:      "to-host",
   171  	TraceToStack:     "to-stack",
   172  	TraceToOverlay:   "to-overlay",
   173  	TraceToNetwork:   "to-network",
   174  	TraceFromLxc:     "from-endpoint",
   175  	TraceFromProxy:   "from-proxy",
   176  	TraceFromHost:    "from-host",
   177  	TraceFromStack:   "from-stack",
   178  	TraceFromOverlay: "from-overlay",
   179  	TraceFromNetwork: "from-network",
   180  }
   181  
   182  // TraceObservationPoint returns the name of a trace observation point
   183  func TraceObservationPoint(obsPoint uint8) string {
   184  	if str, ok := TraceObservationPoints[obsPoint]; ok {
   185  		return str
   186  	}
   187  	return fmt.Sprintf("%d", obsPoint)
   188  }
   189  
   190  // AgentNotify is a notification from the agent. The notification is stored
   191  // in its JSON-encoded representation
   192  type AgentNotify struct {
   193  	Type AgentNotification
   194  	Text string
   195  }
   196  
   197  // AgentNotifyMessage is a notification from the agent. It is similar to
   198  // AgentNotify, but the notification is an unencoded struct. See the *Message
   199  // constructors in this package for possible values.
   200  type AgentNotifyMessage struct {
   201  	Type         AgentNotification
   202  	Notification interface{}
   203  }
   204  
   205  // ToJSON encodes a AgentNotifyMessage to its JSON-based AgentNotify representation
   206  func (m *AgentNotifyMessage) ToJSON() (AgentNotify, error) {
   207  	repr, err := json.Marshal(m.Notification)
   208  	if err != nil {
   209  		return AgentNotify{}, err
   210  	}
   211  	return AgentNotify{
   212  		Type: m.Type,
   213  		Text: string(repr),
   214  	}, nil
   215  }
   216  
   217  // AgentNotification specifies the type of agent notification
   218  type AgentNotification uint32
   219  
   220  const (
   221  	AgentNotifyUnspec AgentNotification = iota
   222  	AgentNotifyGeneric
   223  	AgentNotifyStart
   224  	AgentNotifyEndpointRegenerateSuccess
   225  	AgentNotifyEndpointRegenerateFail
   226  	AgentNotifyPolicyUpdated
   227  	AgentNotifyPolicyDeleted
   228  	AgentNotifyEndpointCreated
   229  	AgentNotifyEndpointDeleted
   230  	AgentNotifyIPCacheUpserted
   231  	AgentNotifyIPCacheDeleted
   232  	AgentNotifyServiceUpserted
   233  	AgentNotifyServiceDeleted
   234  )
   235  
   236  // AgentNotifications is a map of all supported agent notification types.
   237  var AgentNotifications = map[AgentNotification]string{
   238  	AgentNotifyUnspec:                    "unspecified",
   239  	AgentNotifyGeneric:                   "Message",
   240  	AgentNotifyStart:                     "Cilium agent started",
   241  	AgentNotifyEndpointRegenerateSuccess: "Endpoint regenerated",
   242  	AgentNotifyEndpointCreated:           "Endpoint created",
   243  	AgentNotifyEndpointDeleted:           "Endpoint deleted",
   244  	AgentNotifyEndpointRegenerateFail:    "Failed endpoint regeneration",
   245  	AgentNotifyIPCacheDeleted:            "IPCache entry deleted",
   246  	AgentNotifyIPCacheUpserted:           "IPCache entry upserted",
   247  	AgentNotifyPolicyUpdated:             "Policy updated",
   248  	AgentNotifyPolicyDeleted:             "Policy deleted",
   249  	AgentNotifyServiceDeleted:            "Service deleted",
   250  	AgentNotifyServiceUpserted:           "Service upserted",
   251  }
   252  
   253  func resolveAgentType(t AgentNotification) string {
   254  	if n, ok := AgentNotifications[t]; ok {
   255  		return n
   256  	}
   257  
   258  	return fmt.Sprintf("%d", t)
   259  }
   260  
   261  // DumpInfo dumps an agent notification
   262  func (n *AgentNotify) DumpInfo() {
   263  	fmt.Printf(">> %s: %s\n", resolveAgentType(n.Type), n.Text)
   264  }
   265  
   266  func (n *AgentNotify) getJSON() string {
   267  	return fmt.Sprintf(`{"type":"agent","subtype":"%s","message":%s}`, resolveAgentType(n.Type), n.Text)
   268  }
   269  
   270  // DumpJSON prints notification in json format
   271  func (n *AgentNotify) DumpJSON() {
   272  	fmt.Println(n.getJSON())
   273  }
   274  
   275  // PolicyUpdateNotification structures update notification
   276  type PolicyUpdateNotification struct {
   277  	Labels    []string `json:"labels,omitempty"`
   278  	Revision  uint64   `json:"revision,omitempty"`
   279  	RuleCount int      `json:"rule_count"`
   280  }
   281  
   282  // PolicyUpdateMessage constructs an agent notification message for policy updates
   283  func PolicyUpdateMessage(numRules int, labels []string, revision uint64) AgentNotifyMessage {
   284  	notification := PolicyUpdateNotification{
   285  		Labels:    labels,
   286  		Revision:  revision,
   287  		RuleCount: numRules,
   288  	}
   289  
   290  	return AgentNotifyMessage{
   291  		Type:         AgentNotifyPolicyUpdated,
   292  		Notification: notification,
   293  	}
   294  }
   295  
   296  // PolicyDeleteMessage constructs an agent notification message for policy deletion
   297  func PolicyDeleteMessage(deleted int, labels []string, revision uint64) AgentNotifyMessage {
   298  	notification := PolicyUpdateNotification{
   299  		Labels:    labels,
   300  		Revision:  revision,
   301  		RuleCount: deleted,
   302  	}
   303  
   304  	return AgentNotifyMessage{
   305  		Type:         AgentNotifyPolicyDeleted,
   306  		Notification: notification,
   307  	}
   308  }
   309  
   310  // EndpointRegenNotification structures regeneration notification
   311  type EndpointRegenNotification struct {
   312  	ID     uint64   `json:"id,omitempty"`
   313  	Labels []string `json:"labels,omitempty"`
   314  	Error  string   `json:"error,omitempty"`
   315  }
   316  
   317  // EndpointRegenMessage constructs an agent notification message for endpoint regeneration
   318  func EndpointRegenMessage(e notifications.RegenNotificationInfo, err error) AgentNotifyMessage {
   319  	notification := EndpointRegenNotification{
   320  		ID:     e.GetID(),
   321  		Labels: e.GetOpLabels(),
   322  	}
   323  
   324  	typ := AgentNotifyEndpointRegenerateSuccess
   325  	if err != nil {
   326  		notification.Error = err.Error()
   327  		typ = AgentNotifyEndpointRegenerateFail
   328  	}
   329  
   330  	return AgentNotifyMessage{
   331  		Type:         typ,
   332  		Notification: notification,
   333  	}
   334  }
   335  
   336  // EndpointNotification structures the endpoint create or delete notification
   337  type EndpointNotification struct {
   338  	EndpointRegenNotification
   339  	PodName   string `json:"pod-name,omitempty"`
   340  	Namespace string `json:"namespace,omitempty"`
   341  }
   342  
   343  // EndpointCreateMessage constructs an agent notification message for endpoint creation
   344  func EndpointCreateMessage(e notifications.RegenNotificationInfo) AgentNotifyMessage {
   345  	notification := EndpointNotification{
   346  		EndpointRegenNotification: EndpointRegenNotification{
   347  			ID:     e.GetID(),
   348  			Labels: e.GetOpLabels(),
   349  		},
   350  		PodName:   e.GetK8sPodName(),
   351  		Namespace: e.GetK8sNamespace(),
   352  	}
   353  
   354  	return AgentNotifyMessage{
   355  		Type:         AgentNotifyEndpointCreated,
   356  		Notification: notification,
   357  	}
   358  }
   359  
   360  // EndpointDeleteMessage constructs an agent notification message for endpoint deletion
   361  func EndpointDeleteMessage(e notifications.RegenNotificationInfo) AgentNotifyMessage {
   362  	notification := EndpointNotification{
   363  		EndpointRegenNotification: EndpointRegenNotification{
   364  			ID:     e.GetID(),
   365  			Labels: e.GetOpLabels(),
   366  		},
   367  		PodName:   e.GetK8sPodName(),
   368  		Namespace: e.GetK8sNamespace(),
   369  	}
   370  
   371  	return AgentNotifyMessage{
   372  		Type:         AgentNotifyEndpointDeleted,
   373  		Notification: notification,
   374  	}
   375  }
   376  
   377  // IPCacheNotification structures ipcache change notifications
   378  type IPCacheNotification struct {
   379  	CIDR        string  `json:"cidr"`
   380  	Identity    uint32  `json:"id"`
   381  	OldIdentity *uint32 `json:"old-id,omitempty"`
   382  
   383  	HostIP    net.IP `json:"host-ip,omitempty"`
   384  	OldHostIP net.IP `json:"old-host-ip,omitempty"`
   385  
   386  	EncryptKey uint8  `json:"encrypt-key"`
   387  	Namespace  string `json:"namespace,omitempty"`
   388  	PodName    string `json:"pod-name,omitempty"`
   389  }
   390  
   391  // IPCacheUpsertedMessage constructs an agent notification message for ipcache upsertions
   392  func IPCacheUpsertedMessage(cidr string, id uint32, oldID *uint32, hostIP net.IP, oldHostIP net.IP,
   393  	encryptKey uint8, namespace, podName string) AgentNotifyMessage {
   394  	notification := IPCacheNotification{
   395  		CIDR:        cidr,
   396  		Identity:    id,
   397  		OldIdentity: oldID,
   398  		HostIP:      hostIP,
   399  		OldHostIP:   oldHostIP,
   400  		EncryptKey:  encryptKey,
   401  		Namespace:   namespace,
   402  		PodName:     podName,
   403  	}
   404  
   405  	return AgentNotifyMessage{
   406  		Type:         AgentNotifyIPCacheUpserted,
   407  		Notification: notification,
   408  	}
   409  }
   410  
   411  // IPCacheDeletedMessage constructs an agent notification message for ipcache deletions
   412  func IPCacheDeletedMessage(cidr string, id uint32, oldID *uint32, hostIP net.IP, oldHostIP net.IP,
   413  	encryptKey uint8, namespace, podName string) AgentNotifyMessage {
   414  	notification := IPCacheNotification{
   415  		CIDR:        cidr,
   416  		Identity:    id,
   417  		OldIdentity: oldID,
   418  		HostIP:      hostIP,
   419  		OldHostIP:   oldHostIP,
   420  		EncryptKey:  encryptKey,
   421  		Namespace:   namespace,
   422  		PodName:     podName,
   423  	}
   424  
   425  	return AgentNotifyMessage{
   426  		Type:         AgentNotifyIPCacheDeleted,
   427  		Notification: notification,
   428  	}
   429  }
   430  
   431  // TimeNotification structures agent start notification
   432  type TimeNotification struct {
   433  	Time string `json:"time"`
   434  }
   435  
   436  // StartMessage constructs an agent notification message when the agent starts
   437  func StartMessage(t time.Time) AgentNotifyMessage {
   438  	notification := TimeNotification{
   439  		Time: t.Format(time.RFC3339Nano),
   440  	}
   441  
   442  	return AgentNotifyMessage{
   443  		Type:         AgentNotifyStart,
   444  		Notification: notification,
   445  	}
   446  }
   447  
   448  // ServiceUpsertNotificationAddr is part of ServiceUpsertNotification
   449  type ServiceUpsertNotificationAddr struct {
   450  	IP   net.IP `json:"ip"`
   451  	Port uint16 `json:"port"`
   452  }
   453  
   454  // ServiceUpsertNotification structures service upsert notifications
   455  type ServiceUpsertNotification struct {
   456  	ID uint32 `json:"id"`
   457  
   458  	Frontend ServiceUpsertNotificationAddr   `json:"frontend-address"`
   459  	Backends []ServiceUpsertNotificationAddr `json:"backend-addresses"`
   460  
   461  	Type string `json:"type,omitempty"`
   462  	// Deprecated: superseded by ExtTrafficPolicy.
   463  	TrafficPolicy    string `json:"traffic-policy,omitempty"`
   464  	ExtTrafficPolicy string `json:"ext-traffic-policy,omitempty"`
   465  	IntTrafficPolicy string `json:"int-traffic-policy,omitempty"`
   466  
   467  	Name      string `json:"name,omitempty"`
   468  	Namespace string `json:"namespace,,omitempty"`
   469  }
   470  
   471  // ServiceUpsertMessage constructs an agent notification message for service upserts
   472  func ServiceUpsertMessage(
   473  	id uint32,
   474  	frontend ServiceUpsertNotificationAddr,
   475  	backends []ServiceUpsertNotificationAddr,
   476  	svcType, svcExtTrafficPolicy, svcIntTrafficPolicy, svcName, svcNamespace string,
   477  ) AgentNotifyMessage {
   478  	notification := ServiceUpsertNotification{
   479  		ID:               id,
   480  		Frontend:         frontend,
   481  		Backends:         backends,
   482  		Type:             svcType,
   483  		TrafficPolicy:    svcExtTrafficPolicy,
   484  		ExtTrafficPolicy: svcExtTrafficPolicy,
   485  		IntTrafficPolicy: svcIntTrafficPolicy,
   486  		Name:             svcName,
   487  		Namespace:        svcNamespace,
   488  	}
   489  
   490  	return AgentNotifyMessage{
   491  		Type:         AgentNotifyServiceUpserted,
   492  		Notification: notification,
   493  	}
   494  }
   495  
   496  // ServiceDeleteNotification structures service delete notifications
   497  type ServiceDeleteNotification struct {
   498  	ID uint32 `json:"id"`
   499  }
   500  
   501  // ServiceDeleteMessage constructs an agent notification message for service deletions
   502  func ServiceDeleteMessage(id uint32) AgentNotifyMessage {
   503  	notification := ServiceDeleteNotification{
   504  		ID: id,
   505  	}
   506  
   507  	return AgentNotifyMessage{
   508  		Type:         AgentNotifyServiceDeleted,
   509  		Notification: notification,
   510  	}
   511  }
   512  
   513  const (
   514  	// PolicyIngress is the value of Flags&PolicyNotifyFlagDirection for ingress traffic
   515  	PolicyIngress = 1
   516  
   517  	// PolicyEgress is the value of Flags&PolicyNotifyFlagDirection for egress traffic
   518  	PolicyEgress = 2
   519  
   520  	// PolicyMatchNone is the value of MatchType indicatating no policy match
   521  	PolicyMatchNone = 0
   522  
   523  	// PolicyMatchL3Only is the value of MatchType indicating a L3-only match
   524  	PolicyMatchL3Only = 1
   525  
   526  	// PolicyMatchL3L4 is the value of MatchType indicating a L3+L4 match
   527  	PolicyMatchL3L4 = 2
   528  
   529  	// PolicyMatchL4Only is the value of MatchType indicating a L4-only match
   530  	PolicyMatchL4Only = 3
   531  
   532  	// PolicyMatchAll is the value of MatchType indicating an allow-all match
   533  	PolicyMatchAll = 4
   534  
   535  	// PolicyMatchL3Proto is the value of MatchType indicating a L3 and protocol match
   536  	PolicyMatchL3Proto = 5
   537  
   538  	// PolicyMatchProtoOnly is the value of MatchType indicating only a protocol match
   539  	PolicyMatchProtoOnly = 6
   540  )
   541  
   542  type PolicyMatchType int
   543  
   544  func (m PolicyMatchType) String() string {
   545  	switch m {
   546  	case PolicyMatchL3Only:
   547  		return "L3-Only"
   548  	case PolicyMatchL3L4:
   549  		return "L3-L4"
   550  	case PolicyMatchL4Only:
   551  		return "L4-Only"
   552  	case PolicyMatchAll:
   553  		return "all"
   554  	case PolicyMatchNone:
   555  		return "none"
   556  	case PolicyMatchL3Proto:
   557  		return "L3-Proto"
   558  	case PolicyMatchProtoOnly:
   559  		return "Proto-Only"
   560  	}
   561  	return "unknown"
   562  }