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 ctypes as ct 7*387f9dfdSAndroid Build Coastguard Workerimport random 8*387f9dfdSAndroid Build Coastguard Workerimport time 9*387f9dfdSAndroid Build Coastguard Workerimport subprocess 10*387f9dfdSAndroid Build Coastguard Workerfrom bcc.utils import get_online_cpus 11*387f9dfdSAndroid Build Coastguard Workerfrom unittest import main, TestCase 12*387f9dfdSAndroid Build Coastguard Worker 13*387f9dfdSAndroid Build Coastguard Workerclass TestArray(TestCase): 14*387f9dfdSAndroid Build Coastguard Worker def test_simple(self): 15*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=b"""BPF_ARRAY(table1, u64, 128);""") 16*387f9dfdSAndroid Build Coastguard Worker t1 = b[b"table1"] 17*387f9dfdSAndroid Build Coastguard Worker t1[ct.c_int(0)] = ct.c_ulonglong(100) 18*387f9dfdSAndroid Build Coastguard Worker t1[ct.c_int(127)] = ct.c_ulonglong(1000) 19*387f9dfdSAndroid Build Coastguard Worker for i, v in t1.items(): 20*387f9dfdSAndroid Build Coastguard Worker if i.value == 0: 21*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(v.value, 100) 22*387f9dfdSAndroid Build Coastguard Worker if i.value == 127: 23*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(v.value, 1000) 24*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(len(t1), 128) 25*387f9dfdSAndroid Build Coastguard Worker 26*387f9dfdSAndroid Build Coastguard Worker def test_native_type(self): 27*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=b"""BPF_ARRAY(table1, u64, 128);""") 28*387f9dfdSAndroid Build Coastguard Worker t1 = b[b"table1"] 29*387f9dfdSAndroid Build Coastguard Worker t1[0] = ct.c_ulonglong(100) 30*387f9dfdSAndroid Build Coastguard Worker t1[-2] = ct.c_ulonglong(37) 31*387f9dfdSAndroid Build Coastguard Worker t1[127] = ct.c_ulonglong(1000) 32*387f9dfdSAndroid Build Coastguard Worker for i, v in t1.items(): 33*387f9dfdSAndroid Build Coastguard Worker if i.value == 0: 34*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(v.value, 100) 35*387f9dfdSAndroid Build Coastguard Worker if i.value == 127: 36*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(v.value, 1000) 37*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(len(t1), 128) 38*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(t1[-2].value, 37) 39*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(t1[-1].value, t1[127].value) 40*387f9dfdSAndroid Build Coastguard Worker 41*387f9dfdSAndroid Build Coastguard Worker def test_perf_buffer(self): 42*387f9dfdSAndroid Build Coastguard Worker self.counter = 0 43*387f9dfdSAndroid Build Coastguard Worker 44*387f9dfdSAndroid Build Coastguard Worker class Data(ct.Structure): 45*387f9dfdSAndroid Build Coastguard Worker _fields_ = [("ts", ct.c_ulonglong)] 46*387f9dfdSAndroid Build Coastguard Worker 47*387f9dfdSAndroid Build Coastguard Worker def cb(cpu, data, size): 48*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(size, ct.sizeof(Data)) 49*387f9dfdSAndroid Build Coastguard Worker event = ct.cast(data, ct.POINTER(Data)).contents 50*387f9dfdSAndroid Build Coastguard Worker self.counter += 1 51*387f9dfdSAndroid Build Coastguard Worker 52*387f9dfdSAndroid Build Coastguard Worker def lost_cb(lost): 53*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(lost, 0) 54*387f9dfdSAndroid Build Coastguard Worker 55*387f9dfdSAndroid Build Coastguard Worker text = b""" 56*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events); 57*387f9dfdSAndroid Build Coastguard Workerint do_sys_nanosleep(void *ctx) { 58*387f9dfdSAndroid Build Coastguard Worker struct { 59*387f9dfdSAndroid Build Coastguard Worker u64 ts; 60*387f9dfdSAndroid Build Coastguard Worker } data = {bpf_ktime_get_ns()}; 61*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 62*387f9dfdSAndroid Build Coastguard Worker return 0; 63*387f9dfdSAndroid Build Coastguard Worker} 64*387f9dfdSAndroid Build Coastguard Worker""" 65*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=text) 66*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event=b.get_syscall_fnname(b"nanosleep"), 67*387f9dfdSAndroid Build Coastguard Worker fn_name=b"do_sys_nanosleep") 68*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event=b.get_syscall_fnname(b"clock_nanosleep"), 69*387f9dfdSAndroid Build Coastguard Worker fn_name=b"do_sys_nanosleep") 70*387f9dfdSAndroid Build Coastguard Worker b[b"events"].open_perf_buffer(cb, lost_cb=lost_cb) 71*387f9dfdSAndroid Build Coastguard Worker subprocess.call(['sleep', '0.1']) 72*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 73*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(self.counter, 0) 74*387f9dfdSAndroid Build Coastguard Worker b.cleanup() 75*387f9dfdSAndroid Build Coastguard Worker 76*387f9dfdSAndroid Build Coastguard Worker def test_perf_buffer_for_each_cpu(self): 77*387f9dfdSAndroid Build Coastguard Worker self.events = [] 78*387f9dfdSAndroid Build Coastguard Worker 79*387f9dfdSAndroid Build Coastguard Worker class Data(ct.Structure): 80*387f9dfdSAndroid Build Coastguard Worker _fields_ = [("cpu", ct.c_ulonglong)] 81*387f9dfdSAndroid Build Coastguard Worker 82*387f9dfdSAndroid Build Coastguard Worker def cb(cpu, data, size): 83*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(size, ct.sizeof(Data)) 84*387f9dfdSAndroid Build Coastguard Worker event = ct.cast(data, ct.POINTER(Data)).contents 85*387f9dfdSAndroid Build Coastguard Worker self.events.append(event) 86*387f9dfdSAndroid Build Coastguard Worker 87*387f9dfdSAndroid Build Coastguard Worker def lost_cb(lost): 88*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(lost, 0) 89*387f9dfdSAndroid Build Coastguard Worker 90*387f9dfdSAndroid Build Coastguard Worker text = b""" 91*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events); 92*387f9dfdSAndroid Build Coastguard Workerint do_sys_nanosleep(void *ctx) { 93*387f9dfdSAndroid Build Coastguard Worker struct { 94*387f9dfdSAndroid Build Coastguard Worker u64 cpu; 95*387f9dfdSAndroid Build Coastguard Worker } data = {bpf_get_smp_processor_id()}; 96*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 97*387f9dfdSAndroid Build Coastguard Worker return 0; 98*387f9dfdSAndroid Build Coastguard Worker} 99*387f9dfdSAndroid Build Coastguard Worker""" 100*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=text) 101*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event=b.get_syscall_fnname(b"nanosleep"), 102*387f9dfdSAndroid Build Coastguard Worker fn_name=b"do_sys_nanosleep") 103*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event=b.get_syscall_fnname(b"clock_nanosleep"), 104*387f9dfdSAndroid Build Coastguard Worker fn_name=b"do_sys_nanosleep") 105*387f9dfdSAndroid Build Coastguard Worker b[b"events"].open_perf_buffer(cb, lost_cb=lost_cb) 106*387f9dfdSAndroid Build Coastguard Worker online_cpus = get_online_cpus() 107*387f9dfdSAndroid Build Coastguard Worker for cpu in online_cpus: 108*387f9dfdSAndroid Build Coastguard Worker subprocess.call(['taskset', '-c', str(cpu), 'sleep', '0.1']) 109*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 110*387f9dfdSAndroid Build Coastguard Worker b.cleanup() 111*387f9dfdSAndroid Build Coastguard Worker self.assertGreaterEqual(len(self.events), len(online_cpus), 'Received only {}/{} events'.format(len(self.events), len(online_cpus))) 112*387f9dfdSAndroid Build Coastguard Worker 113*387f9dfdSAndroid Build Coastguard Workerif __name__ == "__main__": 114*387f9dfdSAndroid Build Coastguard Worker main() 115