Skip to content

Commit 9ae707a

Browse files
committed
Optimise map and correct delta type
fix
1 parent 7d08f5b commit 9ae707a

6 files changed

Lines changed: 50 additions & 37 deletions

File tree

pkg/security/ebpf/c/include/maps.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ BPF_LRU_MAP(dns_responses_sent_to_userspace, u16, struct dns_responses_sent_to_u
9898
BPF_LRU_MAP(capabilities_usage, struct capabilities_usage_key_t, struct capabilities_usage_entry_t, 1) // max entries will be overridden at runtime
9999
BPF_LRU_MAP(sock_cookie_pid, u64, u32, 1); // max entries will be overridden at runtime
100100
BPF_LRU_MAP(memfd_tracking, struct memfd_key_t, u32, 1024)
101-
BPF_LRU_MAP(dropped_packets, u64, u64, 512)
102101

103102
BPF_LRU_MAP_FLAGS(tasks_in_coredump, u64, u8, 64, BPF_F_NO_COMMON_LRU)
104103
BPF_LRU_MAP_FLAGS(syscalls, u64, struct syscall_cache_t, 1, BPF_F_NO_COMMON_LRU) // max entries will be overridden at runtime
@@ -140,6 +139,7 @@ BPF_PERCPU_ARRAY_MAP(raw_packet_enabled, u32, 1)
140139
BPF_PERCPU_ARRAY_MAP(sysctl_event_gen, struct sysctl_event_t, 1)
141140
BPF_PERCPU_ARRAY_MAP(on_demand_event_gen, struct on_demand_event_t, 1)
142141
BPF_PERCPU_ARRAY_MAP(setsockopt_event, struct setsockopt_event_t, 1)
142+
BPF_PERCPU_ARRAY_MAP(dropped_packets, u32, 256)
143143

144144
BPF_PROG_ARRAY(args_envs_progs, 3)
145145
BPF_PROG_ARRAY(dentry_resolver_kprobe_or_fentry_callbacks, EVENT_MAX)

pkg/security/ebpf/probes/rawpacket/bpffilter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const (
3838
)
3939

4040
// MaxDropActionFilters is the maximum number of network drop action filters tracked in kernel.
41-
const MaxDropActionFilters = 512
41+
const MaxDropActionFilters = 256
4242

4343
// ToTCAct converts a policy to a TCAct
4444
func (p Policy) ToTCAct() TCAct {

pkg/security/ebpf/probes/rawpacket/pcap.go

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ const (
4141
structRawPacketEventDataSize = 256
4242

4343
dropStatsKeyStackOffset = int16(-8)
44-
dropStatsValStackOffset = int16(-16)
4544
)
4645

4746
// ProgOpts defines options
@@ -109,38 +108,25 @@ func (opts *ProgOpts) WithDropStatsMapFd(fd int) *ProgOpts {
109108

110109
func dropStatsIncrementInsts(filterIndex int, dropStatsMapFd int, nextLabel string) asm.Instructions {
111110
incLabel := fmt.Sprintf("inc_drop_stat_%d", filterIndex)
112-
initLabel := fmt.Sprintf("init_drop_stat_%d", filterIndex)
113111

114112
return asm.Instructions{
115113
// Put the key on the stack
116114
asm.Mov.Reg(asm.R1, asm.RFP).WithSymbol(incLabel),
117115
asm.Add.Imm(asm.R1, int32(dropStatsKeyStackOffset)),
118116
asm.Mov.Imm(asm.R2, int32(filterIndex)),
119-
asm.StoreMem(asm.R1, 0, asm.R2, asm.DWord),
117+
asm.StoreMem(asm.R1, 0, asm.R2, asm.Word),
120118
// Lookup in the map
121119
asm.LoadMapPtr(asm.R1, dropStatsMapFd),
122120
asm.Mov.Reg(asm.R2, asm.RFP),
123121
asm.Add.Imm(asm.R2, int32(dropStatsKeyStackOffset)),
124122
asm.FnMapLookupElem.Call(),
125-
asm.JEq.Imm(asm.R0, 0, initLabel),
126-
// Increment if it exists
123+
// should never happen
124+
asm.JEq.Imm(asm.R0, 0, nextLabel),
125+
// Increment
127126
asm.Mov.Reg(asm.R5, asm.R0),
128-
asm.LoadMem(asm.R6, asm.R5, 0, asm.DWord),
127+
asm.LoadMem(asm.R6, asm.R5, 0, asm.Word),
129128
asm.Add.Imm(asm.R6, 1),
130-
asm.StoreMem(asm.R5, 0, asm.R6, asm.DWord),
131-
asm.Ja.Label(nextLabel),
132-
// Otherwise create the key and insert it
133-
asm.Mov.Reg(asm.R3, asm.RFP).WithSymbol(initLabel),
134-
asm.Add.Imm(asm.R3, int32(dropStatsValStackOffset)),
135-
asm.Mov.Imm(asm.R4, 1),
136-
asm.StoreMem(asm.R3, 0, asm.R4, asm.DWord),
137-
asm.LoadMapPtr(asm.R1, dropStatsMapFd),
138-
asm.Mov.Reg(asm.R2, asm.RFP),
139-
asm.Add.Imm(asm.R2, int32(dropStatsKeyStackOffset)),
140-
asm.Mov.Reg(asm.R3, asm.RFP),
141-
asm.Add.Imm(asm.R3, int32(dropStatsValStackOffset)),
142-
asm.Mov.Imm(asm.R4, 0),
143-
asm.FnMapUpdateElem.Call(),
129+
asm.StoreMem(asm.R5, 0, asm.R6, asm.Word),
144130
asm.Ja.Label(nextLabel),
145131
}
146132
}
@@ -270,6 +256,10 @@ func filtersToProgs(filters []Filter, opts ProgOpts, headerInsts, footerInsts as
270256
)
271257

272258
for i, filter := range filters {
259+
if i >= MaxDropActionFilters {
260+
mErr = multierror.Append(mErr, fmt.Errorf("too many filters, stop adding filters, max is %d", MaxDropActionFilters))
261+
break
262+
}
273263
filterInsts, err := FilterToInsts(i, filter, opts)
274264
if err != nil {
275265
mErr = multierror.Append(mErr, fmt.Errorf("unable to generate eBPF bytecode for rule `%s`: %s", filter.RuleID, err))

pkg/security/probe/monitors/rawpacketdrop/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ go_library(
1010
"//pkg/security/metrics",
1111
"//pkg/security/probe/managerhelper",
1212
"//pkg/security/seclog",
13+
"//pkg/security/utils",
1314
"@com_github_cilium_ebpf//:ebpf",
1415
"@com_github_datadog_datadog_go_v5//statsd",
1516
"@com_github_datadog_ebpf_manager//:ebpf-manager",
@@ -18,6 +19,7 @@ go_library(
1819
"//pkg/security/metrics",
1920
"//pkg/security/probe/managerhelper",
2021
"//pkg/security/seclog",
22+
"//pkg/security/utils",
2123
"@com_github_cilium_ebpf//:ebpf",
2224
"@com_github_datadog_datadog_go_v5//statsd",
2325
"@com_github_datadog_ebpf_manager//:ebpf-manager",

pkg/security/probe/monitors/rawpacketdrop/rawpacketdrop_monitor.go

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ package rawpacketdrop
1010

1111
import (
1212
"fmt"
13+
"sync"
1314

1415
manager "github.com/DataDog/ebpf-manager"
1516
lib "github.com/cilium/ebpf"
@@ -19,6 +20,7 @@ import (
1920
"github.com/DataDog/datadog-agent/pkg/security/metrics"
2021
"github.com/DataDog/datadog-agent/pkg/security/probe/managerhelper"
2122
"github.com/DataDog/datadog-agent/pkg/security/seclog"
23+
"github.com/DataDog/datadog-agent/pkg/security/utils"
2224
)
2325

2426
// RuleIDsProvider returns the current filter index to rule_id mapping.
@@ -30,6 +32,8 @@ type Monitor struct {
3032
droppedMap *lib.Map
3133
ruleIDs RuleIDsProvider
3234
lastCounts map[string]uint64
35+
mu sync.Mutex
36+
numCPU int
3337
}
3438

3539
// NewMonitor returns a new Monitor.
@@ -38,48 +42,67 @@ func NewMonitor(manager *manager.Manager, statsdClient statsd.ClientInterface, r
3842
if err != nil {
3943
return nil, err
4044
}
45+
numCPU, err := utils.NumCPU()
46+
if err != nil {
47+
return nil, fmt.Errorf("couldn't fetch the host CPU count: %w", err)
48+
}
4149

4250
return &Monitor{
4351
statsdClient: statsdClient,
4452
droppedMap: droppedMap,
4553
ruleIDs: ruleIDs,
4654
lastCounts: make(map[string]uint64),
55+
numCPU: numCPU,
4756
}, nil
4857
}
4958

5059
// ResetCounters clears user-space counters after the kernel map is reset.
5160
func (m *Monitor) ResetCounters() {
61+
m.mu.Lock()
62+
defer m.mu.Unlock()
5263
m.lastCounts = make(map[string]uint64)
5364
}
5465

5566
// SendStats emits deltas from the kernel dropped_packets map grouped by rule_id.
5667
func (m *Monitor) SendStats() error {
68+
m.mu.Lock()
69+
defer m.mu.Unlock()
70+
5771
// get the up to date corresponding rule IDs for each filter
5872
ruleIDs := m.ruleIDs()
5973
if len(ruleIDs) == 0 {
6074
m.lastCounts = make(map[string]uint64)
6175
return nil
6276
}
63-
6477
currentCounts := make(map[string]uint64, len(ruleIDs))
65-
iterator := m.droppedMap.Iterate()
6678

67-
var filterIndex uint64
79+
perCPU := make([]uint32, m.numCPU)
80+
6881
var count uint64
69-
for iterator.Next(&filterIndex, &count) {
70-
ruleID, ok := ruleIDs[uint32(filterIndex)]
71-
if !ok || ruleID == "" {
82+
// get the current counts from the kernel map
83+
for filterIndex, ruleID := range ruleIDs {
84+
if ruleID == "" {
85+
continue
86+
}
87+
if err := m.droppedMap.Lookup(filterIndex, &perCPU); err != nil {
88+
seclog.Warnf("failed to lookup dropped_packets map: %s", err)
7289
continue
7390
}
91+
count = 0
92+
for _, value := range perCPU {
93+
count += uint64(value)
94+
}
7495
currentCounts[ruleID] += count
7596
}
97+
7698
for ruleID, count := range currentCounts {
7799
last := m.lastCounts[ruleID]
78-
delta := count - last
79-
if delta < 0 {
80-
seclog.Errorf("incorrect mapping leading to a negative delta for rule_id %s: %d", ruleID, delta)
100+
101+
if count < last {
102+
seclog.Errorf("incorrect mapping leading to a negative delta for rule_id %s", ruleID)
81103
continue
82104
}
105+
delta := count - last
83106
if delta == 0 {
84107
continue
85108
}

pkg/security/probe/probe_ebpf.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ func (p *EBPFProbe) rebuildDropActionRuleIDs() {
852852
ruleIDs := make(map[uint32]string, len(p.rawPacketActionFilters))
853853
for i, filter := range p.rawPacketActionFilters {
854854
if i >= rawpacket.MaxDropActionFilters {
855-
seclog.Errorf("too many drop action filters, indexes might be incorrect because of the kernel LRU, max is %d", rawpacket.MaxDropActionFilters)
855+
seclog.Errorf("too many drop action filters, stop adding them is ruleID mapping, max is %d", rawpacket.MaxDropActionFilters)
856856
break
857857
}
858858
ruleIDs[uint32(i)] = string(filter.RuleID)
@@ -876,11 +876,9 @@ func (p *EBPFProbe) getDropActionRuleIDs() map[uint32]string {
876876
}
877877

878878
func (p *EBPFProbe) clearDroppedPacketsMap(droppedPacketsMap *lib.Map) {
879-
iterator := droppedPacketsMap.Iterate()
880-
var key uint64
881-
var value uint64
882-
for iterator.Next(&key, &value) {
883-
_ = droppedPacketsMap.Delete(key)
879+
zero := make([]uint32, p.numCPU)
880+
for i := uint32(0); i < rawpacket.MaxDropActionFilters; i++ {
881+
_ = droppedPacketsMap.Put(i, zero)
884882
}
885883
}
886884

0 commit comments

Comments
 (0)