125763b3cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 226e90931SAlexei Starovoitov /* Copyright (c) 2016 Facebook 326e90931SAlexei Starovoitov */ 426e90931SAlexei Starovoitov #define _GNU_SOURCE 526e90931SAlexei Starovoitov #include <sched.h> 626e90931SAlexei Starovoitov #include <stdio.h> 726e90931SAlexei Starovoitov #include <sys/types.h> 826e90931SAlexei Starovoitov #include <asm/unistd.h> 926e90931SAlexei Starovoitov #include <unistd.h> 1026e90931SAlexei Starovoitov #include <assert.h> 1126e90931SAlexei Starovoitov #include <sys/wait.h> 1226e90931SAlexei Starovoitov #include <stdlib.h> 1326e90931SAlexei Starovoitov #include <signal.h> 1426e90931SAlexei Starovoitov #include <string.h> 1526e90931SAlexei Starovoitov #include <time.h> 16bf8db5d2SMartin KaFai Lau #include <arpa/inet.h> 17bf8db5d2SMartin KaFai Lau #include <errno.h> 18bf8db5d2SMartin KaFai Lau 192bf3e2efSJakub Kicinski #include <bpf/bpf.h> 20cc7f641dSDaniel T. Lee #include <bpf/libbpf.h> 2126e90931SAlexei Starovoitov 229fd63d05SMartin KaFai Lau #define TEST_BIT(t) (1U << (t)) 233a5795b8SMartin KaFai Lau #define MAX_NR_CPUS 1024 2426e90931SAlexei Starovoitov 2526e90931SAlexei Starovoitov static __u64 time_get_ns(void) 2626e90931SAlexei Starovoitov { 2726e90931SAlexei Starovoitov struct timespec ts; 2826e90931SAlexei Starovoitov 2926e90931SAlexei Starovoitov clock_gettime(CLOCK_MONOTONIC, &ts); 3026e90931SAlexei Starovoitov return ts.tv_sec * 1000000000ull + ts.tv_nsec; 3126e90931SAlexei Starovoitov } 3226e90931SAlexei Starovoitov 339fd63d05SMartin KaFai Lau enum test_type { 349fd63d05SMartin KaFai Lau HASH_PREALLOC, 359fd63d05SMartin KaFai Lau PERCPU_HASH_PREALLOC, 369fd63d05SMartin KaFai Lau HASH_KMALLOC, 379fd63d05SMartin KaFai Lau PERCPU_HASH_KMALLOC, 389fd63d05SMartin KaFai Lau LRU_HASH_PREALLOC, 399fd63d05SMartin KaFai Lau NOCOMMON_LRU_HASH_PREALLOC, 409fd63d05SMartin KaFai Lau LPM_KMALLOC, 419fd63d05SMartin KaFai Lau HASH_LOOKUP, 429fd63d05SMartin KaFai Lau ARRAY_LOOKUP, 433a5795b8SMartin KaFai Lau INNER_LRU_HASH_PREALLOC, 44637cd8c3SMartin KaFai Lau LRU_HASH_LOOKUP, 459fd63d05SMartin KaFai Lau NR_TESTS, 469fd63d05SMartin KaFai Lau }; 479fd63d05SMartin KaFai Lau 489fd63d05SMartin KaFai Lau const char *test_map_names[NR_TESTS] = { 499fd63d05SMartin KaFai Lau [HASH_PREALLOC] = "hash_map", 509fd63d05SMartin KaFai Lau [PERCPU_HASH_PREALLOC] = "percpu_hash_map", 519fd63d05SMartin KaFai Lau [HASH_KMALLOC] = "hash_map_alloc", 529fd63d05SMartin KaFai Lau [PERCPU_HASH_KMALLOC] = "percpu_hash_map_alloc", 539fd63d05SMartin KaFai Lau [LRU_HASH_PREALLOC] = "lru_hash_map", 549fd63d05SMartin KaFai Lau [NOCOMMON_LRU_HASH_PREALLOC] = "nocommon_lru_hash_map", 559fd63d05SMartin KaFai Lau [LPM_KMALLOC] = "lpm_trie_map_alloc", 569fd63d05SMartin KaFai Lau [HASH_LOOKUP] = "hash_map", 579fd63d05SMartin KaFai Lau [ARRAY_LOOKUP] = "array_map", 583a5795b8SMartin KaFai Lau [INNER_LRU_HASH_PREALLOC] = "inner_lru_hash_map", 59637cd8c3SMartin KaFai Lau [LRU_HASH_LOOKUP] = "lru_hash_lookup_map", 609fd63d05SMartin KaFai Lau }; 6126e90931SAlexei Starovoitov 62cc7f641dSDaniel T. Lee enum map_idx { 63cc7f641dSDaniel T. Lee array_of_lru_hashs_idx, 64cc7f641dSDaniel T. Lee hash_map_alloc_idx, 65cc7f641dSDaniel T. Lee lru_hash_lookup_idx, 66cc7f641dSDaniel T. Lee NR_IDXES, 67cc7f641dSDaniel T. Lee }; 68cc7f641dSDaniel T. Lee 69cc7f641dSDaniel T. Lee static int map_fd[NR_IDXES]; 70cc7f641dSDaniel T. Lee 7126e90931SAlexei Starovoitov static int test_flags = ~0; 729fd63d05SMartin KaFai Lau static uint32_t num_map_entries; 733a5795b8SMartin KaFai Lau static uint32_t inner_lru_hash_size; 74637cd8c3SMartin KaFai Lau static int lru_hash_lookup_test_entries = 32; 7589dc8d0cSAlexei Starovoitov static uint32_t max_cnt = 10000; 769fd63d05SMartin KaFai Lau 779fd63d05SMartin KaFai Lau static int check_test_flags(enum test_type t) 789fd63d05SMartin KaFai Lau { 799fd63d05SMartin KaFai Lau return test_flags & TEST_BIT(t); 809fd63d05SMartin KaFai Lau } 8126e90931SAlexei Starovoitov 8226e90931SAlexei Starovoitov static void test_hash_prealloc(int cpu) 8326e90931SAlexei Starovoitov { 8426e90931SAlexei Starovoitov __u64 start_time; 8526e90931SAlexei Starovoitov int i; 8626e90931SAlexei Starovoitov 8726e90931SAlexei Starovoitov start_time = time_get_ns(); 889fd63d05SMartin KaFai Lau for (i = 0; i < max_cnt; i++) 8926e90931SAlexei Starovoitov syscall(__NR_getuid); 9026e90931SAlexei Starovoitov printf("%d:hash_map_perf pre-alloc %lld events per sec\n", 919fd63d05SMartin KaFai Lau cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 9226e90931SAlexei Starovoitov } 9326e90931SAlexei Starovoitov 94637cd8c3SMartin KaFai Lau static int pre_test_lru_hash_lookup(int tasks) 95637cd8c3SMartin KaFai Lau { 96637cd8c3SMartin KaFai Lau int fd = map_fd[lru_hash_lookup_idx]; 97637cd8c3SMartin KaFai Lau uint32_t key; 98637cd8c3SMartin KaFai Lau long val = 1; 99637cd8c3SMartin KaFai Lau int ret; 100637cd8c3SMartin KaFai Lau 101637cd8c3SMartin KaFai Lau if (num_map_entries > lru_hash_lookup_test_entries) 102637cd8c3SMartin KaFai Lau lru_hash_lookup_test_entries = num_map_entries; 103637cd8c3SMartin KaFai Lau 104637cd8c3SMartin KaFai Lau /* Populate the lru_hash_map for LRU_HASH_LOOKUP perf test. 105637cd8c3SMartin KaFai Lau * 106637cd8c3SMartin KaFai Lau * It is fine that the user requests for a map with 107637cd8c3SMartin KaFai Lau * num_map_entries < 32 and some of the later lru hash lookup 108637cd8c3SMartin KaFai Lau * may return not found. For LRU map, we are not interested 109637cd8c3SMartin KaFai Lau * in such small map performance. 110637cd8c3SMartin KaFai Lau */ 111637cd8c3SMartin KaFai Lau for (key = 0; key < lru_hash_lookup_test_entries; key++) { 112637cd8c3SMartin KaFai Lau ret = bpf_map_update_elem(fd, &key, &val, BPF_NOEXIST); 113637cd8c3SMartin KaFai Lau if (ret) 114637cd8c3SMartin KaFai Lau return ret; 115637cd8c3SMartin KaFai Lau } 116637cd8c3SMartin KaFai Lau 117637cd8c3SMartin KaFai Lau return 0; 118637cd8c3SMartin KaFai Lau } 119637cd8c3SMartin KaFai Lau 1209fd63d05SMartin KaFai Lau static void do_test_lru(enum test_type test, int cpu) 1215db58fafSMartin KaFai Lau { 1223a5795b8SMartin KaFai Lau static int inner_lru_map_fds[MAX_NR_CPUS]; 1233a5795b8SMartin KaFai Lau 124bf8db5d2SMartin KaFai Lau struct sockaddr_in6 in6 = { .sin6_family = AF_INET6 }; 125bf8db5d2SMartin KaFai Lau const char *test_name; 1265db58fafSMartin KaFai Lau __u64 start_time; 127bf8db5d2SMartin KaFai Lau int i, ret; 1285db58fafSMartin KaFai Lau 129cc7f641dSDaniel T. Lee if (test == INNER_LRU_HASH_PREALLOC && cpu) { 130cc7f641dSDaniel T. Lee /* If CPU is not 0, create inner_lru hash map and insert the fd 131cc7f641dSDaniel T. Lee * value into the array_of_lru_hash map. In case of CPU 0, 132cc7f641dSDaniel T. Lee * 'inner_lru_hash_map' was statically inserted on the map init 133cc7f641dSDaniel T. Lee */ 1343a5795b8SMartin KaFai Lau int outer_fd = map_fd[array_of_lru_hashs_idx]; 135ad17d0e6SMartin KaFai Lau unsigned int mycpu, mynode; 136c58f9815SAndrii Nakryiko LIBBPF_OPTS(bpf_map_create_opts, opts, 137c58f9815SAndrii Nakryiko .map_flags = BPF_F_NUMA_NODE, 138c58f9815SAndrii Nakryiko ); 1393a5795b8SMartin KaFai Lau 1403a5795b8SMartin KaFai Lau assert(cpu < MAX_NR_CPUS); 1413a5795b8SMartin KaFai Lau 142ad17d0e6SMartin KaFai Lau ret = syscall(__NR_getcpu, &mycpu, &mynode, NULL); 143ad17d0e6SMartin KaFai Lau assert(!ret); 144ad17d0e6SMartin KaFai Lau 145c58f9815SAndrii Nakryiko opts.numa_node = mynode; 1463a5795b8SMartin KaFai Lau inner_lru_map_fds[cpu] = 147c58f9815SAndrii Nakryiko bpf_map_create(BPF_MAP_TYPE_LRU_HASH, 14888cda1c9SMartin KaFai Lau test_map_names[INNER_LRU_HASH_PREALLOC], 149ad17d0e6SMartin KaFai Lau sizeof(uint32_t), 150ad17d0e6SMartin KaFai Lau sizeof(long), 151c58f9815SAndrii Nakryiko inner_lru_hash_size, &opts); 1523a5795b8SMartin KaFai Lau if (inner_lru_map_fds[cpu] == -1) { 1533a5795b8SMartin KaFai Lau printf("cannot create BPF_MAP_TYPE_LRU_HASH %s(%d)\n", 1543a5795b8SMartin KaFai Lau strerror(errno), errno); 1553a5795b8SMartin KaFai Lau exit(1); 1563a5795b8SMartin KaFai Lau } 1573a5795b8SMartin KaFai Lau 1583a5795b8SMartin KaFai Lau ret = bpf_map_update_elem(outer_fd, &cpu, 1593a5795b8SMartin KaFai Lau &inner_lru_map_fds[cpu], 1603a5795b8SMartin KaFai Lau BPF_ANY); 1613a5795b8SMartin KaFai Lau if (ret) { 1623a5795b8SMartin KaFai Lau printf("cannot update ARRAY_OF_LRU_HASHS with key:%u. %s(%d)\n", 1633a5795b8SMartin KaFai Lau cpu, strerror(errno), errno); 1643a5795b8SMartin KaFai Lau exit(1); 1653a5795b8SMartin KaFai Lau } 1663a5795b8SMartin KaFai Lau } 1673a5795b8SMartin KaFai Lau 168bf8db5d2SMartin KaFai Lau in6.sin6_addr.s6_addr16[0] = 0xdead; 169bf8db5d2SMartin KaFai Lau in6.sin6_addr.s6_addr16[1] = 0xbeef; 170bf8db5d2SMartin KaFai Lau 1719fd63d05SMartin KaFai Lau if (test == LRU_HASH_PREALLOC) { 172bf8db5d2SMartin KaFai Lau test_name = "lru_hash_map_perf"; 173637cd8c3SMartin KaFai Lau in6.sin6_addr.s6_addr16[2] = 0; 1749fd63d05SMartin KaFai Lau } else if (test == NOCOMMON_LRU_HASH_PREALLOC) { 175bf8db5d2SMartin KaFai Lau test_name = "nocommon_lru_hash_map_perf"; 176637cd8c3SMartin KaFai Lau in6.sin6_addr.s6_addr16[2] = 1; 1773a5795b8SMartin KaFai Lau } else if (test == INNER_LRU_HASH_PREALLOC) { 1783a5795b8SMartin KaFai Lau test_name = "inner_lru_hash_map_perf"; 179637cd8c3SMartin KaFai Lau in6.sin6_addr.s6_addr16[2] = 2; 180637cd8c3SMartin KaFai Lau } else if (test == LRU_HASH_LOOKUP) { 181637cd8c3SMartin KaFai Lau test_name = "lru_hash_lookup_perf"; 182637cd8c3SMartin KaFai Lau in6.sin6_addr.s6_addr16[2] = 3; 183637cd8c3SMartin KaFai Lau in6.sin6_addr.s6_addr32[3] = 0; 184bf8db5d2SMartin KaFai Lau } else { 185bf8db5d2SMartin KaFai Lau assert(0); 1865db58fafSMartin KaFai Lau } 1875db58fafSMartin KaFai Lau 1885db58fafSMartin KaFai Lau start_time = time_get_ns(); 1899fd63d05SMartin KaFai Lau for (i = 0; i < max_cnt; i++) { 190bf8db5d2SMartin KaFai Lau ret = connect(-1, (const struct sockaddr *)&in6, sizeof(in6)); 191bf8db5d2SMartin KaFai Lau assert(ret == -1 && errno == EBADF); 192637cd8c3SMartin KaFai Lau if (in6.sin6_addr.s6_addr32[3] < 193637cd8c3SMartin KaFai Lau lru_hash_lookup_test_entries - 32) 194637cd8c3SMartin KaFai Lau in6.sin6_addr.s6_addr32[3] += 32; 195637cd8c3SMartin KaFai Lau else 196637cd8c3SMartin KaFai Lau in6.sin6_addr.s6_addr32[3] = 0; 197bf8db5d2SMartin KaFai Lau } 198bf8db5d2SMartin KaFai Lau printf("%d:%s pre-alloc %lld events per sec\n", 199bf8db5d2SMartin KaFai Lau cpu, test_name, 2009fd63d05SMartin KaFai Lau max_cnt * 1000000000ll / (time_get_ns() - start_time)); 201bf8db5d2SMartin KaFai Lau } 202bf8db5d2SMartin KaFai Lau 203bf8db5d2SMartin KaFai Lau static void test_lru_hash_prealloc(int cpu) 204bf8db5d2SMartin KaFai Lau { 205bf8db5d2SMartin KaFai Lau do_test_lru(LRU_HASH_PREALLOC, cpu); 206bf8db5d2SMartin KaFai Lau } 207bf8db5d2SMartin KaFai Lau 208bf8db5d2SMartin KaFai Lau static void test_nocommon_lru_hash_prealloc(int cpu) 209bf8db5d2SMartin KaFai Lau { 210bf8db5d2SMartin KaFai Lau do_test_lru(NOCOMMON_LRU_HASH_PREALLOC, cpu); 2115db58fafSMartin KaFai Lau } 2125db58fafSMartin KaFai Lau 2133a5795b8SMartin KaFai Lau static void test_inner_lru_hash_prealloc(int cpu) 2143a5795b8SMartin KaFai Lau { 2153a5795b8SMartin KaFai Lau do_test_lru(INNER_LRU_HASH_PREALLOC, cpu); 2163a5795b8SMartin KaFai Lau } 2173a5795b8SMartin KaFai Lau 218637cd8c3SMartin KaFai Lau static void test_lru_hash_lookup(int cpu) 219637cd8c3SMartin KaFai Lau { 220637cd8c3SMartin KaFai Lau do_test_lru(LRU_HASH_LOOKUP, cpu); 221637cd8c3SMartin KaFai Lau } 222637cd8c3SMartin KaFai Lau 22326e90931SAlexei Starovoitov static void test_percpu_hash_prealloc(int cpu) 22426e90931SAlexei Starovoitov { 22526e90931SAlexei Starovoitov __u64 start_time; 22626e90931SAlexei Starovoitov int i; 22726e90931SAlexei Starovoitov 22826e90931SAlexei Starovoitov start_time = time_get_ns(); 2299fd63d05SMartin KaFai Lau for (i = 0; i < max_cnt; i++) 23026e90931SAlexei Starovoitov syscall(__NR_geteuid); 23126e90931SAlexei Starovoitov printf("%d:percpu_hash_map_perf pre-alloc %lld events per sec\n", 2329fd63d05SMartin KaFai Lau cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 23326e90931SAlexei Starovoitov } 23426e90931SAlexei Starovoitov 23526e90931SAlexei Starovoitov static void test_hash_kmalloc(int cpu) 23626e90931SAlexei Starovoitov { 23726e90931SAlexei Starovoitov __u64 start_time; 23826e90931SAlexei Starovoitov int i; 23926e90931SAlexei Starovoitov 24026e90931SAlexei Starovoitov start_time = time_get_ns(); 2419fd63d05SMartin KaFai Lau for (i = 0; i < max_cnt; i++) 24226e90931SAlexei Starovoitov syscall(__NR_getgid); 24326e90931SAlexei Starovoitov printf("%d:hash_map_perf kmalloc %lld events per sec\n", 2449fd63d05SMartin KaFai Lau cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 24526e90931SAlexei Starovoitov } 24626e90931SAlexei Starovoitov 24726e90931SAlexei Starovoitov static void test_percpu_hash_kmalloc(int cpu) 24826e90931SAlexei Starovoitov { 24926e90931SAlexei Starovoitov __u64 start_time; 25026e90931SAlexei Starovoitov int i; 25126e90931SAlexei Starovoitov 25226e90931SAlexei Starovoitov start_time = time_get_ns(); 2539fd63d05SMartin KaFai Lau for (i = 0; i < max_cnt; i++) 25426e90931SAlexei Starovoitov syscall(__NR_getegid); 25526e90931SAlexei Starovoitov printf("%d:percpu_hash_map_perf kmalloc %lld events per sec\n", 2569fd63d05SMartin KaFai Lau cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 25726e90931SAlexei Starovoitov } 25826e90931SAlexei Starovoitov 259b8a943e2SDavid Herrmann static void test_lpm_kmalloc(int cpu) 260b8a943e2SDavid Herrmann { 261b8a943e2SDavid Herrmann __u64 start_time; 262b8a943e2SDavid Herrmann int i; 263b8a943e2SDavid Herrmann 264b8a943e2SDavid Herrmann start_time = time_get_ns(); 2659fd63d05SMartin KaFai Lau for (i = 0; i < max_cnt; i++) 266b8a943e2SDavid Herrmann syscall(__NR_gettid); 267b8a943e2SDavid Herrmann printf("%d:lpm_perf kmalloc %lld events per sec\n", 2689fd63d05SMartin KaFai Lau cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 269b8a943e2SDavid Herrmann } 270b8a943e2SDavid Herrmann 27195ff141eSAlexei Starovoitov static void test_hash_lookup(int cpu) 27295ff141eSAlexei Starovoitov { 27395ff141eSAlexei Starovoitov __u64 start_time; 27495ff141eSAlexei Starovoitov int i; 27595ff141eSAlexei Starovoitov 27695ff141eSAlexei Starovoitov start_time = time_get_ns(); 2779fd63d05SMartin KaFai Lau for (i = 0; i < max_cnt; i++) 27895ff141eSAlexei Starovoitov syscall(__NR_getpgid, 0); 27995ff141eSAlexei Starovoitov printf("%d:hash_lookup %lld lookups per sec\n", 2809fd63d05SMartin KaFai Lau cpu, max_cnt * 1000000000ll * 64 / (time_get_ns() - start_time)); 28195ff141eSAlexei Starovoitov } 28295ff141eSAlexei Starovoitov 28395ff141eSAlexei Starovoitov static void test_array_lookup(int cpu) 28495ff141eSAlexei Starovoitov { 28595ff141eSAlexei Starovoitov __u64 start_time; 28695ff141eSAlexei Starovoitov int i; 28795ff141eSAlexei Starovoitov 28895ff141eSAlexei Starovoitov start_time = time_get_ns(); 2899fd63d05SMartin KaFai Lau for (i = 0; i < max_cnt; i++) 29095ec6696SJoel Fernandes syscall(__NR_getppid, 0); 29195ff141eSAlexei Starovoitov printf("%d:array_lookup %lld lookups per sec\n", 2929fd63d05SMartin KaFai Lau cpu, max_cnt * 1000000000ll * 64 / (time_get_ns() - start_time)); 29395ff141eSAlexei Starovoitov } 29495ff141eSAlexei Starovoitov 295637cd8c3SMartin KaFai Lau typedef int (*pre_test_func)(int tasks); 296637cd8c3SMartin KaFai Lau const pre_test_func pre_test_funcs[] = { 297637cd8c3SMartin KaFai Lau [LRU_HASH_LOOKUP] = pre_test_lru_hash_lookup, 298637cd8c3SMartin KaFai Lau }; 299637cd8c3SMartin KaFai Lau 3009fd63d05SMartin KaFai Lau typedef void (*test_func)(int cpu); 3019fd63d05SMartin KaFai Lau const test_func test_funcs[] = { 3029fd63d05SMartin KaFai Lau [HASH_PREALLOC] = test_hash_prealloc, 3039fd63d05SMartin KaFai Lau [PERCPU_HASH_PREALLOC] = test_percpu_hash_prealloc, 3049fd63d05SMartin KaFai Lau [HASH_KMALLOC] = test_hash_kmalloc, 3059fd63d05SMartin KaFai Lau [PERCPU_HASH_KMALLOC] = test_percpu_hash_kmalloc, 3069fd63d05SMartin KaFai Lau [LRU_HASH_PREALLOC] = test_lru_hash_prealloc, 3079fd63d05SMartin KaFai Lau [NOCOMMON_LRU_HASH_PREALLOC] = test_nocommon_lru_hash_prealloc, 3089fd63d05SMartin KaFai Lau [LPM_KMALLOC] = test_lpm_kmalloc, 3099fd63d05SMartin KaFai Lau [HASH_LOOKUP] = test_hash_lookup, 3109fd63d05SMartin KaFai Lau [ARRAY_LOOKUP] = test_array_lookup, 3113a5795b8SMartin KaFai Lau [INNER_LRU_HASH_PREALLOC] = test_inner_lru_hash_prealloc, 312637cd8c3SMartin KaFai Lau [LRU_HASH_LOOKUP] = test_lru_hash_lookup, 3139fd63d05SMartin KaFai Lau }; 3149fd63d05SMartin KaFai Lau 315637cd8c3SMartin KaFai Lau static int pre_test(int tasks) 316637cd8c3SMartin KaFai Lau { 317637cd8c3SMartin KaFai Lau int i; 318637cd8c3SMartin KaFai Lau 319637cd8c3SMartin KaFai Lau for (i = 0; i < NR_TESTS; i++) { 320637cd8c3SMartin KaFai Lau if (pre_test_funcs[i] && check_test_flags(i)) { 321637cd8c3SMartin KaFai Lau int ret = pre_test_funcs[i](tasks); 322637cd8c3SMartin KaFai Lau 323637cd8c3SMartin KaFai Lau if (ret) 324637cd8c3SMartin KaFai Lau return ret; 325637cd8c3SMartin KaFai Lau } 326637cd8c3SMartin KaFai Lau } 327637cd8c3SMartin KaFai Lau 328637cd8c3SMartin KaFai Lau return 0; 329637cd8c3SMartin KaFai Lau } 330637cd8c3SMartin KaFai Lau 33126e90931SAlexei Starovoitov static void loop(int cpu) 33226e90931SAlexei Starovoitov { 33326e90931SAlexei Starovoitov cpu_set_t cpuset; 3349fd63d05SMartin KaFai Lau int i; 33526e90931SAlexei Starovoitov 33626e90931SAlexei Starovoitov CPU_ZERO(&cpuset); 33726e90931SAlexei Starovoitov CPU_SET(cpu, &cpuset); 33826e90931SAlexei Starovoitov sched_setaffinity(0, sizeof(cpuset), &cpuset); 33926e90931SAlexei Starovoitov 3409fd63d05SMartin KaFai Lau for (i = 0; i < NR_TESTS; i++) { 3419fd63d05SMartin KaFai Lau if (check_test_flags(i)) 3429fd63d05SMartin KaFai Lau test_funcs[i](cpu); 3439fd63d05SMartin KaFai Lau } 34426e90931SAlexei Starovoitov } 34526e90931SAlexei Starovoitov 34626e90931SAlexei Starovoitov static void run_perf_test(int tasks) 34726e90931SAlexei Starovoitov { 34826e90931SAlexei Starovoitov pid_t pid[tasks]; 34926e90931SAlexei Starovoitov int i; 35026e90931SAlexei Starovoitov 351637cd8c3SMartin KaFai Lau assert(!pre_test(tasks)); 352637cd8c3SMartin KaFai Lau 35326e90931SAlexei Starovoitov for (i = 0; i < tasks; i++) { 35426e90931SAlexei Starovoitov pid[i] = fork(); 35526e90931SAlexei Starovoitov if (pid[i] == 0) { 35626e90931SAlexei Starovoitov loop(i); 35726e90931SAlexei Starovoitov exit(0); 35826e90931SAlexei Starovoitov } else if (pid[i] == -1) { 35926e90931SAlexei Starovoitov printf("couldn't spawn #%d process\n", i); 36026e90931SAlexei Starovoitov exit(1); 36126e90931SAlexei Starovoitov } 36226e90931SAlexei Starovoitov } 36326e90931SAlexei Starovoitov for (i = 0; i < tasks; i++) { 36426e90931SAlexei Starovoitov int status; 36526e90931SAlexei Starovoitov 36626e90931SAlexei Starovoitov assert(waitpid(pid[i], &status, 0) == pid[i]); 36726e90931SAlexei Starovoitov assert(status == 0); 36826e90931SAlexei Starovoitov } 36926e90931SAlexei Starovoitov } 37026e90931SAlexei Starovoitov 371b8a943e2SDavid Herrmann static void fill_lpm_trie(void) 372b8a943e2SDavid Herrmann { 373b8a943e2SDavid Herrmann struct bpf_lpm_trie_key *key; 374b8a943e2SDavid Herrmann unsigned long value = 0; 375b8a943e2SDavid Herrmann unsigned int i; 376b8a943e2SDavid Herrmann int r; 377b8a943e2SDavid Herrmann 378b8a943e2SDavid Herrmann key = alloca(sizeof(*key) + 4); 379b8a943e2SDavid Herrmann key->prefixlen = 32; 380b8a943e2SDavid Herrmann 381b8a943e2SDavid Herrmann for (i = 0; i < 512; ++i) { 382b8a943e2SDavid Herrmann key->prefixlen = rand() % 33; 383b8a943e2SDavid Herrmann key->data[0] = rand() & 0xff; 384b8a943e2SDavid Herrmann key->data[1] = rand() & 0xff; 385b8a943e2SDavid Herrmann key->data[2] = rand() & 0xff; 386b8a943e2SDavid Herrmann key->data[3] = rand() & 0xff; 387cc7f641dSDaniel T. Lee r = bpf_map_update_elem(map_fd[hash_map_alloc_idx], 388cc7f641dSDaniel T. Lee key, &value, 0); 389b8a943e2SDavid Herrmann assert(!r); 390b8a943e2SDavid Herrmann } 391b8a943e2SDavid Herrmann 392b8a943e2SDavid Herrmann key->prefixlen = 32; 393b8a943e2SDavid Herrmann key->data[0] = 192; 394b8a943e2SDavid Herrmann key->data[1] = 168; 395b8a943e2SDavid Herrmann key->data[2] = 0; 396b8a943e2SDavid Herrmann key->data[3] = 1; 397b8a943e2SDavid Herrmann value = 128; 398b8a943e2SDavid Herrmann 399cc7f641dSDaniel T. Lee r = bpf_map_update_elem(map_fd[hash_map_alloc_idx], key, &value, 0); 400b8a943e2SDavid Herrmann assert(!r); 401b8a943e2SDavid Herrmann } 402b8a943e2SDavid Herrmann 403cc7f641dSDaniel T. Lee static void fixup_map(struct bpf_object *obj) 4049fd63d05SMartin KaFai Lau { 405cc7f641dSDaniel T. Lee struct bpf_map *map; 4069fd63d05SMartin KaFai Lau int i; 4079fd63d05SMartin KaFai Lau 408cc7f641dSDaniel T. Lee bpf_object__for_each_map(map, obj) { 409cc7f641dSDaniel T. Lee const char *name = bpf_map__name(map); 4103a5795b8SMartin KaFai Lau 4119fd63d05SMartin KaFai Lau /* Only change the max_entries for the enabled test(s) */ 4129fd63d05SMartin KaFai Lau for (i = 0; i < NR_TESTS; i++) { 413cc7f641dSDaniel T. Lee if (!strcmp(test_map_names[i], name) && 4149fd63d05SMartin KaFai Lau (check_test_flags(i))) { 41561afd3daSAndrii Nakryiko bpf_map__set_max_entries(map, num_map_entries); 416cc7f641dSDaniel T. Lee continue; 4179fd63d05SMartin KaFai Lau } 4189fd63d05SMartin KaFai Lau } 4199fd63d05SMartin KaFai Lau } 4209fd63d05SMartin KaFai Lau 421cc7f641dSDaniel T. Lee inner_lru_hash_size = num_map_entries; 422cc7f641dSDaniel T. Lee } 423cc7f641dSDaniel T. Lee 42426e90931SAlexei Starovoitov int main(int argc, char **argv) 42526e90931SAlexei Starovoitov { 426cc7f641dSDaniel T. Lee int nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 427cc7f641dSDaniel T. Lee struct bpf_link *links[8]; 428cc7f641dSDaniel T. Lee struct bpf_program *prog; 429cc7f641dSDaniel T. Lee struct bpf_object *obj; 430cc7f641dSDaniel T. Lee struct bpf_map *map; 43126e90931SAlexei Starovoitov char filename[256]; 432cc7f641dSDaniel T. Lee int i = 0; 43326e90931SAlexei Starovoitov 43426e90931SAlexei Starovoitov if (argc > 1) 43526e90931SAlexei Starovoitov test_flags = atoi(argv[1]) ? : test_flags; 43626e90931SAlexei Starovoitov 43726e90931SAlexei Starovoitov if (argc > 2) 438cc7f641dSDaniel T. Lee nr_cpus = atoi(argv[2]) ? : nr_cpus; 43926e90931SAlexei Starovoitov 4409fd63d05SMartin KaFai Lau if (argc > 3) 4419fd63d05SMartin KaFai Lau num_map_entries = atoi(argv[3]); 4429fd63d05SMartin KaFai Lau 4439fd63d05SMartin KaFai Lau if (argc > 4) 4449fd63d05SMartin KaFai Lau max_cnt = atoi(argv[4]); 4459fd63d05SMartin KaFai Lau 446*d4fffba4SDaniel T. Lee snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); 447cc7f641dSDaniel T. Lee obj = bpf_object__open_file(filename, NULL); 448cc7f641dSDaniel T. Lee if (libbpf_get_error(obj)) { 449cc7f641dSDaniel T. Lee fprintf(stderr, "ERROR: opening BPF object file failed\n"); 450cc7f641dSDaniel T. Lee return 0; 451cc7f641dSDaniel T. Lee } 452cc7f641dSDaniel T. Lee 453cc7f641dSDaniel T. Lee map = bpf_object__find_map_by_name(obj, "inner_lru_hash_map"); 454cc7f641dSDaniel T. Lee if (libbpf_get_error(map)) { 455cc7f641dSDaniel T. Lee fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 456cc7f641dSDaniel T. Lee goto cleanup; 457cc7f641dSDaniel T. Lee } 458cc7f641dSDaniel T. Lee 459cc7f641dSDaniel T. Lee inner_lru_hash_size = bpf_map__max_entries(map); 460cc7f641dSDaniel T. Lee if (!inner_lru_hash_size) { 461cc7f641dSDaniel T. Lee fprintf(stderr, "ERROR: failed to get map attribute\n"); 462cc7f641dSDaniel T. Lee goto cleanup; 463cc7f641dSDaniel T. Lee } 464cc7f641dSDaniel T. Lee 465cc7f641dSDaniel T. Lee /* resize BPF map prior to loading */ 466cc7f641dSDaniel T. Lee if (num_map_entries > 0) 467cc7f641dSDaniel T. Lee fixup_map(obj); 468cc7f641dSDaniel T. Lee 469cc7f641dSDaniel T. Lee /* load BPF program */ 470cc7f641dSDaniel T. Lee if (bpf_object__load(obj)) { 471cc7f641dSDaniel T. Lee fprintf(stderr, "ERROR: loading BPF object file failed\n"); 472cc7f641dSDaniel T. Lee goto cleanup; 473cc7f641dSDaniel T. Lee } 474cc7f641dSDaniel T. Lee 475cc7f641dSDaniel T. Lee map_fd[0] = bpf_object__find_map_fd_by_name(obj, "array_of_lru_hashs"); 476cc7f641dSDaniel T. Lee map_fd[1] = bpf_object__find_map_fd_by_name(obj, "hash_map_alloc"); 477cc7f641dSDaniel T. Lee map_fd[2] = bpf_object__find_map_fd_by_name(obj, "lru_hash_lookup_map"); 478cc7f641dSDaniel T. Lee if (map_fd[0] < 0 || map_fd[1] < 0 || map_fd[2] < 0) { 479cc7f641dSDaniel T. Lee fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 480cc7f641dSDaniel T. Lee goto cleanup; 481cc7f641dSDaniel T. Lee } 482cc7f641dSDaniel T. Lee 483cc7f641dSDaniel T. Lee bpf_object__for_each_program(prog, obj) { 484cc7f641dSDaniel T. Lee links[i] = bpf_program__attach(prog); 485cc7f641dSDaniel T. Lee if (libbpf_get_error(links[i])) { 486cc7f641dSDaniel T. Lee fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 487cc7f641dSDaniel T. Lee links[i] = NULL; 488cc7f641dSDaniel T. Lee goto cleanup; 489cc7f641dSDaniel T. Lee } 490cc7f641dSDaniel T. Lee i++; 49126e90931SAlexei Starovoitov } 49226e90931SAlexei Starovoitov 493b8a943e2SDavid Herrmann fill_lpm_trie(); 494b8a943e2SDavid Herrmann 495cc7f641dSDaniel T. Lee run_perf_test(nr_cpus); 49626e90931SAlexei Starovoitov 497cc7f641dSDaniel T. Lee cleanup: 498cc7f641dSDaniel T. Lee for (i--; i >= 0; i--) 499cc7f641dSDaniel T. Lee bpf_link__destroy(links[i]); 500cc7f641dSDaniel T. Lee 501cc7f641dSDaniel T. Lee bpf_object__close(obj); 50226e90931SAlexei Starovoitov return 0; 50326e90931SAlexei Starovoitov } 504