github.com/fafucoder/cilium@v1.6.11/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  }