1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2021 Facebook */ 3 4 #include <errno.h> 5 #include <linux/bpf.h> 6 #include <stdbool.h> 7 #include <bpf/bpf_helpers.h> 8 #include "bpf_misc.h" 9 10 char _license[] SEC("license") = "GPL"; 11 12 struct bpf_map; 13 14 __u8 rand_vals[2500000]; 15 const __u32 nr_rand_bytes = 2500000; 16 17 struct { 18 __uint(type, BPF_MAP_TYPE_ARRAY); 19 __uint(key_size, sizeof(__u32)); 20 /* max entries and value_size will be set programmatically. 21 * They are configurable from the userspace bench program. 22 */ 23 } array_map SEC(".maps"); 24 25 struct { 26 __uint(type, BPF_MAP_TYPE_BLOOM_FILTER); 27 /* max entries, value_size, and # of hash functions will be set 28 * programmatically. They are configurable from the userspace 29 * bench program. 30 */ 31 __uint(map_extra, 3); 32 } bloom_map SEC(".maps"); 33 34 struct { 35 __uint(type, BPF_MAP_TYPE_HASH); 36 /* max entries, key_size, and value_size, will be set 37 * programmatically. They are configurable from the userspace 38 * bench program. 39 */ 40 } hashmap SEC(".maps"); 41 42 struct callback_ctx { 43 struct bpf_map *map; 44 bool update; 45 }; 46 47 /* Tracks the number of hits, drops, and false hits */ 48 struct { 49 __u32 stats[3]; 50 } __attribute__((__aligned__(256))) percpu_stats[256]; 51 52 const __u32 hit_key = 0; 53 const __u32 drop_key = 1; 54 const __u32 false_hit_key = 2; 55 56 __u8 value_size; 57 58 const volatile bool hashmap_use_bloom; 59 const volatile bool count_false_hits; 60 61 int error = 0; 62 63 static __always_inline void log_result(__u32 key) 64 { 65 __u32 cpu = bpf_get_smp_processor_id(); 66 67 percpu_stats[cpu & 255].stats[key]++; 68 } 69 70 static __u64 71 bloom_callback(struct bpf_map *map, __u32 *key, void *val, 72 struct callback_ctx *data) 73 { 74 int err; 75 76 if (data->update) 77 err = bpf_map_push_elem(data->map, val, 0); 78 else 79 err = bpf_map_peek_elem(data->map, val); 80 81 if (err) { 82 error |= 1; 83 return 1; /* stop the iteration */ 84 } 85 86 log_result(hit_key); 87 88 return 0; 89 } 90 91 SEC("fentry/" SYS_PREFIX "sys_getpgid") 92 int bloom_lookup(void *ctx) 93 { 94 struct callback_ctx data; 95 96 data.map = (struct bpf_map *)&bloom_map; 97 data.update = false; 98 99 bpf_for_each_map_elem(&array_map, bloom_callback, &data, 0); 100 101 return 0; 102 } 103 104 SEC("fentry/" SYS_PREFIX "sys_getpgid") 105 int bloom_update(void *ctx) 106 { 107 struct callback_ctx data; 108 109 data.map = (struct bpf_map *)&bloom_map; 110 data.update = true; 111 112 bpf_for_each_map_elem(&array_map, bloom_callback, &data, 0); 113 114 return 0; 115 } 116 117 SEC("fentry/" SYS_PREFIX "sys_getpgid") 118 int bloom_hashmap_lookup(void *ctx) 119 { 120 __u64 *result; 121 int i, err; 122 123 __u32 index = bpf_get_prandom_u32(); 124 __u32 bitmask = (1ULL << 21) - 1; 125 126 for (i = 0; i < 1024; i++, index += value_size) { 127 index = index & bitmask; 128 129 if (hashmap_use_bloom) { 130 err = bpf_map_peek_elem(&bloom_map, 131 rand_vals + index); 132 if (err) { 133 if (err != -ENOENT) { 134 error |= 2; 135 return 0; 136 } 137 log_result(hit_key); 138 continue; 139 } 140 } 141 142 result = bpf_map_lookup_elem(&hashmap, 143 rand_vals + index); 144 if (result) { 145 log_result(hit_key); 146 } else { 147 if (hashmap_use_bloom && count_false_hits) 148 log_result(false_hit_key); 149 log_result(drop_key); 150 } 151 } 152 153 return 0; 154 } 155