1cb1c9dddSAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
2cb1c9dddSAndrii Nakryiko // Copyright (c) 2020 Facebook
3cb1c9dddSAndrii Nakryiko 
4cb1c9dddSAndrii Nakryiko #include <linux/bpf.h>
5cb1c9dddSAndrii Nakryiko #include <bpf/bpf_helpers.h>
6cb1c9dddSAndrii Nakryiko 
7cb1c9dddSAndrii Nakryiko char _license[] SEC("license") = "GPL";
8cb1c9dddSAndrii Nakryiko 
9cb1c9dddSAndrii Nakryiko struct sample {
10cb1c9dddSAndrii Nakryiko 	int pid;
11cb1c9dddSAndrii Nakryiko 	int seq;
12cb1c9dddSAndrii Nakryiko 	long value;
13cb1c9dddSAndrii Nakryiko 	char comm[16];
14cb1c9dddSAndrii Nakryiko };
15cb1c9dddSAndrii Nakryiko 
16cb1c9dddSAndrii Nakryiko struct ringbuf_map {
17cb1c9dddSAndrii Nakryiko 	__uint(type, BPF_MAP_TYPE_RINGBUF);
18*7b3a0638SAndrii Nakryiko 	/* libbpf will adjust to valid page size */
19*7b3a0638SAndrii Nakryiko 	__uint(max_entries, 1000);
20cb1c9dddSAndrii Nakryiko } ringbuf1 SEC(".maps"),
21cb1c9dddSAndrii Nakryiko   ringbuf2 SEC(".maps");
22cb1c9dddSAndrii Nakryiko 
23cb1c9dddSAndrii Nakryiko struct {
24cb1c9dddSAndrii Nakryiko 	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
25cb1c9dddSAndrii Nakryiko 	__uint(max_entries, 4);
26cb1c9dddSAndrii Nakryiko 	__type(key, int);
27cb1c9dddSAndrii Nakryiko 	__array(values, struct ringbuf_map);
28cb1c9dddSAndrii Nakryiko } ringbuf_arr SEC(".maps") = {
29cb1c9dddSAndrii Nakryiko 	.values = {
30cb1c9dddSAndrii Nakryiko 		[0] = &ringbuf1,
31cb1c9dddSAndrii Nakryiko 		[2] = &ringbuf2,
32cb1c9dddSAndrii Nakryiko 	},
33cb1c9dddSAndrii Nakryiko };
34cb1c9dddSAndrii Nakryiko 
35cfc0889cSYauheni Kaliuta struct {
36cfc0889cSYauheni Kaliuta 	__uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
37cfc0889cSYauheni Kaliuta 	__uint(max_entries, 1);
38cfc0889cSYauheni Kaliuta 	__type(key, int);
39cfc0889cSYauheni Kaliuta 	__array(values, struct ringbuf_map);
40cfc0889cSYauheni Kaliuta } ringbuf_hash SEC(".maps") = {
41cfc0889cSYauheni Kaliuta 	.values = {
42cfc0889cSYauheni Kaliuta 		[0] = &ringbuf1,
43cfc0889cSYauheni Kaliuta 	},
44cfc0889cSYauheni Kaliuta };
45cfc0889cSYauheni Kaliuta 
46cb1c9dddSAndrii Nakryiko /* inputs */
47cb1c9dddSAndrii Nakryiko int pid = 0;
48cb1c9dddSAndrii Nakryiko int target_ring = 0;
49cb1c9dddSAndrii Nakryiko long value = 0;
50cb1c9dddSAndrii Nakryiko 
51cb1c9dddSAndrii Nakryiko /* outputs */
52cb1c9dddSAndrii Nakryiko long total = 0;
53cb1c9dddSAndrii Nakryiko long dropped = 0;
54cb1c9dddSAndrii Nakryiko long skipped = 0;
55cb1c9dddSAndrii Nakryiko 
56cb1c9dddSAndrii Nakryiko SEC("tp/syscalls/sys_enter_getpgid")
test_ringbuf(void * ctx)57cb1c9dddSAndrii Nakryiko int test_ringbuf(void *ctx)
58cb1c9dddSAndrii Nakryiko {
59cb1c9dddSAndrii Nakryiko 	int cur_pid = bpf_get_current_pid_tgid() >> 32;
60cb1c9dddSAndrii Nakryiko 	struct sample *sample;
61cb1c9dddSAndrii Nakryiko 	void *rb;
62cb1c9dddSAndrii Nakryiko 
63cb1c9dddSAndrii Nakryiko 	if (cur_pid != pid)
64cb1c9dddSAndrii Nakryiko 		return 0;
65cb1c9dddSAndrii Nakryiko 
66cb1c9dddSAndrii Nakryiko 	rb = bpf_map_lookup_elem(&ringbuf_arr, &target_ring);
67cb1c9dddSAndrii Nakryiko 	if (!rb) {
68cb1c9dddSAndrii Nakryiko 		skipped += 1;
69cb1c9dddSAndrii Nakryiko 		return 1;
70cb1c9dddSAndrii Nakryiko 	}
71cb1c9dddSAndrii Nakryiko 
72cb1c9dddSAndrii Nakryiko 	sample = bpf_ringbuf_reserve(rb, sizeof(*sample), 0);
73cb1c9dddSAndrii Nakryiko 	if (!sample) {
74cb1c9dddSAndrii Nakryiko 		dropped += 1;
75cb1c9dddSAndrii Nakryiko 		return 1;
76cb1c9dddSAndrii Nakryiko 	}
77cb1c9dddSAndrii Nakryiko 
78cb1c9dddSAndrii Nakryiko 	sample->pid = pid;
79cb1c9dddSAndrii Nakryiko 	bpf_get_current_comm(sample->comm, sizeof(sample->comm));
80cb1c9dddSAndrii Nakryiko 	sample->value = value;
81cb1c9dddSAndrii Nakryiko 
82cb1c9dddSAndrii Nakryiko 	sample->seq = total;
83cb1c9dddSAndrii Nakryiko 	total += 1;
84cb1c9dddSAndrii Nakryiko 
85cb1c9dddSAndrii Nakryiko 	bpf_ringbuf_submit(sample, 0);
86cb1c9dddSAndrii Nakryiko 
87cb1c9dddSAndrii Nakryiko 	return 0;
88cb1c9dddSAndrii Nakryiko }
89