Skip to content

Commit cf7db6f

Browse files
committed
netstacklat: Add option to groupby cgroup
Add the --groupby-cgroup option to collect and report data on a per-cgroup basis. Just like the -c/--cgroups option, this will only apply to probes in the process context, which is currently only tcp-socket-read and udp-socket-read. When reporting the data, print out the cgroup ID (inode number) directly instead of the cgroup path. As far as I can tell, the only way to resolve the ID into a path is the walk the entire cgroup mount (e.g. /sys/fs/cgroup) and stat each path to find the matching inode. Doing this every time the cgroup needs to be printed seems highly inefficient, and to create an efficient cache the most suitable data structure seems like a hashmap, which C lacks. Adding support for printing out the cgroup path would thus be a significant implementation effort for something we in the end primarily will rely on ebpf-exporter for anyways. Signed-off-by: Simon Sundberg <[email protected]>
1 parent d42cdc2 commit cf7db6f

File tree

4 files changed

+35
-7
lines changed

4 files changed

+35
-7
lines changed

netstacklat/netstacklat.bpf.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ volatile const struct netstacklat_bpf_config user_config = {
1919
.filter_ifindex = false,
2020
.filter_cgroup = false,
2121
.groupby_ifindex = false,
22+
.groupby_cgroup = false,
2223
};
2324

