Skip to content

Commit 81db0fb

Browse files
authored
Merge pull request #3 from richiejp/cgroup
Add partial process tracking for CGroups
2 parents 4796e9f + 861e463 commit 81db0fb

9 files changed

+89
-4
lines changed

README.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ By default eBPF component uses **TC** (Traffic Control) eBPF hooks with TCX atta
1919

2020
Alternatively it can use **KProbes** to monitor TCP, UDP, ICMPv4 and ICMPv6 communication throughout all containers, K8s pods, translations and forwards and display process ID as well as process name, if the traffic was being sent or delivered to userspace application. KProbes traditionally work the slowest, being closest to the userspace -- but they bring sometimes useful process information. KProbes work also with much older Linux kernels as well, but the hard-dependancy is a [BTF-enabled](https://docs.ebpf.io/concepts/btf/) kernel.
2121

22-
In case that you need to monitor just a specific **CGroup**, it is possible as well and monitoring both ingress and egress traffic is supported.
23-
22+
In case that you need to monitor just a specific **CGroup**, it is possible as well and monitoring both ingress and egress traffic is supported. You can also monitor all traffic by attaching to the root CGroup (e.g. `/sys/fs/cgroup`). Process tracking is possible when using CGroups, but only for traffic where pktstat-bpf observed the socket creation.
2423
![Demo](demo.gif)
2524

2625
## Talk
@@ -50,7 +49,7 @@ The following table maps features, requirements and expected performance for des
5049
| Generic [PCAP](https://github.com/dkorunic/pktstat) | Yes | Yes | Low | No | Any | No |
5150
| [AF_PACKET](https://github.com/dkorunic/pktstat) | Yes | Yes | Medium | No | v2.2 | No |
5251
| KProbes | Yes | Yes | Medium+ | **Yes** | v4.1 | No |
53-
| CGroup (SKB) | Yes | Yes | Medium+ | No | v4.10 | No |
52+
| CGroup (SKB) | Yes | Yes | Medium+ | Partial | v4.10 | No |
5453
| TC (SchedACT) | Yes | Yes | **High** | No | v6.6 | No |
5554
| XDP Generic | Yes | **No** | **High** | No | v5.9 | No |
5655
| XDP Native | Yes | **No** | **Very high** | No | v5.9 | No |

counter.c

+35-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#define OK 1
4747
#define NOK 0
4848
#define ALLOW_PKT 1
49+
#define ALLOW_SK 1
4950

5051
// Map key struct for IP traffic
5152
typedef struct statkey_t {
@@ -72,6 +73,18 @@ struct {
7273
__type(value, statvalue);
7374
} pkt_count SEC(".maps");
7475

76+
typedef struct sockinfo_t {
77+
__u8 comm[TASK_COMM_LEN];
78+
pid_t pid;
79+
} sockinfo;
80+
81+
struct {
82+
__uint(type, BPF_MAP_TYPE_LRU_HASH);
83+
__uint(max_entries, MAX_ENTRIES);
84+
__type(key, __u64);
85+
__type(value, sockinfo);
86+
} sock_info SEC(".maps");
87+
7588
// IPv4-mapped IPv6 address prefix (for V4MAPPED conversion)
7689
static const __u8 ip4in6[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff};
7790

@@ -327,7 +340,13 @@ static inline void process_cgroup_skb(struct __sk_buff *skb) {
327340
return;
328341
}
329342

330-
// lookup value in hash
343+
__u64 cookie = bpf_get_socket_cookie(skb);
344+
sockinfo *ski = bpf_map_lookup_elem(&sock_info, &cookie);
345+
if (ski) {
346+
key.pid = ski->pid;
347+
__builtin_memcpy(key.comm, ski->comm, sizeof(key.comm));
348+
}
349+
331350
statvalue *val = (statvalue *)bpf_map_lookup_elem(&pkt_count, &key);
332351
if (val) {
333352
// atomic XADD, doesn't need bpf_spin_lock()
@@ -411,6 +430,21 @@ int tc_count_packets(struct __sk_buff *skb) {
411430
return TC_ACT_UNSPEC;
412431
}
413432

433+
SEC("cgroup/sock_create")
434+
int cgroup_sock_create(struct bpf_sock *sk) {
435+
__u64 cookie = bpf_get_socket_cookie(sk);
436+
sockinfo ski = {
437+
.pid = bpf_get_current_pid_tgid(),
438+
.comm = {0},
439+
};
440+
441+
bpf_get_current_comm(ski.comm, sizeof(ski.comm));
442+
443+
bpf_map_update_elem(&sock_info, &cookie, &ski, BPF_ANY);
444+
445+
return ALLOW_SK;
446+
}
447+
414448
SEC("cgroup_skb/ingress")
415449
int cgroup_skb_ingress(struct __sk_buff *skb) {
416450
process_cgroup_skb(skb);

counter_arm64_bpfel.go

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

counter_arm64_bpfel.o

18 KB
Binary file not shown.

counter_x86_bpfel.go

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

counter_x86_bpfel.o

17.8 KB
Binary file not shown.

main.go

+9
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,15 @@ func startCgroup(objs counterObjects, cgroupPath string, links []link.Link) []li
304304
log.Fatalf("Error checking CGroupSKB support: %v", err)
305305
}
306306

307+
l, err = link.AttachCgroup(link.CgroupOptions{
308+
Program: objs.CgroupSockCreate,
309+
Attach: ebpf.AttachCGroupInetSockCreate,
310+
Path: cgroupPath,
311+
})
312+
if err != nil {
313+
log.Fatalf("Error attaching CgroupSockCreate to %s: %v", cgroupPath, err)
314+
}
315+
307316
l, err = link.AttachCgroup(link.CgroupOptions{
308317
Program: objs.CgroupSkbIngress,
309318
Attach: ebpf.AttachCGroupInetIngress,

output.go

+10
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,16 @@ func outputPlain(m []statEntry) string {
186186
}
187187
}
188188

189+
if *useCGroup != "" {
190+
if v.Pid > 0 {
191+
sb.WriteString(fmt.Sprintf(", pid: %d", v.Pid))
192+
}
193+
194+
if v.Comm != "" {
195+
sb.WriteString(fmt.Sprintf(", comm: %v", v.Comm))
196+
}
197+
}
198+
189199
sb.WriteString("\n")
190200
}
191201

tui.go

+11
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ func drawTUI(objs counterObjects, startTime time.Time) {
9898
infoView := tview.NewTextView().
9999
SetTextColor(tcell.ColorYellow)
100100
switch {
101+
case *useCGroup != "":
102+
infoView.SetText("CGroup eBPF mode w/ partial PID and comm tracking")
101103
case *useKProbes:
102104
infoView.SetText("KProbes eBPF mode w/ PID and comm tracking")
103105
case *useXDP:
@@ -244,6 +246,15 @@ func updateStatsTable(app *tview.Application, table *tview.Table, tableSort *fun
244246
table.SetCell(i+1, 9, tview.NewTableCell(v.Comm).
245247
SetTextColor(tcell.ColorWhite).
246248
SetExpansion(1))
249+
} else if *useCGroup != "" && v.Pid > 0 && v.Comm != "" {
250+
table.SetCell(i+1, 8, tview.NewTableCell(strconv.FormatInt(int64(v.Pid), 10)).
251+
SetTextColor(tcell.ColorWhite).
252+
SetExpansion(1))
253+
254+
table.SetCell(i+1, 9, tview.NewTableCell(v.Comm).
255+
SetTextColor(tcell.ColorWhite).
256+
SetExpansion(1))
257+
247258
} else {
248259
table.SetCell(i+1, 8, tview.NewTableCell("").
249260
SetTextColor(tcell.ColorWhite).

0 commit comments

Comments
 (0)