Skip to content
Merged
Show file tree
Hide file tree
Changes from 67 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
49bed8e
initial commit
hmahmood May 16, 2024
4464eac
iterate
hmahmood May 29, 2024
fca1a1e
Fix lint errors
hmahmood Jun 5, 2024
f75cb82
Add kernel.IsEbpfSupported
hmahmood Jun 5, 2024
059cbef
Rename config
hmahmood Jun 5, 2024
2e56ffe
Add IsEbpfSupported
hmahmood Jun 6, 2024
c2a3d78
Override when ebpfless config is enabled
hmahmood Jun 6, 2024
3959fe9
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jun 6, 2024
39853f1
Update go.mod
hmahmood Jun 6, 2024
90637ce
Remove fargate requirement
hmahmood Jun 6, 2024
753fe21
Fix dns test
hmahmood Jun 6, 2024
6a92446
Fix build
hmahmood Jun 6, 2024
8d5952e
Fix lint
hmahmood Jun 6, 2024
3851ef0
Remove ebpf check
hmahmood Jun 7, 2024
d881f84
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jun 10, 2024
de0b4a1
update go.sum
hmahmood Jun 10, 2024
41d1606
Don't check for tracefs on ebpfless
hmahmood Jun 10, 2024
856ac78
Check module NeedsEBPF function to skip ebpf checks
hmahmood Jun 11, 2024
7e3ec04
Disable configs for ebpf-less
hmahmood Jun 12, 2024
81d931a
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jun 26, 2024
42e758f
Fix merge
hmahmood Jun 26, 2024
de3545f
Disable tests for ebpfless
hmahmood Jun 26, 2024
ce374c6
Update gopacket
hmahmood Jun 26, 2024
497aff8
Fix typo
hmahmood Jun 26, 2024
361d783
Fix lint
hmahmood Jun 26, 2024
72ad33a
Fix go.sum
hmahmood Jun 27, 2024
8326634
Fix windows
hmahmood Jun 27, 2024
2cd3aaa
Rename network_config.enable_ebpf_less to network_config.enable_ebpfless
hmahmood Jun 27, 2024
e1258c9
Fix windows
hmahmood Jun 27, 2024
4e502e6
Fix netlink conntracker loading to check for NET_ADMIN permissions
hmahmood Jun 27, 2024
31f27a6
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jun 27, 2024
08c06aa
Remove old comment
hmahmood Jun 27, 2024
b69ef5a
Remove empty file
hmahmood Jun 27, 2024
d985ac6
Fix lint
hmahmood Jun 27, 2024
64fcc03
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jul 8, 2024
0e39567
Review comments
hmahmood Jul 9, 2024
7ff5a97
Move check for USM support into IsUSMSupported
hmahmood Jul 15, 2024
93fa333
Fix Dockefile
hmahmood Jul 15, 2024
6dc8d7d
Rename IsUSMSupported to CheckUSMSupported
hmahmood Jul 15, 2024
1f504c4
Lint
hmahmood Jul 15, 2024
61dec8d
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jul 15, 2024
c014ee7
Update go.sum
hmahmood Jul 15, 2024
bae0798
Move check for tracefs to newEbpfTracer
hmahmood Jul 16, 2024
5a10f17
Review comments
hmahmood Jul 16, 2024
907b44d
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jul 16, 2024
b4efeb5
Adding reason for disabling configs
hmahmood Jul 16, 2024
8c72538
Update go.sum
hmahmood Jul 16, 2024
398e8d8
Remove http configs from disable code
hmahmood Jul 18, 2024
ba54c03
Fix compile error
hmahmood Jul 18, 2024
7297f4b
Fix lint
hmahmood Jul 23, 2024
cfa736d
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jul 23, 2024
714bf2d
Update go.sum
hmahmood Jul 23, 2024
a97b0af
Review comments
hmahmood Jul 25, 2024
c466fbb
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jul 25, 2024
15e587e
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Jul 30, 2024
4819981
Update go.sum
hmahmood Jul 30, 2024
0502fb9
Move linux only test functions
hmahmood Jul 30, 2024
ab537d4
Add PacketInfo for each packet reported
hmahmood Jul 31, 2024
14b6ee9
Fix windows
hmahmood Aug 1, 2024
21e40e3
Review comments
hmahmood Aug 1, 2024
e002855
Return error from SetEbpf on reflect failures
hmahmood Aug 5, 2024
0621be0
Review comments
hmahmood Aug 5, 2024
75bab0b
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Aug 5, 2024
b0030e8
Removed unused code
hmahmood Aug 7, 2024
ac937f7
Review comments
hmahmood Aug 8, 2024
f6e3146
Fix typo
hmahmood Aug 9, 2024
ef365aa
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Aug 9, 2024
bce4868
Remove Layers object
hmahmood Aug 13, 2024
6844568
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Aug 13, 2024
eae3003
Add comments
hmahmood Aug 14, 2024
e533dd0
Fix build
hmahmood Aug 19, 2024
1a216d4
Merge remote-tracking branch 'origin/main' into hasan.mahmood/ebpfles…
hmahmood Aug 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions cmd/system-probe/config/adjust_npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const (
)

