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  }