xref: /aosp_15_r20/external/bcc/tests/python/test_ringbuf.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) PLUMgrid, Inc.
3*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
4*387f9dfdSAndroid Build Coastguard Worker
5*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
6*387f9dfdSAndroid Build Coastguard Workerimport os
7*387f9dfdSAndroid Build Coastguard Workerimport ctypes as ct
8*387f9dfdSAndroid Build Coastguard Workerimport random
9*387f9dfdSAndroid Build Coastguard Workerimport time
10*387f9dfdSAndroid Build Coastguard Workerimport subprocess
11*387f9dfdSAndroid Build Coastguard Workerfrom unittest import main, TestCase, skipUnless
12*387f9dfdSAndroid Build Coastguard Workerfrom utils import kernel_version_ge
13*387f9dfdSAndroid Build Coastguard Worker
14*387f9dfdSAndroid Build Coastguard Workerclass TestRingbuf(TestCase):
15*387f9dfdSAndroid Build Coastguard Worker    @skipUnless(kernel_version_ge(5,8), "requires kernel >= 5.8")
16*387f9dfdSAndroid Build Coastguard Worker    def test_ringbuf_output(self):
17*387f9dfdSAndroid Build Coastguard Worker        self.counter = 0
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Worker        class Data(ct.Structure):
20*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("ts", ct.c_ulonglong)]
21*387f9dfdSAndroid Build Coastguard Worker
22*387f9dfdSAndroid Build Coastguard Worker        def cb(ctx, data, size):
23*387f9dfdSAndroid Build Coastguard Worker            self.assertEqual(size, ct.sizeof(Data))
24*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data)).contents
25*387f9dfdSAndroid Build Coastguard Worker            self.counter += 1
26*387f9dfdSAndroid Build Coastguard Worker
27*387f9dfdSAndroid Build Coastguard Worker        text = b"""
28*387f9dfdSAndroid Build Coastguard WorkerBPF_RINGBUF_OUTPUT(events, 8);
29*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
30*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
31*387f9dfdSAndroid Build Coastguard Worker};
32*387f9dfdSAndroid Build Coastguard Workerint do_sys_nanosleep(void *ctx) {
33*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {bpf_ktime_get_ns()};
34*387f9dfdSAndroid Build Coastguard Worker    events.ringbuf_output(&data, sizeof(data), 0);
35*387f9dfdSAndroid Build Coastguard Worker    return 0;
36*387f9dfdSAndroid Build Coastguard Worker}
37*387f9dfdSAndroid Build Coastguard Worker"""
38*387f9dfdSAndroid Build Coastguard Worker        b = BPF(text=text)
39*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"nanosleep"),
40*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
41*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"clock_nanosleep"),
42*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
43*387f9dfdSAndroid Build Coastguard Worker        b[b"events"].open_ring_buffer(cb)
44*387f9dfdSAndroid Build Coastguard Worker        subprocess.call(['sleep', '0.1'])
45*387f9dfdSAndroid Build Coastguard Worker        b.ring_buffer_poll()
46*387f9dfdSAndroid Build Coastguard Worker        self.assertGreater(self.counter, 0)
47*387f9dfdSAndroid Build Coastguard Worker        b.cleanup()
48*387f9dfdSAndroid Build Coastguard Worker
49*387f9dfdSAndroid Build Coastguard Worker    @skipUnless(kernel_version_ge(5,8), "requires kernel >= 5.8")
50*387f9dfdSAndroid Build Coastguard Worker    def test_ringbuf_consume(self):
51*387f9dfdSAndroid Build Coastguard Worker        self.counter = 0
52*387f9dfdSAndroid Build Coastguard Worker
53*387f9dfdSAndroid Build Coastguard Worker        class Data(ct.Structure):
54*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("ts", ct.c_ulonglong)]
55*387f9dfdSAndroid Build Coastguard Worker
56*387f9dfdSAndroid Build Coastguard Worker        def cb(ctx, data, size):
57*387f9dfdSAndroid Build Coastguard Worker            self.assertEqual(size, ct.sizeof(Data))
58*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data)).contents
59*387f9dfdSAndroid Build Coastguard Worker            self.counter += 1
60*387f9dfdSAndroid Build Coastguard Worker
61*387f9dfdSAndroid Build Coastguard Worker        text = b"""
62*387f9dfdSAndroid Build Coastguard WorkerBPF_RINGBUF_OUTPUT(events, 8);
63*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
64*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
65*387f9dfdSAndroid Build Coastguard Worker};
66*387f9dfdSAndroid Build Coastguard Workerint do_sys_nanosleep(void *ctx) {
67*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {bpf_ktime_get_ns()};
68*387f9dfdSAndroid Build Coastguard Worker    events.ringbuf_output(&data, sizeof(data), 0);
69*387f9dfdSAndroid Build Coastguard Worker    return 0;
70*387f9dfdSAndroid Build Coastguard Worker}
71*387f9dfdSAndroid Build Coastguard Worker"""
72*387f9dfdSAndroid Build Coastguard Worker        b = BPF(text=text)
73*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"nanosleep"),
74*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
75*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"clock_nanosleep"),
76*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
77*387f9dfdSAndroid Build Coastguard Worker        b[b"events"].open_ring_buffer(cb)
78*387f9dfdSAndroid Build Coastguard Worker        subprocess.call(['sleep', '0.1'])
79*387f9dfdSAndroid Build Coastguard Worker        b.ring_buffer_consume()
80*387f9dfdSAndroid Build Coastguard Worker        self.assertGreater(self.counter, 0)
81*387f9dfdSAndroid Build Coastguard Worker        b.cleanup()
82*387f9dfdSAndroid Build Coastguard Worker
83*387f9dfdSAndroid Build Coastguard Worker    @skipUnless(kernel_version_ge(5,8), "requires kernel >= 5.8")
84*387f9dfdSAndroid Build Coastguard Worker    def test_ringbuf_submit(self):
85*387f9dfdSAndroid Build Coastguard Worker        self.counter = 0
86*387f9dfdSAndroid Build Coastguard Worker
87*387f9dfdSAndroid Build Coastguard Worker        class Data(ct.Structure):
88*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("ts", ct.c_ulonglong)]
89*387f9dfdSAndroid Build Coastguard Worker
90*387f9dfdSAndroid Build Coastguard Worker        def cb(ctx, data, size):
91*387f9dfdSAndroid Build Coastguard Worker            self.assertEqual(size, ct.sizeof(Data))
92*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data)).contents
93*387f9dfdSAndroid Build Coastguard Worker            self.counter += 1
94*387f9dfdSAndroid Build Coastguard Worker
95*387f9dfdSAndroid Build Coastguard Worker        text = b"""
96*387f9dfdSAndroid Build Coastguard WorkerBPF_RINGBUF_OUTPUT(events, 8);
97*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
98*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
99*387f9dfdSAndroid Build Coastguard Worker};
100*387f9dfdSAndroid Build Coastguard Workerint do_sys_nanosleep(void *ctx) {
101*387f9dfdSAndroid Build Coastguard Worker    struct data_t *data = events.ringbuf_reserve(sizeof(struct data_t));
102*387f9dfdSAndroid Build Coastguard Worker    if (!data)
103*387f9dfdSAndroid Build Coastguard Worker        return 1;
104*387f9dfdSAndroid Build Coastguard Worker    data->ts = bpf_ktime_get_ns();
105*387f9dfdSAndroid Build Coastguard Worker    events.ringbuf_submit(data, 0);
106*387f9dfdSAndroid Build Coastguard Worker    return 0;
107*387f9dfdSAndroid Build Coastguard Worker}
108*387f9dfdSAndroid Build Coastguard Worker"""
109*387f9dfdSAndroid Build Coastguard Worker        b = BPF(text=text)
110*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"nanosleep"),
111*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
112*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"clock_nanosleep"),
113*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
114*387f9dfdSAndroid Build Coastguard Worker        b[b"events"].open_ring_buffer(cb)
115*387f9dfdSAndroid Build Coastguard Worker        subprocess.call(['sleep', '0.1'])
116*387f9dfdSAndroid Build Coastguard Worker        b.ring_buffer_poll()
117*387f9dfdSAndroid Build Coastguard Worker        self.assertGreater(self.counter, 0)
118*387f9dfdSAndroid Build Coastguard Worker        b.cleanup()
119*387f9dfdSAndroid Build Coastguard Worker
120*387f9dfdSAndroid Build Coastguard Worker    @skipUnless(kernel_version_ge(5,8), "requires kernel >= 5.8")
121*387f9dfdSAndroid Build Coastguard Worker    def test_ringbuf_discard(self):
122*387f9dfdSAndroid Build Coastguard Worker        self.counter = 0
123*387f9dfdSAndroid Build Coastguard Worker
124*387f9dfdSAndroid Build Coastguard Worker        class Data(ct.Structure):
125*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("ts", ct.c_ulonglong)]
126*387f9dfdSAndroid Build Coastguard Worker
127*387f9dfdSAndroid Build Coastguard Worker        def cb(ctx, data, size):
128*387f9dfdSAndroid Build Coastguard Worker            self.assertEqual(size, ct.sizeof(Data))
129*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data)).contents
130*387f9dfdSAndroid Build Coastguard Worker            self.counter += 1
131*387f9dfdSAndroid Build Coastguard Worker
132*387f9dfdSAndroid Build Coastguard Worker        text = b"""
133*387f9dfdSAndroid Build Coastguard WorkerBPF_RINGBUF_OUTPUT(events, 8);
134*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
135*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
136*387f9dfdSAndroid Build Coastguard Worker};
137*387f9dfdSAndroid Build Coastguard Workerint do_sys_nanosleep(void *ctx) {
138*387f9dfdSAndroid Build Coastguard Worker    struct data_t *data = events.ringbuf_reserve(sizeof(struct data_t));
139*387f9dfdSAndroid Build Coastguard Worker    if (!data)
140*387f9dfdSAndroid Build Coastguard Worker        return 1;
141*387f9dfdSAndroid Build Coastguard Worker    data->ts = bpf_ktime_get_ns();
142*387f9dfdSAndroid Build Coastguard Worker    events.ringbuf_discard(data, 0);
143*387f9dfdSAndroid Build Coastguard Worker    return 0;
144*387f9dfdSAndroid Build Coastguard Worker}
145*387f9dfdSAndroid Build Coastguard Worker"""
146*387f9dfdSAndroid Build Coastguard Worker        b = BPF(text=text)
147*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"nanosleep"),
148*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
149*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"clock_nanosleep"),
150*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
151*387f9dfdSAndroid Build Coastguard Worker        b[b"events"].open_ring_buffer(cb)
152*387f9dfdSAndroid Build Coastguard Worker        subprocess.call(['sleep', '0.1'])
153*387f9dfdSAndroid Build Coastguard Worker        b.ring_buffer_poll()
154*387f9dfdSAndroid Build Coastguard Worker        self.assertEqual(self.counter, 0)
155*387f9dfdSAndroid Build Coastguard Worker        b.cleanup()
156*387f9dfdSAndroid Build Coastguard Worker
157*387f9dfdSAndroid Build Coastguard Worker    @skipUnless(kernel_version_ge(5,8), "requires kernel >= 5.8")
158*387f9dfdSAndroid Build Coastguard Worker    def test_ringbuf_query(self):
159*387f9dfdSAndroid Build Coastguard Worker        PAGE_SIZE = 8
160*387f9dfdSAndroid Build Coastguard Worker        self.counter = 0
161*387f9dfdSAndroid Build Coastguard Worker        self.page_counts = 0
162*387f9dfdSAndroid Build Coastguard Worker
163*387f9dfdSAndroid Build Coastguard Worker        class Data(ct.Structure):
164*387f9dfdSAndroid Build Coastguard Worker            _fields_ = [("page_cnt", ct.c_ulonglong)]
165*387f9dfdSAndroid Build Coastguard Worker
166*387f9dfdSAndroid Build Coastguard Worker        def cb(ctx, data, size):
167*387f9dfdSAndroid Build Coastguard Worker            self.assertEqual(size, ct.sizeof(Data))
168*387f9dfdSAndroid Build Coastguard Worker            event = ct.cast(data, ct.POINTER(Data)).contents
169*387f9dfdSAndroid Build Coastguard Worker            self.page_counts += event.page_cnt
170*387f9dfdSAndroid Build Coastguard Worker            self.counter += 1
171*387f9dfdSAndroid Build Coastguard Worker
172*387f9dfdSAndroid Build Coastguard Worker        text = b"""
173*387f9dfdSAndroid Build Coastguard WorkerBPF_RINGBUF_OUTPUT(events, %i);
174*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
175*387f9dfdSAndroid Build Coastguard Worker    u64 page_cnt;
176*387f9dfdSAndroid Build Coastguard Worker};
177*387f9dfdSAndroid Build Coastguard Workerint do_sys_nanosleep(void *ctx) {
178*387f9dfdSAndroid Build Coastguard Worker    u64 res = 0;
179*387f9dfdSAndroid Build Coastguard Worker    res = events.ringbuf_query(BPF_RB_RING_SIZE);
180*387f9dfdSAndroid Build Coastguard Worker    if(res == 0) {
181*387f9dfdSAndroid Build Coastguard Worker        return 1;
182*387f9dfdSAndroid Build Coastguard Worker    }
183*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {res / PAGE_SIZE};
184*387f9dfdSAndroid Build Coastguard Worker    events.ringbuf_output(&data, sizeof(data), 0);
185*387f9dfdSAndroid Build Coastguard Worker    return 0;
186*387f9dfdSAndroid Build Coastguard Worker}
187*387f9dfdSAndroid Build Coastguard Worker"""
188*387f9dfdSAndroid Build Coastguard Worker        text = text % PAGE_SIZE
189*387f9dfdSAndroid Build Coastguard Worker        b = BPF(text=text)
190*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"nanosleep"),
191*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
192*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=b.get_syscall_fnname(b"clock_nanosleep"),
193*387f9dfdSAndroid Build Coastguard Worker                        fn_name=b"do_sys_nanosleep")
194*387f9dfdSAndroid Build Coastguard Worker        b[b"events"].open_ring_buffer(cb)
195*387f9dfdSAndroid Build Coastguard Worker        subprocess.call(['sleep', '0.1'])
196*387f9dfdSAndroid Build Coastguard Worker        b.ring_buffer_poll()
197*387f9dfdSAndroid Build Coastguard Worker        self.assertEqual(self.page_counts / self.counter, PAGE_SIZE)
198*387f9dfdSAndroid Build Coastguard Worker        b.cleanup()
199*387f9dfdSAndroid Build Coastguard Worker
200*387f9dfdSAndroid Build Coastguard Workerif __name__ == "__main__":
201*387f9dfdSAndroid Build Coastguard Worker    main()
202