From e634f4672260dac9c086a06bfe10e4e3859c77a1 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 15 Apr 2024 14:54:55 +0200 Subject: vm: export VM output metric VM output we receive on the host is effectively equivalent to RPC recv metric. If we stop printing programs in the fuzzer, traffic will move from output to RPC. It will be useful to see this change via metrics. --- pkg/rpctype/rpc.go | 8 ++------ pkg/stats/set.go | 5 +++++ vm/vm.go | 47 +++++++++++++++++++++++++---------------------- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/pkg/rpctype/rpc.go b/pkg/rpctype/rpc.go index ef434ebef..39a299653 100644 --- a/pkg/rpctype/rpc.go +++ b/pkg/rpctype/rpc.go @@ -33,18 +33,14 @@ func NewRPCServer(addr, name string, receiver interface{}, useCompression bool) if err := s.RegisterName(name, receiver); err != nil { return nil, err } - formatMB := func(v int, period time.Duration) string { - const KB, MB = 1 << 10, 1 << 20 - return fmt.Sprintf("%v MB (%v kb/sec)", (v+MB/2)/MB, (v+KB/2)/KB/int(period/time.Second)) - } serv := &RPCServer{ ln: ln, s: s, useCompression: useCompression, statSent: stats.Create("rpc sent", "Uncompressed outbound RPC traffic", - stats.Graph("RPC traffic"), stats.Rate{}, formatMB), + stats.Graph("traffic"), stats.Rate{}, stats.FormatMB), statRecv: stats.Create("rpc recv", "Uncompressed inbound RPC traffic", - stats.Graph("RPC traffic"), stats.Rate{}, formatMB), + stats.Graph("traffic"), stats.Rate{}, stats.FormatMB), } return serv, nil } diff --git a/pkg/stats/set.go b/pkg/stats/set.go index 54e44e457..f5671148d 100644 --- a/pkg/stats/set.go +++ b/pkg/stats/set.go @@ -190,6 +190,11 @@ func LenOf(containerPtr any, mu *sync.RWMutex) func() int { } } +func FormatMB(v int, period time.Duration) string { + const KB, MB = 1 << 10, 1 << 20 + return fmt.Sprintf("%v MB (%v kb/sec)", (v+MB/2)/MB, (v+KB/2)/KB/int(period/time.Second)) +} + // Addittionally a custom 'func() int' can be passed to read the metric value from the function. // and 'func(int, time.Duration) string' can be passed for custom formatting of the metric value. diff --git a/vm/vm.go b/vm/vm.go index 918ac878a..5972771b7 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -21,6 +21,7 @@ import ( "github.com/google/syzkaller/pkg/mgrconfig" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/pkg/report" + "github.com/google/syzkaller/pkg/stats" "github.com/google/syzkaller/sys/targets" "github.com/google/syzkaller/vm/vmimpl" @@ -39,21 +40,21 @@ import ( ) type Pool struct { - impl vmimpl.Pool - workdir string - template string - timeouts targets.Timeouts - activeCount int32 - hostFuzzer bool + impl vmimpl.Pool + workdir string + template string + timeouts targets.Timeouts + activeCount int32 + hostFuzzer bool + statOutputReceived *stats.Val } type Instance struct { - impl vmimpl.Instance - workdir string - timeouts targets.Timeouts - index int - onClose func() - hostFuzzer bool + pool *Pool + impl vmimpl.Instance + workdir string + index int + onClose func() } var ( @@ -126,6 +127,8 @@ func Create(cfg *mgrconfig.Config, debug bool) (*Pool, error) { template: cfg.WorkdirTemplate, timeouts: cfg.Timeouts, hostFuzzer: cfg.SysTarget.HostFuzzer, + statOutputReceived: stats.Create("vm output", "Bytes of VM console output received", + stats.Graph("traffic"), stats.Rate{}, stats.FormatMB), }, nil } @@ -153,12 +156,11 @@ func (pool *Pool) Create(index int) (*Instance, error) { } atomic.AddInt32(&pool.activeCount, 1) return &Instance{ - impl: impl, - workdir: workdir, - timeouts: pool.timeouts, - index: index, - onClose: func() { atomic.AddInt32(&pool.activeCount, -1) }, - hostFuzzer: pool.hostFuzzer, + pool: pool, + impl: impl, + workdir: workdir, + index: index, + onClose: func() { atomic.AddInt32(&pool.activeCount, -1) }, }, nil } @@ -251,7 +253,7 @@ func (inst *Instance) Info() ([]byte, error) { } func (inst *Instance) PprofPort() int { - if inst.hostFuzzer { + if inst.pool.hostFuzzer { // In the fuzzing on host mode, fuzzers are always on the same network. // Don't set up pprof endpoints in this case. return 0 @@ -289,7 +291,7 @@ type monitor struct { } func (mon *monitor) monitorExecution() *report.Report { - ticker := time.NewTicker(tickerPeriod * mon.inst.timeouts.Scale) + ticker := time.NewTicker(tickerPeriod * mon.inst.pool.timeouts.Scale) defer ticker.Stop() for { select { @@ -322,6 +324,7 @@ func (mon *monitor) monitorExecution() *report.Report { mon.outc = nil continue } + mon.inst.pool.statOutputReceived.Add(len(out)) if rep := mon.appendOutput(out); rep != nil { return rep } @@ -332,7 +335,7 @@ func (mon *monitor) monitorExecution() *report.Report { case <-ticker.C: // Detect both "no output whatsoever" and "kernel episodically prints // something to console, but fuzzer is not actually executing programs". - if time.Since(mon.lastExecuteTime) > mon.inst.timeouts.NoOutput { + if time.Since(mon.lastExecuteTime) > mon.inst.pool.timeouts.NoOutput { return mon.extractError(noOutputCrash) } case <-Shutdown: @@ -432,7 +435,7 @@ func (mon *monitor) createReport(defaultError string) *report.Report { } func (mon *monitor) waitForOutput() { - timer := time.NewTimer(waitForOutputTimeout * mon.inst.timeouts.Scale) + timer := time.NewTimer(waitForOutputTimeout * mon.inst.pool.timeouts.Scale) defer timer.Stop() for { select { -- cgit mrf-deployment