github.com/fafucoder/cilium@v1.6.11/pkg/monitor/payload/monitor_payload.go (about) 1 // Copyright 2017 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 payload 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "encoding/gob" 21 "fmt" 22 "io" 23 24 "github.com/cilium/cilium/pkg/byteorder" 25 ) 26 27 // Below constants are based on the ones from <linux/perf_event.h>. 28 const ( 29 // EventSample is equivalent to PERF_RECORD_SAMPLE 30 EventSample = 9 31 // RecordLost is equivalent to PERF_RECORD_LOST 32 RecordLost = 2 33 ) 34 35 // Meta is used by readers to get information about the payload. 36 type Meta struct { 37 Size uint32 38 _ [28]byte // Reserved 28 bytes for future fields. 39 } 40 41 // UnmarshalBinary decodes the metadata from its binary representation. 42 func (meta *Meta) UnmarshalBinary(data []byte) error { 43 return meta.ReadBinary(bytes.NewReader(data)) 44 } 45 46 // MarshalBinary encodes the metadata into its binary representation. 47 func (meta *Meta) MarshalBinary() ([]byte, error) { 48 var buf bytes.Buffer 49 if err := meta.WriteBinary(&buf); err != nil { 50 return nil, err 51 } 52 return buf.Bytes(), nil 53 } 54 55 // ReadBinary reads the metadata from its binary representation. 56 func (meta *Meta) ReadBinary(r io.Reader) error { 57 return binary.Read(r, byteorder.Native, meta) 58 } 59 60 // WriteBinary writes the metadata into its binary representation. 61 func (meta *Meta) WriteBinary(w io.Writer) error { 62 return binary.Write(w, byteorder.Native, meta) 63 } 64 65 // Payload is the structure used when copying events from the main monitor. 66 type Payload struct { 67 Data []byte 68 CPU int 69 Lost uint64 70 Type int 71 } 72 73 // Decode decodes the payload from its binary representation. 74 func (pl *Payload) Decode(data []byte) error { 75 // Note that this method can't be named UnmarshalBinary, because the gob encoder would call 76 // this method, resulting in infinite recursion. 77 return pl.ReadBinary(bytes.NewBuffer(data)) 78 } 79 80 // Encode encodes the payload into its binary representation. 81 func (pl *Payload) Encode() ([]byte, error) { 82 // Note that this method can't be named MarshalBinary, because the gob encoder would call 83 // this method, resulting in infinite recursion. 84 var buf bytes.Buffer 85 if err := pl.WriteBinary(&buf); err != nil { 86 return nil, err 87 } 88 return buf.Bytes(), nil 89 } 90 91 // ReadBinary reads the payload from its binary representation. 92 func (pl *Payload) ReadBinary(r io.Reader) error { 93 dec := gob.NewDecoder(r) 94 return pl.DecodeBinary(dec) 95 } 96 97 // WriteBinary writes the payload into its binary representation. 98 func (pl *Payload) WriteBinary(w io.Writer) error { 99 enc := gob.NewEncoder(w) 100 return pl.EncodeBinary(enc) 101 } 102 103 // EncodeBinary writes the payload into its binary representation. 104 func (pl *Payload) EncodeBinary(enc *gob.Encoder) error { 105 return enc.Encode(pl) 106 } 107 108 // DecodeBinary reads the payload from its binary representation. 109 func (pl *Payload) DecodeBinary(dec *gob.Decoder) error { 110 return dec.Decode(pl) 111 } 112 113 // ReadMetaPayload reads a Meta and Payload from a Cilium monitor connection. 114 func ReadMetaPayload(r io.Reader, meta *Meta, pl *Payload) error { 115 if err := meta.ReadBinary(r); err != nil { 116 return err 117 } 118 119 // Meta.Size is not necessary for framing/decoding, but is useful to validate the payload size. 120 return pl.ReadBinary(io.LimitReader(r, int64(meta.Size))) 121 } 122 123 // WriteMetaPayload writes a Meta and Payload into a Cilium monitor connection. 124 // meta.Size is set to the size of the encoded Payload. 125 func WriteMetaPayload(w io.Writer, meta *Meta, pl *Payload) error { 126 payloadBuf, err := pl.Encode() 127 if err != nil { 128 return err 129 } 130 meta.Size = uint32(len(payloadBuf)) 131 meta.WriteBinary(w) 132 _, err = w.Write(payloadBuf) 133 return err 134 } 135 136 // BuildMessage builds the binary message to be sent and returns it 137 func (pl *Payload) BuildMessage() ([]byte, error) { 138 plBuf, err := pl.Encode() 139 if err != nil { 140 return nil, fmt.Errorf("unable to encode payload: %s", err) 141 } 142 143 meta := &Meta{Size: uint32(len(plBuf))} 144 metaBuf, err := meta.MarshalBinary() 145 if err != nil { 146 return nil, fmt.Errorf("unable to encode metadata: %s", err) 147 } 148 149 return append(metaBuf, plBuf...), nil 150 }