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 }