github.com/cilium/cilium@v1.16.2/pkg/hubble/parser/parser.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Hubble
     3  
     4  // Copyright Authors of Cilium
     5  
     6  package parser
     7  
     8  import (
     9  	"github.com/sirupsen/logrus"
    10  	"google.golang.org/protobuf/types/known/timestamppb"
    11  	"google.golang.org/protobuf/types/known/wrapperspb"
    12  
    13  	pb "github.com/cilium/cilium/api/v1/flow"
    14  	v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
    15  	observerTypes "github.com/cilium/cilium/pkg/hubble/observer/types"
    16  	"github.com/cilium/cilium/pkg/hubble/parser/agent"
    17  	"github.com/cilium/cilium/pkg/hubble/parser/debug"
    18  	"github.com/cilium/cilium/pkg/hubble/parser/errors"
    19  	"github.com/cilium/cilium/pkg/hubble/parser/getters"
    20  	"github.com/cilium/cilium/pkg/hubble/parser/options"
    21  	"github.com/cilium/cilium/pkg/hubble/parser/seven"
    22  	"github.com/cilium/cilium/pkg/hubble/parser/sock"
    23  	"github.com/cilium/cilium/pkg/hubble/parser/threefour"
    24  	monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
    25  	"github.com/cilium/cilium/pkg/proxy/accesslog"
    26  )
    27  
    28  // Decoder is an interface for the parser.
    29  // It decodes a monitor event into a hubble event.
    30  type Decoder interface {
    31  	// Decode transforms a monitor event into a hubble event.
    32  	Decode(monitorEvent *observerTypes.MonitorEvent) (*v1.Event, error)
    33  }
    34  
    35  // Parser for all flows
    36  type Parser struct {
    37  	l34  *threefour.Parser
    38  	l7   *seven.Parser
    39  	dbg  *debug.Parser
    40  	sock *sock.Parser
    41  }
    42  
    43  // New creates a new parser
    44  func New(
    45  	log logrus.FieldLogger,
    46  	endpointGetter getters.EndpointGetter,
    47  	identityGetter getters.IdentityGetter,
    48  	dnsGetter getters.DNSGetter,
    49  	ipGetter getters.IPGetter,
    50  	serviceGetter getters.ServiceGetter,
    51  	linkGetter getters.LinkGetter,
    52  	cgroupGetter getters.PodMetadataGetter,
    53  	opts ...options.Option,
    54  ) (*Parser, error) {
    55  
    56  	l34, err := threefour.New(log, endpointGetter, identityGetter, dnsGetter, ipGetter, serviceGetter, linkGetter)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	l7, err := seven.New(log, dnsGetter, ipGetter, serviceGetter, endpointGetter, opts...)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	dbg, err := debug.New(log, endpointGetter)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	sock, err := sock.New(log, endpointGetter, identityGetter, dnsGetter, ipGetter, serviceGetter, cgroupGetter)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	return &Parser{
    77  		l34:  l34,
    78  		l7:   l7,
    79  		dbg:  dbg,
    80  		sock: sock,
    81  	}, nil
    82  }
    83  
    84  func lostEventSourceToProto(source int) pb.LostEventSource {
    85  	switch source {
    86  	case observerTypes.LostEventSourcePerfRingBuffer:
    87  		return pb.LostEventSource_PERF_EVENT_RING_BUFFER
    88  	case observerTypes.LostEventSourceEventsQueue:
    89  		return pb.LostEventSource_OBSERVER_EVENTS_QUEUE
    90  	case observerTypes.LostEventSourceHubbleRingBuffer:
    91  		return pb.LostEventSource_HUBBLE_RING_BUFFER
    92  	default:
    93  		return pb.LostEventSource_UNKNOWN_LOST_EVENT_SOURCE
    94  	}
    95  }
    96  
    97  // Decode decodes a cilium monitor 'payload' and returns a v1.Event with
    98  // the Event field populated.
    99  func (p *Parser) Decode(monitorEvent *observerTypes.MonitorEvent) (*v1.Event, error) {
   100  	if monitorEvent == nil {
   101  		return nil, errors.ErrEmptyData
   102  	}
   103  
   104  	// TODO: Pool decoded flows instead of allocating new objects each time.
   105  	ts := timestamppb.New(monitorEvent.Timestamp)
   106  	ev := &v1.Event{
   107  		Timestamp: ts,
   108  	}
   109  
   110  	switch payload := monitorEvent.Payload.(type) {
   111  	case *observerTypes.PerfEvent:
   112  		if len(payload.Data) == 0 {
   113  			return nil, errors.ErrEmptyData
   114  		}
   115  
   116  		flow := &pb.Flow{}
   117  		switch payload.Data[0] {
   118  		case monitorAPI.MessageTypeDebug:
   119  			// Debug and TraceSock are both perf ring buffer events without any
   120  			// associated captured network packet header, so we treat them
   121  			// separately
   122  			dbg, err := p.dbg.Decode(payload.Data, payload.CPU)
   123  			if err != nil {
   124  				return nil, err
   125  			}
   126  			ev.Event = dbg
   127  			return ev, nil
   128  		case monitorAPI.MessageTypeTraceSock:
   129  			if err := p.sock.Decode(payload.Data, flow); err != nil {
   130  				return nil, err
   131  			}
   132  		default:
   133  			if err := p.l34.Decode(payload.Data, flow); err != nil {
   134  				return nil, err
   135  			}
   136  		}
   137  		flow.Uuid = monitorEvent.UUID.String()
   138  		// FIXME: Time and NodeName are now part of GetFlowsResponse. We
   139  		// populate these fields for compatibility with old clients.
   140  		flow.Time = ts
   141  		flow.NodeName = monitorEvent.NodeName
   142  		ev.Event = flow
   143  		return ev, nil
   144  	case *observerTypes.AgentEvent:
   145  		switch payload.Type {
   146  		case monitorAPI.MessageTypeAccessLog:
   147  			flow := &pb.Flow{}
   148  			logrecord, ok := payload.Message.(accesslog.LogRecord)
   149  			if !ok {
   150  				return nil, errors.ErrInvalidAgentMessageType
   151  			}
   152  			if err := p.l7.Decode(&logrecord, flow); err != nil {
   153  				return nil, err
   154  			}
   155  			flow.Uuid = monitorEvent.UUID.String()
   156  			// FIXME: Time and NodeName are now part of GetFlowsResponse. We
   157  			// populate these fields for compatibility with old clients.
   158  			flow.Time = ts
   159  			flow.NodeName = monitorEvent.NodeName
   160  			ev.Event = flow
   161  			return ev, nil
   162  		case monitorAPI.MessageTypeAgent:
   163  			agentNotifyMessage, ok := payload.Message.(monitorAPI.AgentNotifyMessage)
   164  			if !ok {
   165  				return nil, errors.ErrInvalidAgentMessageType
   166  			}
   167  			ev.Event = agent.NotifyMessageToProto(agentNotifyMessage)
   168  			return ev, nil
   169  		default:
   170  			return nil, errors.ErrUnknownEventType
   171  		}
   172  	case *observerTypes.LostEvent:
   173  		ev.Event = &pb.LostEvent{
   174  			Source:        lostEventSourceToProto(payload.Source),
   175  			NumEventsLost: payload.NumLostEvents,
   176  			Cpu: &wrapperspb.Int32Value{
   177  				Value: int32(payload.CPU),
   178  			},
   179  		}
   180  		return ev, nil
   181  	case nil:
   182  		return ev, errors.ErrEmptyData
   183  	default:
   184  		return nil, errors.ErrUnknownEventType
   185  	}
   186  }