Alexei Starovoitov | 5c7fc2d | 2015-03-25 12:49:25 -0700 | [diff] [blame] | 1 | /* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com |
| 2 | * |
| 3 | * This program is free software; you can redistribute it and/or |
| 4 | * modify it under the terms of version 2 of the GNU General Public |
| 5 | * License as published by the Free Software Foundation. |
| 6 | */ |
| 7 | #include <linux/skbuff.h> |
| 8 | #include <linux/netdevice.h> |
| 9 | #include <linux/version.h> |
| 10 | #include <uapi/linux/bpf.h> |
Toke Høiland-Jørgensen | 7cf245a | 2020-01-20 14:06:49 +0100 | [diff] [blame] | 11 | #include <bpf/bpf_helpers.h> |
| 12 | #include <bpf/bpf_tracing.h> |
Alexei Starovoitov | 5c7fc2d | 2015-03-25 12:49:25 -0700 | [diff] [blame] | 13 | |
Daniel T. Lee | 59929cd | 2020-05-16 13:06:08 +0900 | [diff] [blame] | 14 | struct { |
| 15 | __uint(type, BPF_MAP_TYPE_HASH); |
| 16 | __type(key, long); |
| 17 | __type(value, u64); |
| 18 | __uint(max_entries, 4096); |
| 19 | } my_map SEC(".maps"); |
Alexei Starovoitov | 5c7fc2d | 2015-03-25 12:49:25 -0700 | [diff] [blame] | 20 | |
| 21 | /* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe |
| 22 | * example will no longer be meaningful |
| 23 | */ |
Daniel T. Lee | d2e614c | 2019-02-27 02:52:26 -0500 | [diff] [blame] | 24 | SEC("kprobe/blk_mq_start_request") |
Alexei Starovoitov | 5c7fc2d | 2015-03-25 12:49:25 -0700 | [diff] [blame] | 25 | int bpf_prog1(struct pt_regs *ctx) |
| 26 | { |
Michael Holzheu | d912557 | 2015-07-06 16:20:07 +0200 | [diff] [blame] | 27 | long rq = PT_REGS_PARM1(ctx); |
Alexei Starovoitov | 5c7fc2d | 2015-03-25 12:49:25 -0700 | [diff] [blame] | 28 | u64 val = bpf_ktime_get_ns(); |
| 29 | |
| 30 | bpf_map_update_elem(&my_map, &rq, &val, BPF_ANY); |
| 31 | return 0; |
| 32 | } |
| 33 | |
| 34 | static unsigned int log2l(unsigned long long n) |
| 35 | { |
| 36 | #define S(k) if (n >= (1ull << k)) { i += k; n >>= k; } |
| 37 | int i = -(n == 0); |
| 38 | S(32); S(16); S(8); S(4); S(2); S(1); |
| 39 | return i; |
| 40 | #undef S |
| 41 | } |
| 42 | |
| 43 | #define SLOTS 100 |
| 44 | |
Daniel T. Lee | 59929cd | 2020-05-16 13:06:08 +0900 | [diff] [blame] | 45 | struct { |
| 46 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); |
| 47 | __uint(key_size, sizeof(u32)); |
| 48 | __uint(value_size, sizeof(u64)); |
| 49 | __uint(max_entries, SLOTS); |
| 50 | } lat_map SEC(".maps"); |
Alexei Starovoitov | 5c7fc2d | 2015-03-25 12:49:25 -0700 | [diff] [blame] | 51 | |
Daniel T. Lee | 2bf8c7e | 2020-08-18 14:16:41 +0900 | [diff] [blame] | 52 | SEC("kprobe/blk_account_io_done") |
Alexei Starovoitov | 5c7fc2d | 2015-03-25 12:49:25 -0700 | [diff] [blame] | 53 | int bpf_prog2(struct pt_regs *ctx) |
| 54 | { |
Michael Holzheu | d912557 | 2015-07-06 16:20:07 +0200 | [diff] [blame] | 55 | long rq = PT_REGS_PARM1(ctx); |
Alexei Starovoitov | 5c7fc2d | 2015-03-25 12:49:25 -0700 | [diff] [blame] | 56 | u64 *value, l, base; |
| 57 | u32 index; |
| 58 | |
| 59 | value = bpf_map_lookup_elem(&my_map, &rq); |
| 60 | if (!value) |
| 61 | return 0; |
| 62 | |
| 63 | u64 cur_time = bpf_ktime_get_ns(); |
| 64 | u64 delta = cur_time - *value; |
| 65 | |
| 66 | bpf_map_delete_elem(&my_map, &rq); |
| 67 | |
| 68 | /* the lines below are computing index = log10(delta)*10 |
| 69 | * using integer arithmetic |
| 70 | * index = 29 ~ 1 usec |
| 71 | * index = 59 ~ 1 msec |
| 72 | * index = 89 ~ 1 sec |
| 73 | * index = 99 ~ 10sec or more |
| 74 | * log10(x)*10 = log2(x)*10/log2(10) = log2(x)*3 |
| 75 | */ |
| 76 | l = log2l(delta); |
| 77 | base = 1ll << l; |
| 78 | index = (l * 64 + (delta - base) * 64 / base) * 3 / 64; |
| 79 | |
| 80 | if (index >= SLOTS) |
| 81 | index = SLOTS - 1; |
| 82 | |
| 83 | value = bpf_map_lookup_elem(&lat_map, &index); |
| 84 | if (value) |
Alexei Starovoitov | 3059303 | 2016-02-01 22:39:58 -0800 | [diff] [blame] | 85 | *value += 1; |
Alexei Starovoitov | 5c7fc2d | 2015-03-25 12:49:25 -0700 | [diff] [blame] | 86 | |
| 87 | return 0; |
| 88 | } |
| 89 | char _license[] SEC("license") = "GPL"; |
| 90 | u32 _version SEC("version") = LINUX_VERSION_CODE; |