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 Workerimport os 6*387f9dfdSAndroid Build Coastguard Workerimport unittest 7*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 8*387f9dfdSAndroid Build Coastguard Workerimport multiprocessing 9*387f9dfdSAndroid Build Coastguard Worker 10*387f9dfdSAndroid Build Coastguard WorkerMONITORED_SYSCALL=b"execve" 11*387f9dfdSAndroid Build Coastguard Worker 12*387f9dfdSAndroid Build Coastguard Workerclass TestPercpu(unittest.TestCase): 13*387f9dfdSAndroid Build Coastguard Worker 14*387f9dfdSAndroid Build Coastguard Worker def setUp(self): 15*387f9dfdSAndroid Build Coastguard Worker try: 16*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=b'BPF_PERCPU_ARRAY(stub, u32, 1);') 17*387f9dfdSAndroid Build Coastguard Worker except: 18*387f9dfdSAndroid Build Coastguard Worker raise unittest.SkipTest("PerCpu unsupported on this kernel") 19*387f9dfdSAndroid Build Coastguard Worker 20*387f9dfdSAndroid Build Coastguard Worker def test_helper(self): 21*387f9dfdSAndroid Build Coastguard Worker test_prog1 = b""" 22*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_ARRAY(stub_default); 23*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_ARRAY(stub_type, u64); 24*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_ARRAY(stub_full, u64, 1024); 25*387f9dfdSAndroid Build Coastguard Worker """ 26*387f9dfdSAndroid Build Coastguard Worker BPF(text=test_prog1) 27*387f9dfdSAndroid Build Coastguard Worker 28*387f9dfdSAndroid Build Coastguard Worker def test_u64(self): 29*387f9dfdSAndroid Build Coastguard Worker test_prog1 = b""" 30*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_HASH(stats, u32, u64, 1); 31*387f9dfdSAndroid Build Coastguard Worker int hello_world(void *ctx) { 32*387f9dfdSAndroid Build Coastguard Worker u32 key=0; 33*387f9dfdSAndroid Build Coastguard Worker u64 value = 0, *val; 34*387f9dfdSAndroid Build Coastguard Worker val = stats.lookup_or_try_init(&key, &value); 35*387f9dfdSAndroid Build Coastguard Worker if (val) { 36*387f9dfdSAndroid Build Coastguard Worker *val += 1; 37*387f9dfdSAndroid Build Coastguard Worker } 38*387f9dfdSAndroid Build Coastguard Worker return 0; 39*387f9dfdSAndroid Build Coastguard Worker } 40*387f9dfdSAndroid Build Coastguard Worker """ 41*387f9dfdSAndroid Build Coastguard Worker bpf_code = BPF(text=test_prog1) 42*387f9dfdSAndroid Build Coastguard Worker stats_map = bpf_code.get_table(b"stats") 43*387f9dfdSAndroid Build Coastguard Worker event_name = bpf_code.get_syscall_fnname(MONITORED_SYSCALL) 44*387f9dfdSAndroid Build Coastguard Worker bpf_code.attach_kprobe(event=event_name, fn_name=b"hello_world") 45*387f9dfdSAndroid Build Coastguard Worker ini = stats_map.Leaf() 46*387f9dfdSAndroid Build Coastguard Worker for i in range(0, multiprocessing.cpu_count()): 47*387f9dfdSAndroid Build Coastguard Worker ini[i] = 0 48*387f9dfdSAndroid Build Coastguard Worker stats_map[ stats_map.Key(0) ] = ini 49*387f9dfdSAndroid Build Coastguard Worker f = os.popen("hostname") 50*387f9dfdSAndroid Build Coastguard Worker f.close() 51*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(len(stats_map),1) 52*387f9dfdSAndroid Build Coastguard Worker val = stats_map[ stats_map.Key(0) ] 53*387f9dfdSAndroid Build Coastguard Worker sum = stats_map.sum(stats_map.Key(0)) 54*387f9dfdSAndroid Build Coastguard Worker avg = stats_map.average(stats_map.Key(0)) 55*387f9dfdSAndroid Build Coastguard Worker max = stats_map.max(stats_map.Key(0)) 56*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(sum.value, int(0)) 57*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(max.value, int(0)) 58*387f9dfdSAndroid Build Coastguard Worker bpf_code.detach_kprobe(event_name) 59*387f9dfdSAndroid Build Coastguard Worker 60*387f9dfdSAndroid Build Coastguard Worker def test_u32(self): 61*387f9dfdSAndroid Build Coastguard Worker test_prog1 = b""" 62*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_ARRAY(stats, u32, 1); 63*387f9dfdSAndroid Build Coastguard Worker int hello_world(void *ctx) { 64*387f9dfdSAndroid Build Coastguard Worker u32 key=0; 65*387f9dfdSAndroid Build Coastguard Worker u32 value = 0, *val; 66*387f9dfdSAndroid Build Coastguard Worker val = stats.lookup_or_try_init(&key, &value); 67*387f9dfdSAndroid Build Coastguard Worker if (val) { 68*387f9dfdSAndroid Build Coastguard Worker *val += 1; 69*387f9dfdSAndroid Build Coastguard Worker } 70*387f9dfdSAndroid Build Coastguard Worker return 0; 71*387f9dfdSAndroid Build Coastguard Worker } 72*387f9dfdSAndroid Build Coastguard Worker """ 73*387f9dfdSAndroid Build Coastguard Worker bpf_code = BPF(text=test_prog1) 74*387f9dfdSAndroid Build Coastguard Worker stats_map = bpf_code.get_table(b"stats") 75*387f9dfdSAndroid Build Coastguard Worker event_name = bpf_code.get_syscall_fnname(MONITORED_SYSCALL) 76*387f9dfdSAndroid Build Coastguard Worker bpf_code.attach_kprobe(event=event_name, fn_name=b"hello_world") 77*387f9dfdSAndroid Build Coastguard Worker ini = stats_map.Leaf() 78*387f9dfdSAndroid Build Coastguard Worker for i in range(0, multiprocessing.cpu_count()): 79*387f9dfdSAndroid Build Coastguard Worker ini[i] = 0 80*387f9dfdSAndroid Build Coastguard Worker stats_map[ stats_map.Key(0) ] = ini 81*387f9dfdSAndroid Build Coastguard Worker f = os.popen("hostname") 82*387f9dfdSAndroid Build Coastguard Worker f.close() 83*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(len(stats_map),1) 84*387f9dfdSAndroid Build Coastguard Worker val = stats_map[ stats_map.Key(0) ] 85*387f9dfdSAndroid Build Coastguard Worker sum = stats_map.sum(stats_map.Key(0)) 86*387f9dfdSAndroid Build Coastguard Worker avg = stats_map.average(stats_map.Key(0)) 87*387f9dfdSAndroid Build Coastguard Worker max = stats_map.max(stats_map.Key(0)) 88*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(sum.value, int(0)) 89*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(max.value, int(0)) 90*387f9dfdSAndroid Build Coastguard Worker bpf_code.detach_kprobe(event_name) 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Worker def test_struct_custom_func(self): 93*387f9dfdSAndroid Build Coastguard Worker test_prog2 = b""" 94*387f9dfdSAndroid Build Coastguard Worker typedef struct counter { 95*387f9dfdSAndroid Build Coastguard Worker u32 c1; 96*387f9dfdSAndroid Build Coastguard Worker u32 c2; 97*387f9dfdSAndroid Build Coastguard Worker } counter; 98*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_HASH(stats, u32, counter, 1); 99*387f9dfdSAndroid Build Coastguard Worker int hello_world(void *ctx) { 100*387f9dfdSAndroid Build Coastguard Worker u32 key=0; 101*387f9dfdSAndroid Build Coastguard Worker counter value = {0,0}, *val; 102*387f9dfdSAndroid Build Coastguard Worker val = stats.lookup_or_try_init(&key, &value); 103*387f9dfdSAndroid Build Coastguard Worker if (val) { 104*387f9dfdSAndroid Build Coastguard Worker val->c1 += 1; 105*387f9dfdSAndroid Build Coastguard Worker val->c2 += 1; 106*387f9dfdSAndroid Build Coastguard Worker } 107*387f9dfdSAndroid Build Coastguard Worker return 0; 108*387f9dfdSAndroid Build Coastguard Worker } 109*387f9dfdSAndroid Build Coastguard Worker """ 110*387f9dfdSAndroid Build Coastguard Worker bpf_code = BPF(text=test_prog2) 111*387f9dfdSAndroid Build Coastguard Worker stats_map = bpf_code.get_table(b"stats", 112*387f9dfdSAndroid Build Coastguard Worker reducer=lambda x,y: stats_map.sLeaf(x.c1+y.c1)) 113*387f9dfdSAndroid Build Coastguard Worker event_name = bpf_code.get_syscall_fnname(MONITORED_SYSCALL) 114*387f9dfdSAndroid Build Coastguard Worker bpf_code.attach_kprobe(event=event_name, fn_name=b"hello_world") 115*387f9dfdSAndroid Build Coastguard Worker ini = stats_map.Leaf() 116*387f9dfdSAndroid Build Coastguard Worker for i in ini: 117*387f9dfdSAndroid Build Coastguard Worker i = stats_map.sLeaf(0,0) 118*387f9dfdSAndroid Build Coastguard Worker stats_map[ stats_map.Key(0) ] = ini 119*387f9dfdSAndroid Build Coastguard Worker f = os.popen("hostname") 120*387f9dfdSAndroid Build Coastguard Worker f.close() 121*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(len(stats_map),1) 122*387f9dfdSAndroid Build Coastguard Worker k = stats_map[ stats_map.Key(0) ] 123*387f9dfdSAndroid Build Coastguard Worker self.assertGreater(k.c1, int(0)) 124*387f9dfdSAndroid Build Coastguard Worker bpf_code.detach_kprobe(event_name) 125*387f9dfdSAndroid Build Coastguard Worker 126*387f9dfdSAndroid Build Coastguard Worker 127*387f9dfdSAndroid Build Coastguard Workerif __name__ == "__main__": 128*387f9dfdSAndroid Build Coastguard Worker unittest.main() 129