github.com/zhyoulun/cilium@v1.6.12/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 }