2425
/*
@@ -36,7 +37,7 @@ struct sk_buff___old {
3637

3738
struct {
3839
__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
39-
__uint(max_entries, HIST_NBUCKETS * NETSTACKLAT_N_HOOKS * 16);
40+
__uint(max_entries, HIST_NBUCKETS * NETSTACKLAT_N_HOOKS * 64);
4041
__type(key, struct hist_key);
4142
__type(value, u64);
4243
} netstack_latency_seconds SEC(".maps");
@@ -249,21 +250,18 @@ static bool filter_cgroup(u64 cgroup_id)
249250
return bpf_map_lookup_elem(&netstack_cgroupfilter, &cgroup_id) != NULL;
250251
}
251252

252-
static bool filter_current_task(void)
253+
static bool filter_current_task(u64 cgroup)
253254
{
254255
bool ok = true;
255-
__u64 cgroup;
256256
__u32 tgid;
257257

258258
if (user_config.filter_pid) {
259259
tgid = bpf_get_current_pid_tgid() >> 32;
260260
ok = ok && filter_pid(tgid);
261261
}
262262

263-
if (user_config.filter_cgroup) {
264-
cgroup = bpf_get_current_cgroup_id();
263+
if (user_config.filter_cgroup)
265264
ok = ok && filter_cgroup(cgroup);
266-
}
267265

268266
return ok;
269267
}
@@ -272,9 +270,13 @@ static void record_socket_latency(struct sock *sk, struct sk_buff *skb,
272270
ktime_t tstamp, enum netstacklat_hook hook)
273271
{
274272
struct hist_key key = { .hook = hook };
273+
u64 cgroup = 0;
275274
u32 ifindex;
276275

277-
if (!filter_current_task())
276+
if (user_config.filter_cgroup || user_config.groupby_cgroup)
277+
cgroup = bpf_get_current_cgroup_id();
278+
279+
if (!filter_current_task(cgroup))
278280
return;
279281

280282
ifindex = skb ? skb->skb_iif : sk->sk_rx_dst_ifindex;
@@ -286,6 +288,8 @@ static void record_socket_latency(struct sock *sk, struct sk_buff *skb,
286288

287289
if (user_config.groupby_ifindex)
288290
key.ifindex = ifindex;
291+
if (user_config.groupby_cgroup)
292+
key.cgroup = cgroup;
289293

290294
record_latency_since(tstamp, &key);
291295
}

netstacklat/netstacklat.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ static const char *__doc__ =
5757
#define MAX_PARSED_IFACES 4096
5858

5959
#define ARG_GROUPBY_INTERFACE 256
60+
#define ARG_GROUPBY_CGROUP 257
6061

6162
typedef int (*t_parse_val_func)(const char *, void *);
6263

@@ -99,6 +100,7 @@ static const struct option long_options[] = {
99100
{ "network-namespace", required_argument, NULL, 'n' },
100101
{ "cgroups", required_argument, NULL, 'c' },
101102
{ "groupby-interface", no_argument, NULL, ARG_GROUPBY_INTERFACE },
103+
{ "groupby-cgroup", no_argument, NULL, ARG_GROUPBY_CGROUP },
102104
{ 0, 0, 0, 0 }
103105
};
104106

@@ -564,6 +566,7 @@ static int parse_arguments(int argc, char *argv[],
564566
conf->bpf_conf.filter_pid = false;
565567
conf->bpf_conf.filter_ifindex = false;
566568
conf->bpf_conf.groupby_ifindex = false;
569+
conf->bpf_conf.groupby_cgroup = false;
567570

568571
conf->pids = calloc(MAX_PARSED_PIDS, sizeof(*conf->pids));
569572
conf->ifindices = calloc(MAX_PARSED_IFACES, sizeof(*conf->ifindices));
@@ -654,6 +657,9 @@ static int parse_arguments(int argc, char *argv[],
654657
case ARG_GROUPBY_INTERFACE:
655658
conf->bpf_conf.groupby_ifindex = true;
656659
break;
660+
case ARG_GROUPBY_CGROUP:
661+
conf->bpf_conf.groupby_cgroup = true;
662+
break;
657663
case 'h': // help
658664
print_usage(stdout, argv[0]);
659665
exit(EXIT_SUCCESS);
@@ -827,6 +833,9 @@ static void print_histkey(FILE *stream, const struct hist_key *key)
827833

828834
if (key->ifindex)
829835
fprintf(stream, ", interface=%u", key->ifindex);
836+
837+
if (key->cgroup)
838+
fprintf(stream, ", cgroup=%llu\n", key->cgroup);
830839
}
831840

832841
static int cmp_histkey(const void *val1, const void *val2)
@@ -839,6 +848,9 @@ static int cmp_histkey(const void *val1, const void *val2)
839848
if (key1->ifindex != key2->ifindex)
840849
return key1->ifindex > key2->ifindex ? 1 : -1;
841850

851+
if (key1->cgroup != key2->cgroup)
852+
return key1->cgroup > key2->cgroup ? 1 : -1;
853+
842854
return 0;
843855
}
844856

@@ -1038,6 +1050,11 @@ static int init_histogram_buffer(struct histogram_buffer *buf,
10381050
min(conf->nifindices, 64) :
10391051
32;
10401052

1053+
if (conf->bpf_conf.groupby_cgroup)
1054+
max_hists *= conf->bpf_conf.filter_cgroup ?
1055+
min(conf->ncgroups, 128) :
1056+
64;
1057+
10411058
buf->hists = calloc(max_hists, sizeof(*buf->hists));
10421059
if (!buf->hists)
10431060
return -errno;

netstacklat/netstacklat.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ enum netstacklat_hook {
6060
* member is named "bucket" and is the histogram bucket index.
6161
*/
6262
struct hist_key {
63+
__u64 cgroup;
6364
__u32 ifindex;
6465
__u16 hook; // need well defined size for ebpf-exporter to decode
6566
__u16 bucket; // needs to be last to be compatible with ebpf-exporter
@@ -71,6 +72,7 @@ struct netstacklat_bpf_config {
7172
bool filter_ifindex;
7273
bool filter_cgroup;
7374
bool groupby_ifindex;
75+
bool groupby_cgroup;
7476
};
7577

7678
#endif

netstacklat/netstacklat.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ metrics:
77
bucket_max: 34
88
bucket_multiplier: 0.000000001 # nanoseconds to seconds
99
labels:
10+
- name: cgroup
11+
size: 8
12+
decoders:
13+
- name: uint
14+
- name: cgroup
1015
- name: iface
1116
size: 4
1217
decoders:

0 commit comments

Comments
 (0)