github.com/fafucoder/cilium@v1.6.11/pkg/monitor/datapath_trace.go (about)

     1  // Copyright 2016-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 monitor
    16  
    17  import (
    18  	"encoding/json"
    19  	"fmt"
    20  )
    21  
    22  const (
    23  	// TraceNotifyLen is the amount of packet data provided in a trace notification
    24  	TraceNotifyLen = 32
    25  	// TraceReasonEncryptMask is the bit used to indicate encryption or not
    26  	TraceReasonEncryptMask uint8 = 0x80
    27  )
    28  
    29  // TraceNotify is the message format of a trace notification in the BPF ring buffer
    30  type TraceNotify struct {
    31  	Type     uint8
    32  	ObsPoint uint8
    33  	Source   uint16
    34  	Hash     uint32
    35  	OrigLen  uint32
    36  	CapLen   uint32
    37  	SrcLabel uint32
    38  	DstLabel uint32
    39  	DstID    uint16
    40  	Reason   uint8
    41  	Pad      uint8
    42  	Ifindex  uint32
    43  	// data
    44  }
    45  
    46  // Available observation points.
    47  const (
    48  	TraceToLxc = iota
    49  	TraceToProxy
    50  	TraceToHost
    51  	TraceToStack
    52  	TraceToOverlay
    53  	TraceFromLxc
    54  	TraceFromProxy
    55  	TraceFromHost
    56  	TraceFromStack
    57  	TraceFromOverlay
    58  	TraceFromNetwork
    59  )
    60  
    61  var traceObsPoints = map[uint8]string{
    62  	TraceToLxc:       "to-endpoint",
    63  	TraceToProxy:     "to-proxy",
    64  	TraceToHost:      "to-host",
    65  	TraceToStack:     "to-stack",
    66  	TraceToOverlay:   "to-overlay",
    67  	TraceFromLxc:     "from-endpoint",
    68  	TraceFromProxy:   "from-proxy",
    69  	TraceFromHost:    "from-host",
    70  	TraceFromStack:   "from-stack",
    71  	TraceFromOverlay: "from-overlay",
    72  	TraceFromNetwork: "from-network",
    73  }
    74  
    75  func obsPoint(obsPoint uint8) string {
    76  	if str, ok := traceObsPoints[obsPoint]; ok {
    77  		return str
    78  	}
    79  	return fmt.Sprintf("%d", obsPoint)
    80  }
    81  
    82  // Reasons for forwarding a packet.
    83  const (
    84  	TraceReasonPolicy = iota
    85  	TraceReasonCtEstablished
    86  	TraceReasonCtReply
    87  	TraceReasonCtRelated
    88  )
    89  
    90  var traceReasons = map[uint8]string{
    91  	TraceReasonPolicy:        "new",
    92  	TraceReasonCtEstablished: "established",
    93  	TraceReasonCtReply:       "reply",
    94  	TraceReasonCtRelated:     "related",
    95  }
    96  
    97  func connState(reason uint8) string {
    98  	r := reason & ^TraceReasonEncryptMask
    99  	if str, ok := traceReasons[r]; ok {
   100  		return str
   101  	}
   102  	return fmt.Sprintf("%d", reason)
   103  }
   104  
   105  func (n *TraceNotify) encryptReason() string {
   106  	if (n.Reason & TraceReasonEncryptMask) != 0 {
   107  		return fmt.Sprintf("encrypted ")
   108  	}
   109  	return ""
   110  }
   111  
   112  func (n *TraceNotify) traceReason() string {
   113  	return connState(n.Reason)
   114  }
   115  
   116  func (n *TraceNotify) traceSummary() string {
   117  	switch n.ObsPoint {
   118  	case TraceToLxc:
   119  		return fmt.Sprintf("-> endpoint %d", n.DstID)
   120  	case TraceToProxy:
   121  		return "-> proxy"
   122  	case TraceToHost:
   123  		return "-> host from"
   124  	case TraceToStack:
   125  		return "-> stack"
   126  	case TraceToOverlay:
   127  		return "-> overlay"
   128  	case TraceFromLxc:
   129  		return fmt.Sprintf("<- endpoint %d", n.Source)
   130  	case TraceFromProxy:
   131  		return "<- proxy"
   132  	case TraceFromHost:
   133  		return "<- host"
   134  	case TraceFromStack:
   135  		return "<- stack"
   136  	case TraceFromOverlay:
   137  		return "<- overlay"
   138  	case TraceFromNetwork:
   139  		return "<- network"
   140  	default:
   141  		return "unknown trace"
   142  	}
   143  }
   144  
   145  // DumpInfo prints a summary of the trace messages.
   146  func (n *TraceNotify) DumpInfo(data []byte) {
   147  	if n.encryptReason() != "" {
   148  		fmt.Printf("%s %s flow %#x identity %d->%d state %s ifindex %s: %s\n",
   149  			n.traceSummary(), n.encryptReason(), n.Hash, n.SrcLabel, n.DstLabel,
   150  			n.traceReason(), ifname(int(n.Ifindex)), GetConnectionSummary(data[TraceNotifyLen:]))
   151  	} else {
   152  		fmt.Printf("%s flow %#x identity %d->%d state %s ifindex %s: %s\n",
   153  			n.traceSummary(), n.Hash, n.SrcLabel, n.DstLabel,
   154  			n.traceReason(), ifname(int(n.Ifindex)), GetConnectionSummary(data[TraceNotifyLen:]))
   155  	}
   156  }
   157  
   158  // DumpVerbose prints the trace notification in human readable form
   159  func (n *TraceNotify) DumpVerbose(dissect bool, data []byte, prefix string) {
   160  	fmt.Printf("%s MARK %#x FROM %d %s: %d bytes (%d captured), state %s",
   161  		prefix, n.Hash, n.Source, obsPoint(n.ObsPoint), n.OrigLen, n.CapLen, connState(n.Reason))
   162  
   163  	if n.Ifindex != 0 {
   164  		fmt.Printf(", interface %s", ifname(int(n.Ifindex)))
   165  	}
   166  
   167  	if n.SrcLabel != 0 || n.DstLabel != 0 {
   168  		fmt.Printf(", identity %d->%d", n.SrcLabel, n.DstLabel)
   169  	}
   170  
   171  	if n.DstID != 0 {
   172  		fmt.Printf(", to endpoint %d\n", n.DstID)
   173  	} else {
   174  		fmt.Printf("\n")
   175  	}
   176  
   177  	if n.CapLen > 0 && len(data) > TraceNotifyLen {
   178  		Dissect(dissect, data[TraceNotifyLen:])
   179  	}
   180  }
   181  
   182  func (n *TraceNotify) getJSON(data []byte, cpuPrefix string) (string, error) {
   183  	v := TraceNotifyToVerbose(n)
   184  	v.CPUPrefix = cpuPrefix
   185  	if n.CapLen > 0 && len(data) > TraceNotifyLen {
   186  		v.Summary = GetDissectSummary(data[TraceNotifyLen:])
   187  	}
   188  
   189  	ret, err := json.Marshal(v)
   190  	return string(ret), err
   191  }
   192  
   193  // DumpJSON prints notification in json format
   194  func (n *TraceNotify) DumpJSON(data []byte, cpuPrefix string) {
   195  	resp, err := n.getJSON(data, cpuPrefix)
   196  	if err == nil {
   197  		fmt.Println(resp)
   198  	}
   199  }
   200  
   201  // TraceNotifyVerbose represents a json notification printed by monitor
   202  type TraceNotifyVerbose struct {
   203  	CPUPrefix        string `json:"cpu,omitempty"`
   204  	Type             string `json:"type,omitempty"`
   205  	Mark             string `json:"mark,omitempty"`
   206  	Ifindex          string `json:"ifindex,omitempty"`
   207  	State            string `json:"state,omitempty"`
   208  	ObservationPoint string `json:"observationPoint"`
   209  	TraceSummary     string `json:"traceSummary"`
   210  
   211  	Source   uint16 `json:"source"`
   212  	Bytes    uint32 `json:"bytes"`
   213  	SrcLabel uint32 `json:"srcLabel"`
   214  	DstLabel uint32 `json:"dstLabel"`
   215  	DstID    uint16 `json:"dstID"`
   216  
   217  	Summary *DissectSummary `json:"summary,omitempty"`
   218  }
   219  
   220  // TraceNotifyToVerbose creates verbose notification from base TraceNotify
   221  func TraceNotifyToVerbose(n *TraceNotify) TraceNotifyVerbose {
   222  	return TraceNotifyVerbose{
   223  		Type:             "trace",
   224  		Mark:             fmt.Sprintf("%#x", n.Hash),
   225  		Ifindex:          ifname(int(n.Ifindex)),
   226  		State:            connState(n.Reason),
   227  		ObservationPoint: obsPoint(n.ObsPoint),
   228  		TraceSummary:     n.traceSummary(),
   229  		Source:           n.Source,
   230  		Bytes:            n.OrigLen,
   231  		SrcLabel:         n.SrcLabel,
   232  		DstLabel:         n.DstLabel,
   233  		DstID:            n.DstID,
   234  	}
   235  }