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 Workerfrom ctypes import c_int, c_ulonglong 7*387f9dfdSAndroid Build Coastguard Workerimport random 8*387f9dfdSAndroid Build Coastguard Workerimport time 9*387f9dfdSAndroid Build Coastguard Workerfrom unittest import main, TestCase 10*387f9dfdSAndroid Build Coastguard Worker 11*387f9dfdSAndroid Build Coastguard Workerclass TestHistogram(TestCase): 12*387f9dfdSAndroid Build Coastguard Worker def test_simple(self): 13*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=b""" 14*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 15*387f9dfdSAndroid Build Coastguard Workerstruct bpf_map; 16*387f9dfdSAndroid Build Coastguard WorkerBPF_HISTOGRAM(hist1); 17*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(stub); 18*387f9dfdSAndroid Build Coastguard Workerint kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *k) { 19*387f9dfdSAndroid Build Coastguard Worker hist1.increment(bpf_log2l(*k)); 20*387f9dfdSAndroid Build Coastguard Worker hist1.atomic_increment(bpf_log2l(*k)); 21*387f9dfdSAndroid Build Coastguard Worker return 0; 22*387f9dfdSAndroid Build Coastguard Worker} 23*387f9dfdSAndroid Build Coastguard Worker""") 24*387f9dfdSAndroid Build Coastguard Worker for i in range(0, 32): 25*387f9dfdSAndroid Build Coastguard Worker for j in range(0, random.randint(1, 10)): 26*387f9dfdSAndroid Build Coastguard Worker try: del b[b"stub"][c_ulonglong(1 << i)] 27*387f9dfdSAndroid Build Coastguard Worker except: pass 28*387f9dfdSAndroid Build Coastguard Worker b[b"hist1"].print_log2_hist() 29*387f9dfdSAndroid Build Coastguard Worker 30*387f9dfdSAndroid Build Coastguard Worker for i in range(32, 64): 31*387f9dfdSAndroid Build Coastguard Worker for j in range(0, random.randint(1, 10)): 32*387f9dfdSAndroid Build Coastguard Worker try: del b[b"stub"][c_ulonglong(1 << i)] 33*387f9dfdSAndroid Build Coastguard Worker except: pass 34*387f9dfdSAndroid Build Coastguard Worker b[b"hist1"].print_log2_hist() 35*387f9dfdSAndroid Build Coastguard Worker b.cleanup() 36*387f9dfdSAndroid Build Coastguard Worker 37*387f9dfdSAndroid Build Coastguard Worker def test_struct(self): 38*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=b""" 39*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 40*387f9dfdSAndroid Build Coastguard Workerstruct bpf_map; 41*387f9dfdSAndroid Build Coastguard Workertypedef struct { void *map; u64 slot; } Key; 42*387f9dfdSAndroid Build Coastguard WorkerBPF_HISTOGRAM(hist1, Key, 1024); 43*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(stub1); 44*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(stub2); 45*387f9dfdSAndroid Build Coastguard Workerint kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *k) { 46*387f9dfdSAndroid Build Coastguard Worker hist1.increment((Key){map, bpf_log2l(*k)}); 47*387f9dfdSAndroid Build Coastguard Worker hist1.atomic_increment((Key){map, bpf_log2l(*k)}); 48*387f9dfdSAndroid Build Coastguard Worker return 0; 49*387f9dfdSAndroid Build Coastguard Worker} 50*387f9dfdSAndroid Build Coastguard Worker""") 51*387f9dfdSAndroid Build Coastguard Worker for i in range(0, 64): 52*387f9dfdSAndroid Build Coastguard Worker for j in range(0, random.randint(1, 10)): 53*387f9dfdSAndroid Build Coastguard Worker try: del b[b"stub1"][c_ulonglong(1 << i)] 54*387f9dfdSAndroid Build Coastguard Worker except: pass 55*387f9dfdSAndroid Build Coastguard Worker try: del b[b"stub2"][c_ulonglong(1 << i)] 56*387f9dfdSAndroid Build Coastguard Worker except: pass 57*387f9dfdSAndroid Build Coastguard Worker b[b"hist1"].print_log2_hist() 58*387f9dfdSAndroid Build Coastguard Worker b.cleanup() 59*387f9dfdSAndroid Build Coastguard Worker 60*387f9dfdSAndroid Build Coastguard Worker def test_chars(self): 61*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=b""" 62*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 63*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 64*387f9dfdSAndroid Build Coastguard Worker#include <linux/version.h> 65*387f9dfdSAndroid Build Coastguard Workertypedef struct { char name[TASK_COMM_LEN]; u64 slot; } Key; 66*387f9dfdSAndroid Build Coastguard WorkerBPF_HISTOGRAM(hist1, Key, 1024); 67*387f9dfdSAndroid Build Coastguard Workerint kprobe__finish_task_switch(struct pt_regs *ctx, struct task_struct *prev) { 68*387f9dfdSAndroid Build Coastguard Worker#if LINUX_VERSION_CODE < KERNEL_VERSION(5,5,0) 69*387f9dfdSAndroid Build Coastguard Worker Key k = {.slot = bpf_log2l(prev->real_start_time)}; 70*387f9dfdSAndroid Build Coastguard Worker#else 71*387f9dfdSAndroid Build Coastguard Worker Key k = {.slot = bpf_log2l(prev->start_boottime)}; 72*387f9dfdSAndroid Build Coastguard Worker#endif 73*387f9dfdSAndroid Build Coastguard Worker if (!bpf_get_current_comm(&k.name, sizeof(k.name))) { 74*387f9dfdSAndroid Build Coastguard Worker hist1.increment(k); 75*387f9dfdSAndroid Build Coastguard Worker hist1.atomic_increment(k); 76*387f9dfdSAndroid Build Coastguard Worker } 77*387f9dfdSAndroid Build Coastguard Worker return 0; 78*387f9dfdSAndroid Build Coastguard Worker} 79*387f9dfdSAndroid Build Coastguard Worker""") 80*387f9dfdSAndroid Build Coastguard Worker for i in range(0, 100): time.sleep(0.01) 81*387f9dfdSAndroid Build Coastguard Worker b[b"hist1"].print_log2_hist() 82*387f9dfdSAndroid Build Coastguard Worker b.cleanup() 83*387f9dfdSAndroid Build Coastguard Worker 84*387f9dfdSAndroid Build Coastguard Worker def test_multiple_key(self): 85*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=b""" 86*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 87*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/fs.h> 88*387f9dfdSAndroid Build Coastguard Workerstruct hist_s_key { 89*387f9dfdSAndroid Build Coastguard Worker u64 key_1; 90*387f9dfdSAndroid Build Coastguard Worker u64 key_2; 91*387f9dfdSAndroid Build Coastguard Worker}; 92*387f9dfdSAndroid Build Coastguard Workerstruct hist_key { 93*387f9dfdSAndroid Build Coastguard Worker struct hist_s_key s_key; 94*387f9dfdSAndroid Build Coastguard Worker u64 slot; 95*387f9dfdSAndroid Build Coastguard Worker}; 96*387f9dfdSAndroid Build Coastguard WorkerBPF_HISTOGRAM(mk_hist, struct hist_key, 1024); 97*387f9dfdSAndroid Build Coastguard Workerint kprobe__vfs_read(struct pt_regs *ctx, struct file *file, 98*387f9dfdSAndroid Build Coastguard Worker char __user *buf, size_t count) { 99*387f9dfdSAndroid Build Coastguard Worker struct hist_key key = {.slot = bpf_log2l(count)}; 100*387f9dfdSAndroid Build Coastguard Worker key.s_key.key_1 = (unsigned long)buf & 0x70; 101*387f9dfdSAndroid Build Coastguard Worker key.s_key.key_2 = (unsigned long)buf & 0x7; 102*387f9dfdSAndroid Build Coastguard Worker mk_hist.increment(key); 103*387f9dfdSAndroid Build Coastguard Worker return 0; 104*387f9dfdSAndroid Build Coastguard Worker} 105*387f9dfdSAndroid Build Coastguard Worker""") 106*387f9dfdSAndroid Build Coastguard Worker def bucket_sort(buckets): 107*387f9dfdSAndroid Build Coastguard Worker buckets.sort() 108*387f9dfdSAndroid Build Coastguard Worker return buckets 109*387f9dfdSAndroid Build Coastguard Worker 110*387f9dfdSAndroid Build Coastguard Worker for i in range(0, 100): time.sleep(0.01) 111*387f9dfdSAndroid Build Coastguard Worker b[b"mk_hist"].print_log2_hist("size", "k_1 & k_2", 112*387f9dfdSAndroid Build Coastguard Worker section_print_fn=lambda bucket: "%3d %d" % (bucket[0], bucket[1]), 113*387f9dfdSAndroid Build Coastguard Worker bucket_fn=lambda bucket: (bucket.key_1, bucket.key_2), 114*387f9dfdSAndroid Build Coastguard Worker strip_leading_zero=True, 115*387f9dfdSAndroid Build Coastguard Worker bucket_sort_fn=bucket_sort) 116*387f9dfdSAndroid Build Coastguard Worker b.cleanup() 117*387f9dfdSAndroid Build Coastguard Worker 118*387f9dfdSAndroid Build Coastguard Workerif __name__ == "__main__": 119*387f9dfdSAndroid Build Coastguard Worker main() 120