From c42bc10c1f4271cee7d03b6456bcb4bffa7783ac Mon Sep 17 00:00:00 2001 From: Michael Schubert Date: Fri, 10 Mar 2017 08:22:58 +0100 Subject: [PATCH] Implement ebpf proc fallback --- probe/endpoint/connection_tracker.go | 55 ++++++++++++++-------------- probe/endpoint/reporter.go | 3 ++ prog/probe.go | 8 +--- 3 files changed, 31 insertions(+), 35 deletions(-) diff --git a/probe/endpoint/connection_tracker.go b/probe/endpoint/connection_tracker.go index 14bf7665b8..ba008f5c6c 100644 --- a/probe/endpoint/connection_tracker.go +++ b/probe/endpoint/connection_tracker.go @@ -19,6 +19,7 @@ type connectionTrackerConfig struct { UseEbpfConn bool ProcRoot string BufferSize int + ProcessCache *process.CachingWalker Scanner procspy.ConnectionScanner DNSSnooper *DNSSnooper } @@ -28,43 +29,37 @@ type connectionTracker struct { flowWalker flowWalker // Interface ebpfTracker eventTracker reverseResolver *reverseResolver - processCache *process.CachingWalker +} + +func newProcfsConnectionTracker(conf connectionTrackerConfig) connectionTracker { + if conf.WalkProc && conf.Scanner == nil { + conf.Scanner = procspy.NewConnectionScanner(conf.ProcessCache) + } + return connectionTracker{ + conf: conf, + flowWalker: newConntrackFlowWalker(conf.UseConntrack, conf.ProcRoot, conf.BufferSize, "--any-nat"), + ebpfTracker: nil, + reverseResolver: newReverseResolver(), + } } func newConnectionTracker(conf connectionTrackerConfig) connectionTracker { if !conf.UseEbpfConn { - // ebpf OFF, use flowWalker - return connectionTracker{ - conf: conf, - flowWalker: newConntrackFlowWalker(conf.UseConntrack, conf.ProcRoot, conf.BufferSize, "--any-nat"), - ebpfTracker: nil, - reverseResolver: newReverseResolver(), - } + // ebpf off, use conntrack for connection tracking + return newProcfsConnectionTracker(conf) } - // When ebpf will be active by default, check if it starts correctly otherwise fallback to flowWalk et, err := newEbpfTracker() if err != nil { - // TODO: fallback to flowWalker, when ebpf is enabled by default - log.Errorf("Error setting up the ebpfTracker, connections will not be reported: %s", err) - noopConnectionTracker := connectionTracker{ - conf: conf, - flowWalker: nil, - ebpfTracker: nil, - reverseResolver: nil, - } - return noopConnectionTracker + // ebpf failed, fallback to conntrack for connection tracking + log.Warnf("Error setting up the eBPF tracker: %v", err) + log.Warnf("Fallback to proc scanning") + return newProcfsConnectionTracker(conf) } - - var processCache *process.CachingWalker - processCache = process.NewCachingWalker(process.NewWalker(conf.ProcRoot)) - processCache.Tick() - ct := connectionTracker{ conf: conf, flowWalker: nil, ebpfTracker: et, reverseResolver: newReverseResolver(), - processCache: processCache, } go ct.getInitialState() return ct @@ -89,8 +84,7 @@ func flowToTuple(f flow) (ft fourTuple) { return ft } -// ReportConnections calls trackers accordingly to the configuration. -// When ebpf is enabled, only performEbpfTrack() is called +// ReportConnections calls trackers according to the configuration. func (t *connectionTracker) ReportConnections(rpt *report.Report) { hostNodeID := report.MakeHostNodeID(t.conf.HostID) @@ -164,9 +158,14 @@ func (t *connectionTracker) performWalkProc(rpt *report.Report, hostNodeID strin return nil } +// getInitialState runs conntrack and proc parsing synchronously only +// once to initialize ebpfTracker func (t *connectionTracker) getInitialState() { - scanner := procspy.NewSyncConnectionScanner(t.processCache) - // Run conntrack and proc parsing synchronously only once to initialize ebpfTracker + var processCache *process.CachingWalker + processCache = process.NewCachingWalker(process.NewWalker(t.conf.ProcRoot)) + processCache.Tick() + + scanner := procspy.NewSyncConnectionScanner(processCache) seenTuples := map[string]fourTuple{} // Consult the flowWalker to get the initial state if err := IsConntrackSupported(t.conf.ProcRoot); t.conf.UseConntrack && err != nil { diff --git a/probe/endpoint/reporter.go b/probe/endpoint/reporter.go index d627208cb6..87251cc13d 100644 --- a/probe/endpoint/reporter.go +++ b/probe/endpoint/reporter.go @@ -5,6 +5,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/weaveworks/scope/probe/endpoint/procspy" + "github.com/weaveworks/scope/probe/process" "github.com/weaveworks/scope/report" ) @@ -29,6 +30,7 @@ type ReporterConfig struct { UseEbpfConn bool ProcRoot string BufferSize int + ProcessCache *process.CachingWalker Scanner procspy.ConnectionScanner DNSSnooper *DNSSnooper } @@ -69,6 +71,7 @@ func NewReporter(conf ReporterConfig) *Reporter { UseEbpfConn: conf.UseEbpfConn, ProcRoot: conf.ProcRoot, BufferSize: conf.BufferSize, + ProcessCache: conf.ProcessCache, Scanner: conf.Scanner, DNSSnooper: conf.DNSSnooper, }), diff --git a/prog/probe.go b/prog/probe.go index cb74cf70c1..4a2d430d36 100644 --- a/prog/probe.go +++ b/prog/probe.go @@ -27,7 +27,6 @@ import ( "github.com/weaveworks/scope/probe/controls" "github.com/weaveworks/scope/probe/docker" "github.com/weaveworks/scope/probe/endpoint" - "github.com/weaveworks/scope/probe/endpoint/procspy" "github.com/weaveworks/scope/probe/host" "github.com/weaveworks/scope/probe/kubernetes" "github.com/weaveworks/scope/probe/overlay" @@ -158,13 +157,8 @@ func probeMain(flags probeFlags, targets []appclient.Target) { p.AddTagger(probe.NewTopologyTagger(), host.NewTagger(hostID)) var processCache *process.CachingWalker - var scanner procspy.ConnectionScanner if flags.procEnabled { processCache = process.NewCachingWalker(process.NewWalker(flags.procRoot)) - // The eBPF tracker finds connections itself and does not need the connection scanner - if !flags.useEbpfConn { - scanner = procspy.NewConnectionScanner(processCache) - } p.AddTicker(processCache) p.AddReporter(process.NewReporter(processCache, hostID, process.GetDeltaTotalJiffies, flags.noCommandLineArguments)) } @@ -185,7 +179,7 @@ func probeMain(flags probeFlags, targets []appclient.Target) { UseEbpfConn: flags.useEbpfConn, ProcRoot: flags.procRoot, BufferSize: flags.conntrackBufferSize, - Scanner: scanner, + ProcessCache: processCache, DNSSnooper: dnsSnooper, }) defer endpointReporter.Stop()