github.com/zhyoulun/cilium@v1.6.12/pkg/monitor/format/format.go (about) 1 // Copyright 2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package format 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "encoding/gob" 21 "fmt" 22 23 "github.com/cilium/cilium/pkg/byteorder" 24 "github.com/cilium/cilium/pkg/logging" 25 "github.com/cilium/cilium/pkg/logging/logfields" 26 "github.com/cilium/cilium/pkg/monitor" 27 monitorAPI "github.com/cilium/cilium/pkg/monitor/api" 28 "github.com/cilium/cilium/pkg/monitor/payload" 29 ) 30 31 var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "monitor-format") 32 33 // Verbosity levels for formatting output. 34 type Verbosity uint8 35 36 const ( 37 msgSeparator = "------------------------------------------------------------------------------" 38 39 // INFO is the level of verbosity in which summaries of Drop and Capture 40 // messages are printed out when the monitor is invoked 41 INFO Verbosity = iota + 1 42 // DEBUG is the level of verbosity in which more information about packets 43 // is printed than in INFO mode. Debug, Drop, and Capture messages are printed. 44 DEBUG 45 // VERBOSE is the level of verbosity in which the most information possible 46 // about packets is printed out. Currently is not utilized. 47 VERBOSE 48 // JSON is the level of verbosity in which event information is printed out in json format 49 JSON 50 ) 51 52 // MonitorFormatter filters and formats monitor messages from a buffer. 53 type MonitorFormatter struct { 54 EventTypes monitorAPI.MessageTypeFilter 55 FromSource Uint16Flags 56 ToDst Uint16Flags 57 Related Uint16Flags 58 Verbose bool 59 Hex bool 60 JSONOutput bool 61 Verbosity Verbosity 62 } 63 64 // NewMonitorFormatter returns a new formatter with default configuration. 65 func NewMonitorFormatter(verbosity Verbosity) *MonitorFormatter { 66 return &MonitorFormatter{ 67 Hex: false, 68 EventTypes: monitorAPI.MessageTypeFilter{}, 69 FromSource: Uint16Flags{}, 70 ToDst: Uint16Flags{}, 71 Related: Uint16Flags{}, 72 Verbose: false, 73 JSONOutput: false, 74 Verbosity: verbosity, 75 } 76 } 77 78 // match checks if the event type, from endpoint and / or to endpoint match 79 // when they are supplied. The either part of from and to endpoint depends on 80 // related to, which can match on both. If either one of them is less than or 81 // equal to zero, then it is assumed user did not use them. 82 func (m *MonitorFormatter) match(messageType int, src uint16, dst uint16) bool { 83 if len(m.EventTypes) > 0 && !m.EventTypes.Contains(messageType) { 84 return false 85 } else if len(m.FromSource) > 0 && !m.FromSource.Has(src) { 86 return false 87 } else if len(m.ToDst) > 0 && !m.ToDst.Has(dst) { 88 return false 89 } else if len(m.Related) > 0 && !m.Related.Has(src) && !m.Related.Has(dst) { 90 return false 91 } 92 93 return true 94 } 95 96 // dropEvents prints out all the received drop notifications. 97 func (m *MonitorFormatter) dropEvents(prefix string, data []byte) { 98 dn := monitor.DropNotify{} 99 100 if err := binary.Read(bytes.NewReader(data), byteorder.Native, &dn); err != nil { 101 fmt.Printf("Error while parsing drop notification message: %s\n", err) 102 } 103 if m.match(monitorAPI.MessageTypeDrop, dn.Source, uint16(dn.DstID)) { 104 switch m.Verbosity { 105 case INFO: 106 dn.DumpInfo(data) 107 case JSON: 108 dn.DumpJSON(data, prefix) 109 default: 110 fmt.Println(msgSeparator) 111 dn.DumpVerbose(!m.Hex, data, prefix) 112 } 113 } 114 } 115 116 // traceEvents prints out all the received trace notifications. 117 func (m *MonitorFormatter) traceEvents(prefix string, data []byte) { 118 tn := monitor.TraceNotify{} 119 120 if err := binary.Read(bytes.NewReader(data), byteorder.Native, &tn); err != nil { 121 fmt.Printf("Error while parsing trace notification message: %s\n", err) 122 } 123 if m.match(monitorAPI.MessageTypeTrace, tn.Source, tn.DstID) { 124 switch m.Verbosity { 125 case INFO: 126 tn.DumpInfo(data) 127 case JSON: 128 tn.DumpJSON(data, prefix) 129 default: 130 fmt.Println(msgSeparator) 131 tn.DumpVerbose(!m.Hex, data, prefix) 132 } 133 } 134 } 135 136 // debugEvents prints out all the debug messages. 137 func (m *MonitorFormatter) debugEvents(prefix string, data []byte) { 138 dm := monitor.DebugMsg{} 139 140 if err := binary.Read(bytes.NewReader(data), byteorder.Native, &dm); err != nil { 141 fmt.Printf("Error while parsing debug message: %s\n", err) 142 } 143 if m.match(monitorAPI.MessageTypeDebug, dm.Source, 0) { 144 switch m.Verbosity { 145 case INFO: 146 dm.DumpInfo(data) 147 case JSON: 148 dm.DumpJSON(prefix) 149 default: 150 dm.Dump(prefix) 151 } 152 } 153 } 154 155 // captureEvents prints out all the capture messages. 156 func (m *MonitorFormatter) captureEvents(prefix string, data []byte) { 157 dc := monitor.DebugCapture{} 158 159 if err := binary.Read(bytes.NewReader(data), byteorder.Native, &dc); err != nil { 160 fmt.Printf("Error while parsing debug capture message: %s\n", err) 161 } 162 if m.match(monitorAPI.MessageTypeCapture, dc.Source, 0) { 163 switch m.Verbosity { 164 case INFO: 165 dc.DumpInfo(data) 166 case JSON: 167 dc.DumpJSON(data, prefix) 168 default: 169 fmt.Println(msgSeparator) 170 dc.DumpVerbose(!m.Hex, data, prefix) 171 } 172 } 173 } 174 175 // logRecordEvents prints out LogRecord events 176 func (m *MonitorFormatter) logRecordEvents(prefix string, data []byte) { 177 buf := bytes.NewBuffer(data[1:]) 178 dec := gob.NewDecoder(buf) 179 180 lr := monitor.LogRecordNotify{} 181 if err := dec.Decode(&lr); err != nil { 182 fmt.Printf("Error while decoding LogRecord notification message: %s\n", err) 183 } 184 185 if m.match(monitorAPI.MessageTypeAccessLog, uint16(lr.SourceEndpoint.ID), uint16(lr.DestinationEndpoint.ID)) { 186 if m.Verbosity == JSON { 187 lr.DumpJSON() 188 } else { 189 lr.DumpInfo() 190 } 191 } 192 } 193 194 // agentEvents prints out agent events 195 func (m *MonitorFormatter) agentEvents(prefix string, data []byte) { 196 buf := bytes.NewBuffer(data[1:]) 197 dec := gob.NewDecoder(buf) 198 199 an := monitorAPI.AgentNotify{} 200 if err := dec.Decode(&an); err != nil { 201 fmt.Printf("Error while decoding agent notification message: %s\n", err) 202 } 203 204 if m.match(monitorAPI.MessageTypeAgent, 0, 0) { 205 if m.Verbosity == JSON { 206 an.DumpJSON() 207 } else { 208 an.DumpInfo() 209 } 210 } 211 } 212 213 // FormatSample prints an event from the provided raw data slice to stdout. 214 // 215 // For most monitor event types, 'data' corresponds to the 'data' field in 216 // bpf.PerfEventSample. Exceptions are MessageTypeAccessLog and 217 // MessageTypeAgent. 218 func (m *MonitorFormatter) FormatSample(data []byte, cpu int) { 219 prefix := fmt.Sprintf("CPU %02d:", cpu) 220 messageType := data[0] 221 222 switch messageType { 223 case monitorAPI.MessageTypeDrop: 224 m.dropEvents(prefix, data) 225 case monitorAPI.MessageTypeDebug: 226 m.debugEvents(prefix, data) 227 case monitorAPI.MessageTypeCapture: 228 m.captureEvents(prefix, data) 229 case monitorAPI.MessageTypeTrace: 230 m.traceEvents(prefix, data) 231 case monitorAPI.MessageTypeAccessLog: 232 m.logRecordEvents(prefix, data) 233 case monitorAPI.MessageTypeAgent: 234 m.agentEvents(prefix, data) 235 default: 236 fmt.Printf("%s Unknown event: %+v\n", prefix, data) 237 } 238 } 239 240 // LostEvent formats a lost event using the specified payload parameters. 241 func LostEvent(lost uint64, cpu int) { 242 fmt.Printf("CPU %02d: Lost %d events\n", cpu, lost) 243 } 244 245 // FormatEvent formats an event from the specified payload to stdout. 246 // 247 // Returns true if the event was successfully printed, false otherwise. 248 func (m *MonitorFormatter) FormatEvent(pl *payload.Payload) bool { 249 switch pl.Type { 250 case payload.EventSample: 251 m.FormatSample(pl.Data, pl.CPU) 252 case payload.RecordLost: 253 LostEvent(pl.Lost, pl.CPU) 254 default: 255 return false 256 } 257 258 return true 259 }