github.com/cilium/cilium@v1.16.2/pkg/monitor/datapath_drop.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package monitor
     5  
     6  import (
     7  	"bufio"
     8  	"encoding/json"
     9  	"fmt"
    10  	"os"
    11  
    12  	"github.com/cilium/cilium/pkg/byteorder"
    13  	"github.com/cilium/cilium/pkg/identity"
    14  	"github.com/cilium/cilium/pkg/monitor/api"
    15  )
    16  
    17  const (
    18  	// DropNotifyLen is the amount of packet data provided in a drop notification
    19  	DropNotifyLen = 36
    20  )
    21  
    22  // DropNotify is the message format of a drop notification in the BPF ring buffer
    23  type DropNotify struct {
    24  	Type     uint8
    25  	SubType  uint8
    26  	Source   uint16
    27  	Hash     uint32
    28  	OrigLen  uint32
    29  	CapLen   uint32
    30  	SrcLabel identity.NumericIdentity
    31  	DstLabel identity.NumericIdentity
    32  	DstID    uint32
    33  	Line     uint16
    34  	File     uint8
    35  	ExtError int8
    36  	Ifindex  uint32
    37  	// data
    38  }
    39  
    40  // dumpIdentity dumps the source and destination identities in numeric or
    41  // human-readable format.
    42  func (n *DropNotify) dumpIdentity(buf *bufio.Writer, numeric DisplayFormat) {
    43  	if numeric {
    44  		fmt.Fprintf(buf, ", identity %d->%d", n.SrcLabel, n.DstLabel)
    45  	} else {
    46  		fmt.Fprintf(buf, ", identity %s->%s", n.SrcLabel, n.DstLabel)
    47  	}
    48  }
    49  
    50  // DecodeDropNotify will decode 'data' into the provided DropNotify structure
    51  func DecodeDropNotify(data []byte, dn *DropNotify) error {
    52  	return dn.decodeDropNotify(data)
    53  }
    54  
    55  func (n *DropNotify) decodeDropNotify(data []byte) error {
    56  	if l := len(data); l < DropNotifyLen {
    57  		return fmt.Errorf("unexpected DropNotify data length, expected %d but got %d", DropNotifyLen, l)
    58  	}
    59  
    60  	n.Type = data[0]
    61  	n.SubType = data[1]
    62  	n.Source = byteorder.Native.Uint16(data[2:4])
    63  	n.Hash = byteorder.Native.Uint32(data[4:8])
    64  	n.OrigLen = byteorder.Native.Uint32(data[8:12])
    65  	n.CapLen = byteorder.Native.Uint32(data[12:16])
    66  	n.SrcLabel = identity.NumericIdentity(byteorder.Native.Uint32(data[16:20]))
    67  	n.DstLabel = identity.NumericIdentity(byteorder.Native.Uint32(data[20:24]))
    68  	n.DstID = byteorder.Native.Uint32(data[24:28])
    69  	n.Line = byteorder.Native.Uint16(data[28:30])
    70  	n.File = data[30]
    71  	n.ExtError = int8(data[31])
    72  	n.Ifindex = byteorder.Native.Uint32(data[32:36])
    73  
    74  	return nil
    75  }
    76  
    77  // DumpInfo prints a summary of the drop messages.
    78  func (n *DropNotify) DumpInfo(data []byte, numeric DisplayFormat) {
    79  	buf := bufio.NewWriter(os.Stdout)
    80  	fmt.Fprintf(buf, "xx drop (%s) flow %#x to endpoint %d, ifindex %d, file %s:%d, ",
    81  		api.DropReasonExt(n.SubType, n.ExtError), n.Hash, n.DstID, n.Ifindex, api.BPFFileName(n.File), int(n.Line))
    82  	n.dumpIdentity(buf, numeric)
    83  	fmt.Fprintf(buf, ": %s\n", GetConnectionSummary(data[DropNotifyLen:]))
    84  	buf.Flush()
    85  }
    86  
    87  // DumpVerbose prints the drop notification in human readable form
    88  func (n *DropNotify) DumpVerbose(dissect bool, data []byte, prefix string, numeric DisplayFormat) {
    89  	buf := bufio.NewWriter(os.Stdout)
    90  	fmt.Fprintf(buf, "%s MARK %#x FROM %d DROP: %d bytes, reason %s",
    91  		prefix, n.Hash, n.Source, n.OrigLen, api.DropReasonExt(n.SubType, n.ExtError))
    92  
    93  	if n.SrcLabel != 0 || n.DstLabel != 0 {
    94  		n.dumpIdentity(buf, numeric)
    95  	}
    96  
    97  	if n.DstID != 0 {
    98  		fmt.Fprintf(buf, ", to endpoint %d\n", n.DstID)
    99  	} else {
   100  		fmt.Fprintf(buf, "\n")
   101  	}
   102  
   103  	if n.CapLen > 0 && len(data) > DropNotifyLen {
   104  		Dissect(dissect, data[DropNotifyLen:])
   105  	}
   106  	buf.Flush()
   107  }
   108  
   109  func (n *DropNotify) getJSON(data []byte, cpuPrefix string) (string, error) {
   110  
   111  	v := DropNotifyToVerbose(n)
   112  	v.CPUPrefix = cpuPrefix
   113  	if n.CapLen > 0 && len(data) > DropNotifyLen {
   114  		v.Summary = GetDissectSummary(data[DropNotifyLen:])
   115  	}
   116  
   117  	ret, err := json.Marshal(v)
   118  	return string(ret), err
   119  }
   120  
   121  // DumpJSON prints notification in json format
   122  func (n *DropNotify) DumpJSON(data []byte, cpuPrefix string) {
   123  	resp, err := n.getJSON(data, cpuPrefix)
   124  	if err == nil {
   125  		fmt.Println(resp)
   126  	}
   127  }
   128  
   129  // DropNotifyVerbose represents a json notification printed by monitor
   130  type DropNotifyVerbose struct {
   131  	CPUPrefix string `json:"cpu,omitempty"`
   132  	Type      string `json:"type,omitempty"`
   133  	Mark      string `json:"mark,omitempty"`
   134  	Reason    string `json:"reason,omitempty"`
   135  
   136  	Source   uint16                   `json:"source"`
   137  	Bytes    uint32                   `json:"bytes"`
   138  	SrcLabel identity.NumericIdentity `json:"srcLabel"`
   139  	DstLabel identity.NumericIdentity `json:"dstLabel"`
   140  	DstID    uint32                   `json:"dstID"`
   141  	Line     uint16                   `json:"Line"`
   142  	File     uint8                    `json:"File"`
   143  	ExtError int8                     `json:"ExtError"`
   144  	Ifindex  uint32                   `json:"Ifindex"`
   145  
   146  	Summary *DissectSummary `json:"summary,omitempty"`
   147  }
   148  
   149  // DropNotifyToVerbose creates verbose notification from DropNotify
   150  func DropNotifyToVerbose(n *DropNotify) DropNotifyVerbose {
   151  	return DropNotifyVerbose{
   152  		Type:     "drop",
   153  		Mark:     fmt.Sprintf("%#x", n.Hash),
   154  		Reason:   api.DropReasonExt(n.SubType, n.ExtError),
   155  		Source:   n.Source,
   156  		Bytes:    n.OrigLen,
   157  		SrcLabel: n.SrcLabel,
   158  		DstLabel: n.DstLabel,
   159  		DstID:    n.DstID,
   160  		Line:     n.Line,
   161  		File:     n.File,
   162  		ExtError: n.ExtError,
   163  		Ifindex:  n.Ifindex,
   164  	}
   165  }