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

     1  // Copyright 2017-2019 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 agent
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"encoding/gob"
    21  	"fmt"
    22  	"net"
    23  	"os"
    24  
    25  	"github.com/cilium/cilium/api/v1/models"
    26  	"github.com/cilium/cilium/pkg/api"
    27  	"github.com/cilium/cilium/pkg/defaults"
    28  	"github.com/cilium/cilium/pkg/lock"
    29  	"github.com/cilium/cilium/pkg/logging"
    30  	"github.com/cilium/cilium/pkg/logging/logfields"
    31  	"github.com/cilium/cilium/pkg/monitor/payload"
    32  	"github.com/cilium/cilium/pkg/option"
    33  )
    34  
    35  var (
    36  	log = logging.DefaultLogger.WithField(logfields.LogSubsys, "monitor-agent")
    37  )
    38  
    39  // buildServer opens a listener socket at path. It exits with logging on all
    40  // errors.
    41  func buildServer(path string) (net.Listener, error) {
    42  	os.Remove(path)
    43  	server, err := net.Listen("unix", path)
    44  	if err != nil {
    45  		return nil, fmt.Errorf("cannot listen on unix socket %s: %s", path, err)
    46  	}
    47  
    48  	if os.Getuid() == 0 {
    49  		err := api.SetDefaultPermissions(path)
    50  		if err != nil {
    51  			return nil, fmt.Errorf("cannot set default permissions on socket %s: %s", path, err)
    52  		}
    53  	}
    54  
    55  	return server, nil
    56  }
    57  
    58  // Agent represents an instance of a monitor agent. It runs a monitor to read
    59  // events from the BPF perf ring buffer and provides an interface to also pass
    60  // in non-BPF events.
    61  type Agent struct {
    62  	mutex     lock.Mutex
    63  	lost      uint64
    64  	server1_2 net.Listener
    65  	monitor   *Monitor
    66  	queue     chan payload.Payload
    67  }
    68  
    69  // NewAgent creates a new monitor agent
    70  func NewAgent(ctx context.Context, npages int) (a *Agent, err error) {
    71  	a = &Agent{
    72  		queue: make(chan payload.Payload, option.Config.MonitorQueueSize),
    73  	}
    74  
    75  	a.server1_2, err = buildServer(defaults.MonitorSockPath1_2)
    76  	if err != nil {
    77  		return
    78  	}
    79  
    80  	a.monitor, err = NewMonitor(ctx, npages, a.server1_2)
    81  	if err != nil {
    82  		return
    83  	}
    84  
    85  	log.Infof("Serving cilium node monitor v1.2 API at unix://%s", defaults.MonitorSockPath1_2)
    86  
    87  	go a.eventDrainer()
    88  
    89  	return
    90  }
    91  
    92  // Stop stops the monitor agent
    93  func (a *Agent) Stop() {
    94  	a.server1_2.Close()
    95  	close(a.queue)
    96  }
    97  
    98  func (a *Agent) eventDrainer() {
    99  	for {
   100  		p, ok := <-a.queue
   101  		if !ok {
   102  			return
   103  		}
   104  
   105  		a.monitor.send(&p)
   106  	}
   107  }
   108  
   109  // State returns the monitor status.
   110  func (a *Agent) State() *models.MonitorStatus {
   111  	if a == nil || a.monitor == nil {
   112  		return nil
   113  	}
   114  
   115  	return a.monitor.Status()
   116  }
   117  
   118  // SendEvent sends an event to the node monitor which will then distribute to
   119  // all monitor listeners
   120  func (a *Agent) SendEvent(typ int, event interface{}) error {
   121  	var buf bytes.Buffer
   122  
   123  	if a == nil {
   124  		return fmt.Errorf("monitor agent is not set up")
   125  	}
   126  
   127  	if err := gob.NewEncoder(&buf).Encode(event); err != nil {
   128  		//nm.bumpLost()
   129  		return fmt.Errorf("Unable to gob encode: %s", err)
   130  	}
   131  
   132  	a.mutex.Lock()
   133  	defer a.mutex.Unlock()
   134  
   135  	p := payload.Payload{Data: append([]byte{byte(typ)}, buf.Bytes()...), CPU: 0, Lost: 0, Type: payload.EventSample}
   136  
   137  	select {
   138  	case a.queue <- p:
   139  	default:
   140  		//nm.bumpLost()
   141  		return fmt.Errorf("Monitor queue is full, discarding notification")
   142  	}
   143  
   144  	return nil
   145  }