func adjustNetwork(cfg config.Config) {
ebpflessEnabled := cfg.GetBool(netNS("enable_ebpfless"))

limitMaxInt(cfg, spNS("max_conns_per_message"), maxConnsMessageBatchSize)

if cfg.GetBool(spNS("disable_tcp")) {
Expand Down Expand Up @@ -99,4 +101,24 @@ func adjustNetwork(cfg config.Config) {
log.Warn("disabling NPM connection rollups since USM connection rollups are not enabled")
cfg.Set(netNS("enable_connection_rollup"), false, model.SourceAgentRuntime)
}

// disable features that are not supported on certain
// configs/platforms
var disableConfigs []struct {
key, reason string
}
if ebpflessEnabled {
const notSupportedEbpfless = "not supported when ebpf-less is enabled"
disableConfigs = append(disableConfigs, []struct{ key, reason string }{
{netNS("enable_protocol_classification"), notSupportedEbpfless},
{evNS("network_process", "enabled"), notSupportedEbpfless}}...,
)
}

for _, c := range disableConfigs {
if cfg.GetBool(c.key) {
log.Warnf("disabling %s: %s", c.key, c.reason)
cfg.Set(c.key, false, model.SourceAgentRuntime)
}
}
}
5 changes: 2 additions & 3 deletions cmd/system-probe/modules/network_tracer_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@ package modules
import (
"github.com/DataDog/datadog-agent/cmd/system-probe/api/module"
"github.com/DataDog/datadog-agent/cmd/system-probe/config"
"github.com/DataDog/datadog-agent/pkg/network/tracer"
)

// NetworkTracer is a factory for NPM's tracer
var NetworkTracer = module.Factory{
Name: config.NetworkTracerModule,
ConfigNamespaces: networkTracerModuleConfigNamespaces,
Fn: createNetworkTracerModule,
NeedsEBPF: func() bool {
return true
},
NeedsEBPF: tracer.NeedsEBPF,
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -1075,3 +1075,5 @@ replace (

// Prevent a false-positive detection by the Google and Ikarus security vendors on VirusTotal
exclude go.opentelemetry.io/proto/otlp v1.1.0

replace github.com/google/gopacket v1.1.19 => github.com/DataDog/gopacket v0.0.0-20240626205202-4ac4cee31f14
5 changes: 3 additions & 2 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pkg/config/setup/system_probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ func InitSystemProbeConfig(cfg pkgconfigmodel.Config) {
// connection aggregation with port rollups
cfg.BindEnvAndSetDefault(join(netNS, "enable_connection_rollup"), false)

cfg.BindEnvAndSetDefault(join(netNS, "enable_ebpfless"), false)

// windows config
cfg.BindEnvAndSetDefault(join(spNS, "windows.enable_monotonic_count"), false)

Expand Down
19 changes: 19 additions & 0 deletions pkg/ebpf/ebpftest/buildmode.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ var (
RuntimeCompiled BuildMode
CORE BuildMode
Fentry BuildMode
Ebpfless BuildMode
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we should dedicate some time to the build modes. I don't think it's a blocker for this PR considering it's a PoC and the ebpfless mode isn't enabled by default (wdyt @brycekahle?), but we could probably find a way to reconciliate the actual eBPF build modes (prebuild/runtime/CORE) with fentry and ebpfless which are not something we'll want in the rest of test code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ebpfless feels OK because it is mutually exclusive from prebuilt/rc/co-re. fentry is the confusing one, because that could be any of the build modes.


func init() {
Prebuilt = prebuilt{}
RuntimeCompiled = runtimeCompiled{}
CORE = core{}
Fentry = fentry{}
Ebpfless = ebpfless{}
}

// BuildMode is an eBPF build mode
Expand Down Expand Up @@ -95,6 +97,23 @@ func (f fentry) Env() map[string]string {
}
}

type ebpfless struct{}

func (e ebpfless) String() string {
return "eBPFless"
}

func (e ebpfless) Env() map[string]string {
return map[string]string{
"NETWORK_TRACER_FENTRY_TESTS": "false",
"DD_ENABLE_RUNTIME_COMPILER": "false",
"DD_ENABLE_CO_RE": "false",
"DD_ALLOW_RUNTIME_COMPILED_FALLBACK": "false",
"DD_ALLOW_PRECOMPILED_FALLBACK": "false",
"DD_NETWORK_CONFIG_ENABLE_EBPFLESS": "true",
}
}

// GetBuildMode returns which build mode the current environment matches, if any
func GetBuildMode() BuildMode {
for _, mode := range []BuildMode{Prebuilt, RuntimeCompiled, CORE, Fentry} {
Expand Down
4 changes: 4 additions & 0 deletions pkg/ebpf/ebpftest/buildmode_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func SupportedBuildModes() []BuildMode {
(runtime.GOARCH == "amd64" && (hostPlatform == "amazon" || hostPlatform == "amzn") && kv.Major() == 5 && kv.Minor() == 10) {
modes = append(modes, Fentry)
}
if os.Getenv("TEST_EBPFLESS_OVERRIDE") == "true" {
modes = append(modes, Ebpfless)
}

return modes
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/network/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ type Config struct {
// buffers (>=5.8) will result in forcing the use of Perf Maps instead.
EnableUSMRingBuffers bool

EnableEbpfless bool

// EnableUSMEventStream enables USM to use the event stream instead
// of netlink for receiving process events.
EnableUSMEventStream bool
Expand Down Expand Up @@ -406,6 +408,8 @@ func New() *Config {

EnableNPMConnectionRollup: cfg.GetBool(join(netNS, "enable_connection_rollup")),

EnableEbpfless: cfg.GetBool(join(netNS, "enable_ebpfless")),

// Service Monitoring
EnableJavaTLSSupport: cfg.GetBool(join(smjtNS, "enabled")),
JavaAgentDebug: cfg.GetBool(join(smjtNS, "debug")),
Expand Down
5 changes: 3 additions & 2 deletions pkg/network/dns/driver_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"github.com/DataDog/datadog-agent/comp/core/telemetry"
"github.com/DataDog/datadog-agent/pkg/network/driver"
"github.com/DataDog/datadog-agent/pkg/network/filter"
)

const (
Expand Down Expand Up @@ -99,7 +100,7 @@ func (d *dnsDriver) SetDataFilters(filters []driver.FilterDefinition) error {
}

// ReadDNSPacket visits a raw DNS packet if one is available.
func (d *dnsDriver) ReadDNSPacket(visit func([]byte, time.Time) error) (didRead bool, err error) {
func (d *dnsDriver) ReadDNSPacket(visit func(data []byte, info filter.PacketInfo, t time.Time) error) (didRead bool, err error) {
var bytesRead uint32
var key uintptr // returned by GetQueuedCompletionStatus, then ignored
var ol *windows.Overlapped
Expand All @@ -125,7 +126,7 @@ func (d *dnsDriver) ReadDNSPacket(visit func([]byte, time.Time) error) (didRead

start := driver.FilterPacketHeaderSize

if err := visit(buf.data[start:], captureTime); err != nil {
if err := visit(buf.data[start:], nil, captureTime); err != nil {
return false, err
}

Expand Down
60 changes: 31 additions & 29 deletions pkg/network/dns/monitor_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,14 @@ import (
"fmt"
"math"

"golang.org/x/net/bpf"

"github.com/vishvananda/netns"

manager "github.com/DataDog/ebpf-manager"
"github.com/vishvananda/netns"

"github.com/DataDog/datadog-agent/comp/core/telemetry"
ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf"
"github.com/DataDog/datadog-agent/pkg/network/config"
"github.com/DataDog/datadog-agent/pkg/network/ebpf/probes"
filterpkg "github.com/DataDog/datadog-agent/pkg/network/filter"
"github.com/DataDog/datadog-agent/pkg/network/filter"
"github.com/DataDog/datadog-agent/pkg/util/kernel"
"github.com/DataDog/datadog-agent/pkg/util/log"
)
Expand All @@ -33,6 +30,26 @@ type dnsMonitor struct {

// NewReverseDNS starts snooping on DNS traffic to allow IP -> domain reverse resolution
func NewReverseDNS(cfg *config.Config, _ telemetry.Component) (ReverseDNS, error) {
// Create the RAW_SOCKET inside the root network namespace
var (
packetSrc *filter.AFPacketSource
srcErr error
ns netns.NsHandle
)
ns, err := cfg.GetRootNetNs()
if err != nil {
return nil, err
}
defer ns.Close()

err = kernel.WithNS(ns, func() error {
packetSrc, srcErr = filter.NewAFPacketSource(4 << 20) // 4 MB total
return srcErr
})
if err != nil {
return nil, err
}

currKernelVersion, err := kernel.HostVersion()
if err != nil {
// if the platform couldn't be determined, treat it as new kernel case
Expand All @@ -42,12 +59,11 @@ func NewReverseDNS(cfg *config.Config, _ telemetry.Component) (ReverseDNS, error
pre410Kernel := currKernelVersion < kernel.VersionCode(4, 1, 0)

var p *ebpfProgram
var filter *manager.Probe
var bpfFilter []bpf.RawInstruction
if pre410Kernel {
bpfFilter, err = generateBPFFilter(cfg)
if err != nil {
if pre410Kernel || cfg.EnableEbpfless {
if bpfFilter, err := generateBPFFilter(cfg); err != nil {
return nil, fmt.Errorf("error creating bpf classic filter: %w", err)
} else if err = packetSrc.SetBPF(bpfFilter); err != nil {
return nil, fmt.Errorf("could not set BPF filter on packet source: %w", err)
}
} else {
p, err = newEBPFProgram(cfg)
Expand All @@ -59,35 +75,21 @@ func NewReverseDNS(cfg *config.Config, _ telemetry.Component) (ReverseDNS, error
return nil, fmt.Errorf("error initializing ebpf programs: %w", err)
}

filter, _ = p.GetProbe(manager.ProbeIdentificationPair{EBPFFuncName: probes.SocketDNSFilter, UID: probeUID})
filter, _ := p.GetProbe(manager.ProbeIdentificationPair{EBPFFuncName: probes.SocketDNSFilter, UID: probeUID})
if filter == nil {
return nil, fmt.Errorf("error retrieving socket filter")
}
}

// Create the RAW_SOCKET inside the root network namespace
var (
packetSrc *filterpkg.AFPacketSource
srcErr error
ns netns.NsHandle
)
if ns, err = cfg.GetRootNetNs(); err != nil {
return nil, err
}
defer ns.Close()

err = kernel.WithNS(ns, func() error {
packetSrc, srcErr = filterpkg.NewPacketSource(filter, bpfFilter)
return srcErr
})
if err != nil {
return nil, err
if err = packetSrc.SetEbpf(filter); err != nil {
return nil, fmt.Errorf("could not set file descriptor for eBPF program: %w", err)
}
}

snoop, err := newSocketFilterSnooper(cfg, packetSrc)
if err != nil {
return nil, err
}

return &dnsMonitor{
snoop,
p,
Expand Down
9 changes: 5 additions & 4 deletions pkg/network/dns/packet_source_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,25 @@ import (
"github.com/google/gopacket/layers"

"github.com/DataDog/datadog-agent/comp/core/telemetry"
"github.com/DataDog/datadog-agent/pkg/network/filter"
)

var _ packetSource = &windowsPacketSource{}
var _ filter.PacketSource = &windowsPacketSource{}

type windowsPacketSource struct {
di *dnsDriver
}

// newWindowsPacketSource constructs a new packet source
func newWindowsPacketSource(telemetrycomp telemetry.Component) (packetSource, error) {
func newWindowsPacketSource(telemetrycomp telemetry.Component) (filter.PacketSource, error) {
di, err := newDriver(telemetrycomp)
if err != nil {
return nil, err
}
return &windowsPacketSource{di: di}, nil
}

func (p *windowsPacketSource) VisitPackets(exit <-chan struct{}, visit func([]byte, time.Time) error) error {
func (p *windowsPacketSource) VisitPackets(exit <-chan struct{}, visit func([]byte, filter.PacketInfo, time.Time) error) error {
for {
didReadPacket, err := p.di.ReadDNSPacket(visit)
if err != nil {
Expand All @@ -50,7 +51,7 @@ func (p *windowsPacketSource) VisitPackets(exit <-chan struct{}, visit func([]by
}
}

func (p *windowsPacketSource) PacketType() gopacket.LayerType {
func (p *windowsPacketSource) LayerType() gopacket.LayerType {
return layers.LayerTypeIPv4
}

Expand Down
27 changes: 5 additions & 22 deletions pkg/network/dns/snooper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import (
"sync"
"time"

"github.com/google/gopacket"

"github.com/DataDog/datadog-agent/pkg/network/config"
"github.com/DataDog/datadog-agent/pkg/network/filter"
"github.com/DataDog/datadog-agent/pkg/process/util"
"github.com/DataDog/datadog-agent/pkg/telemetry"
"github.com/DataDog/datadog-agent/pkg/util/log"
Expand Down Expand Up @@ -45,7 +44,7 @@ var _ ReverseDNS = &socketFilterSnooper{}

// socketFilterSnooper is a DNS traffic snooper built on top of an eBPF SOCKET_FILTER
type socketFilterSnooper struct {
source packetSource
source filter.PacketSource
parser *dnsParser
cache *reverseDNSCache
statKeeper *dnsStatKeeper
Expand All @@ -62,24 +61,8 @@ func (s *socketFilterSnooper) WaitForDomain(domain string) error {
return s.statKeeper.WaitForDomain(domain)
}

// packetSource reads raw packet data
type packetSource interface {
// VisitPackets reads all new raw packets that are available, invoking the given callback for each packet.
// If no packet is available, VisitPacket returns immediately.
// The format of the packet is dependent on the implementation of packetSource -- i.e. it may be an ethernet frame, or a IP frame.
// The data buffer is reused between invocations of VisitPacket and thus should not be pointed to.
// If the cancel channel is closed, VisitPackets will stop reading.
VisitPackets(cancel <-chan struct{}, visitor func(data []byte, timestamp time.Time) error) error

// PacketType returns the type of packet this source reads
PacketType() gopacket.LayerType

// Close closes the packet source
Close()
}

// newSocketFilterSnooper returns a new socketFilterSnooper
func newSocketFilterSnooper(cfg *config.Config, source packetSource) (*socketFilterSnooper, error) {
func newSocketFilterSnooper(cfg *config.Config, source filter.PacketSource) (*socketFilterSnooper, error) {
cache := newReverseDNSCache(dnsCacheSize, dnsCacheExpirationPeriod)
var statKeeper *dnsStatKeeper
if cfg.CollectDNSStats {
Expand All @@ -93,7 +76,7 @@ func newSocketFilterSnooper(cfg *config.Config, source packetSource) (*socketFil
}
snooper := &socketFilterSnooper{
source: source,
parser: newDNSParser(source.PacketType(), cfg),
parser: newDNSParser(source.LayerType(), cfg),
cache: cache,
statKeeper: statKeeper,
translation: new(translation),
Expand Down Expand Up @@ -154,7 +137,7 @@ func (s *socketFilterSnooper) Close() {
// The *translation is recycled and re-used in subsequent calls and it should not be accessed concurrently.
// The second parameter `ts` is the time when the packet was captured off the wire. This is used for latency calculation
// and much more reliable than calling time.Now() at the user layer.
func (s *socketFilterSnooper) processPacket(data []byte, ts time.Time) error {
func (s *socketFilterSnooper) processPacket(data []byte, _ filter.PacketInfo, ts time.Time) error {
t := s.getCachedTranslation()
pktInfo := dnsPacketInfo{}

Expand Down
Loading