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 }