18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* Copyright (c) 2016 Facebook 38c2ecf20Sopenharmony_ci */ 48c2ecf20Sopenharmony_ci#define _GNU_SOURCE 58c2ecf20Sopenharmony_ci#include <sched.h> 68c2ecf20Sopenharmony_ci#include <stdio.h> 78c2ecf20Sopenharmony_ci#include <sys/types.h> 88c2ecf20Sopenharmony_ci#include <asm/unistd.h> 98c2ecf20Sopenharmony_ci#include <unistd.h> 108c2ecf20Sopenharmony_ci#include <assert.h> 118c2ecf20Sopenharmony_ci#include <sys/wait.h> 128c2ecf20Sopenharmony_ci#include <stdlib.h> 138c2ecf20Sopenharmony_ci#include <signal.h> 148c2ecf20Sopenharmony_ci#include <string.h> 158c2ecf20Sopenharmony_ci#include <time.h> 168c2ecf20Sopenharmony_ci#include <sys/resource.h> 178c2ecf20Sopenharmony_ci#include <arpa/inet.h> 188c2ecf20Sopenharmony_ci#include <errno.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 218c2ecf20Sopenharmony_ci#include <bpf/libbpf.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define TEST_BIT(t) (1U << (t)) 248c2ecf20Sopenharmony_ci#define MAX_NR_CPUS 1024 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic __u64 time_get_ns(void) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci struct timespec ts; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &ts); 318c2ecf20Sopenharmony_ci return ts.tv_sec * 1000000000ull + ts.tv_nsec; 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cienum test_type { 358c2ecf20Sopenharmony_ci HASH_PREALLOC, 368c2ecf20Sopenharmony_ci PERCPU_HASH_PREALLOC, 378c2ecf20Sopenharmony_ci HASH_KMALLOC, 388c2ecf20Sopenharmony_ci PERCPU_HASH_KMALLOC, 398c2ecf20Sopenharmony_ci LRU_HASH_PREALLOC, 408c2ecf20Sopenharmony_ci NOCOMMON_LRU_HASH_PREALLOC, 418c2ecf20Sopenharmony_ci LPM_KMALLOC, 428c2ecf20Sopenharmony_ci HASH_LOOKUP, 438c2ecf20Sopenharmony_ci ARRAY_LOOKUP, 448c2ecf20Sopenharmony_ci INNER_LRU_HASH_PREALLOC, 458c2ecf20Sopenharmony_ci LRU_HASH_LOOKUP, 468c2ecf20Sopenharmony_ci NR_TESTS, 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ciconst char *test_map_names[NR_TESTS] = { 508c2ecf20Sopenharmony_ci [HASH_PREALLOC] = "hash_map", 518c2ecf20Sopenharmony_ci [PERCPU_HASH_PREALLOC] = "percpu_hash_map", 528c2ecf20Sopenharmony_ci [HASH_KMALLOC] = "hash_map_alloc", 538c2ecf20Sopenharmony_ci [PERCPU_HASH_KMALLOC] = "percpu_hash_map_alloc", 548c2ecf20Sopenharmony_ci [LRU_HASH_PREALLOC] = "lru_hash_map", 558c2ecf20Sopenharmony_ci [NOCOMMON_LRU_HASH_PREALLOC] = "nocommon_lru_hash_map", 568c2ecf20Sopenharmony_ci [LPM_KMALLOC] = "lpm_trie_map_alloc", 578c2ecf20Sopenharmony_ci [HASH_LOOKUP] = "hash_map", 588c2ecf20Sopenharmony_ci [ARRAY_LOOKUP] = "array_map", 598c2ecf20Sopenharmony_ci [INNER_LRU_HASH_PREALLOC] = "inner_lru_hash_map", 608c2ecf20Sopenharmony_ci [LRU_HASH_LOOKUP] = "lru_hash_lookup_map", 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cienum map_idx { 648c2ecf20Sopenharmony_ci array_of_lru_hashs_idx, 658c2ecf20Sopenharmony_ci hash_map_alloc_idx, 668c2ecf20Sopenharmony_ci lru_hash_lookup_idx, 678c2ecf20Sopenharmony_ci NR_IDXES, 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic int map_fd[NR_IDXES]; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic int test_flags = ~0; 738c2ecf20Sopenharmony_cistatic uint32_t num_map_entries; 748c2ecf20Sopenharmony_cistatic uint32_t inner_lru_hash_size; 758c2ecf20Sopenharmony_cistatic int lru_hash_lookup_test_entries = 32; 768c2ecf20Sopenharmony_cistatic uint32_t max_cnt = 1000000; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int check_test_flags(enum test_type t) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci return test_flags & TEST_BIT(t); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic void test_hash_prealloc(int cpu) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci __u64 start_time; 868c2ecf20Sopenharmony_ci int i; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci start_time = time_get_ns(); 898c2ecf20Sopenharmony_ci for (i = 0; i < max_cnt; i++) 908c2ecf20Sopenharmony_ci syscall(__NR_getuid); 918c2ecf20Sopenharmony_ci printf("%d:hash_map_perf pre-alloc %lld events per sec\n", 928c2ecf20Sopenharmony_ci cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int pre_test_lru_hash_lookup(int tasks) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci int fd = map_fd[lru_hash_lookup_idx]; 988c2ecf20Sopenharmony_ci uint32_t key; 998c2ecf20Sopenharmony_ci long val = 1; 1008c2ecf20Sopenharmony_ci int ret; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (num_map_entries > lru_hash_lookup_test_entries) 1038c2ecf20Sopenharmony_ci lru_hash_lookup_test_entries = num_map_entries; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* Populate the lru_hash_map for LRU_HASH_LOOKUP perf test. 1068c2ecf20Sopenharmony_ci * 1078c2ecf20Sopenharmony_ci * It is fine that the user requests for a map with 1088c2ecf20Sopenharmony_ci * num_map_entries < 32 and some of the later lru hash lookup 1098c2ecf20Sopenharmony_ci * may return not found. For LRU map, we are not interested 1108c2ecf20Sopenharmony_ci * in such small map performance. 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_ci for (key = 0; key < lru_hash_lookup_test_entries; key++) { 1138c2ecf20Sopenharmony_ci ret = bpf_map_update_elem(fd, &key, &val, BPF_NOEXIST); 1148c2ecf20Sopenharmony_ci if (ret) 1158c2ecf20Sopenharmony_ci return ret; 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci return 0; 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic void do_test_lru(enum test_type test, int cpu) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci static int inner_lru_map_fds[MAX_NR_CPUS]; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci struct sockaddr_in6 in6 = { .sin6_family = AF_INET6 }; 1268c2ecf20Sopenharmony_ci const char *test_name; 1278c2ecf20Sopenharmony_ci __u64 start_time; 1288c2ecf20Sopenharmony_ci int i, ret; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci if (test == INNER_LRU_HASH_PREALLOC && cpu) { 1318c2ecf20Sopenharmony_ci /* If CPU is not 0, create inner_lru hash map and insert the fd 1328c2ecf20Sopenharmony_ci * value into the array_of_lru_hash map. In case of CPU 0, 1338c2ecf20Sopenharmony_ci * 'inner_lru_hash_map' was statically inserted on the map init 1348c2ecf20Sopenharmony_ci */ 1358c2ecf20Sopenharmony_ci int outer_fd = map_fd[array_of_lru_hashs_idx]; 1368c2ecf20Sopenharmony_ci unsigned int mycpu, mynode; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci assert(cpu < MAX_NR_CPUS); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci ret = syscall(__NR_getcpu, &mycpu, &mynode, NULL); 1418c2ecf20Sopenharmony_ci assert(!ret); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci inner_lru_map_fds[cpu] = 1448c2ecf20Sopenharmony_ci bpf_create_map_node(BPF_MAP_TYPE_LRU_HASH, 1458c2ecf20Sopenharmony_ci test_map_names[INNER_LRU_HASH_PREALLOC], 1468c2ecf20Sopenharmony_ci sizeof(uint32_t), 1478c2ecf20Sopenharmony_ci sizeof(long), 1488c2ecf20Sopenharmony_ci inner_lru_hash_size, 0, 1498c2ecf20Sopenharmony_ci mynode); 1508c2ecf20Sopenharmony_ci if (inner_lru_map_fds[cpu] == -1) { 1518c2ecf20Sopenharmony_ci printf("cannot create BPF_MAP_TYPE_LRU_HASH %s(%d)\n", 1528c2ecf20Sopenharmony_ci strerror(errno), errno); 1538c2ecf20Sopenharmony_ci exit(1); 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci ret = bpf_map_update_elem(outer_fd, &cpu, 1578c2ecf20Sopenharmony_ci &inner_lru_map_fds[cpu], 1588c2ecf20Sopenharmony_ci BPF_ANY); 1598c2ecf20Sopenharmony_ci if (ret) { 1608c2ecf20Sopenharmony_ci printf("cannot update ARRAY_OF_LRU_HASHS with key:%u. %s(%d)\n", 1618c2ecf20Sopenharmony_ci cpu, strerror(errno), errno); 1628c2ecf20Sopenharmony_ci exit(1); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci in6.sin6_addr.s6_addr16[0] = 0xdead; 1678c2ecf20Sopenharmony_ci in6.sin6_addr.s6_addr16[1] = 0xbeef; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if (test == LRU_HASH_PREALLOC) { 1708c2ecf20Sopenharmony_ci test_name = "lru_hash_map_perf"; 1718c2ecf20Sopenharmony_ci in6.sin6_addr.s6_addr16[2] = 0; 1728c2ecf20Sopenharmony_ci } else if (test == NOCOMMON_LRU_HASH_PREALLOC) { 1738c2ecf20Sopenharmony_ci test_name = "nocommon_lru_hash_map_perf"; 1748c2ecf20Sopenharmony_ci in6.sin6_addr.s6_addr16[2] = 1; 1758c2ecf20Sopenharmony_ci } else if (test == INNER_LRU_HASH_PREALLOC) { 1768c2ecf20Sopenharmony_ci test_name = "inner_lru_hash_map_perf"; 1778c2ecf20Sopenharmony_ci in6.sin6_addr.s6_addr16[2] = 2; 1788c2ecf20Sopenharmony_ci } else if (test == LRU_HASH_LOOKUP) { 1798c2ecf20Sopenharmony_ci test_name = "lru_hash_lookup_perf"; 1808c2ecf20Sopenharmony_ci in6.sin6_addr.s6_addr16[2] = 3; 1818c2ecf20Sopenharmony_ci in6.sin6_addr.s6_addr32[3] = 0; 1828c2ecf20Sopenharmony_ci } else { 1838c2ecf20Sopenharmony_ci assert(0); 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci start_time = time_get_ns(); 1878c2ecf20Sopenharmony_ci for (i = 0; i < max_cnt; i++) { 1888c2ecf20Sopenharmony_ci ret = connect(-1, (const struct sockaddr *)&in6, sizeof(in6)); 1898c2ecf20Sopenharmony_ci assert(ret == -1 && errno == EBADF); 1908c2ecf20Sopenharmony_ci if (in6.sin6_addr.s6_addr32[3] < 1918c2ecf20Sopenharmony_ci lru_hash_lookup_test_entries - 32) 1928c2ecf20Sopenharmony_ci in6.sin6_addr.s6_addr32[3] += 32; 1938c2ecf20Sopenharmony_ci else 1948c2ecf20Sopenharmony_ci in6.sin6_addr.s6_addr32[3] = 0; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci printf("%d:%s pre-alloc %lld events per sec\n", 1978c2ecf20Sopenharmony_ci cpu, test_name, 1988c2ecf20Sopenharmony_ci max_cnt * 1000000000ll / (time_get_ns() - start_time)); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic void test_lru_hash_prealloc(int cpu) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci do_test_lru(LRU_HASH_PREALLOC, cpu); 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic void test_nocommon_lru_hash_prealloc(int cpu) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci do_test_lru(NOCOMMON_LRU_HASH_PREALLOC, cpu); 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic void test_inner_lru_hash_prealloc(int cpu) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci do_test_lru(INNER_LRU_HASH_PREALLOC, cpu); 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic void test_lru_hash_lookup(int cpu) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci do_test_lru(LRU_HASH_LOOKUP, cpu); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic void test_percpu_hash_prealloc(int cpu) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci __u64 start_time; 2248c2ecf20Sopenharmony_ci int i; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci start_time = time_get_ns(); 2278c2ecf20Sopenharmony_ci for (i = 0; i < max_cnt; i++) 2288c2ecf20Sopenharmony_ci syscall(__NR_geteuid); 2298c2ecf20Sopenharmony_ci printf("%d:percpu_hash_map_perf pre-alloc %lld events per sec\n", 2308c2ecf20Sopenharmony_ci cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic void test_hash_kmalloc(int cpu) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci __u64 start_time; 2368c2ecf20Sopenharmony_ci int i; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci start_time = time_get_ns(); 2398c2ecf20Sopenharmony_ci for (i = 0; i < max_cnt; i++) 2408c2ecf20Sopenharmony_ci syscall(__NR_getgid); 2418c2ecf20Sopenharmony_ci printf("%d:hash_map_perf kmalloc %lld events per sec\n", 2428c2ecf20Sopenharmony_ci cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic void test_percpu_hash_kmalloc(int cpu) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci __u64 start_time; 2488c2ecf20Sopenharmony_ci int i; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci start_time = time_get_ns(); 2518c2ecf20Sopenharmony_ci for (i = 0; i < max_cnt; i++) 2528c2ecf20Sopenharmony_ci syscall(__NR_getegid); 2538c2ecf20Sopenharmony_ci printf("%d:percpu_hash_map_perf kmalloc %lld events per sec\n", 2548c2ecf20Sopenharmony_ci cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic void test_lpm_kmalloc(int cpu) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci __u64 start_time; 2608c2ecf20Sopenharmony_ci int i; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci start_time = time_get_ns(); 2638c2ecf20Sopenharmony_ci for (i = 0; i < max_cnt; i++) 2648c2ecf20Sopenharmony_ci syscall(__NR_gettid); 2658c2ecf20Sopenharmony_ci printf("%d:lpm_perf kmalloc %lld events per sec\n", 2668c2ecf20Sopenharmony_ci cpu, max_cnt * 1000000000ll / (time_get_ns() - start_time)); 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cistatic void test_hash_lookup(int cpu) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci __u64 start_time; 2728c2ecf20Sopenharmony_ci int i; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci start_time = time_get_ns(); 2758c2ecf20Sopenharmony_ci for (i = 0; i < max_cnt; i++) 2768c2ecf20Sopenharmony_ci syscall(__NR_getpgid, 0); 2778c2ecf20Sopenharmony_ci printf("%d:hash_lookup %lld lookups per sec\n", 2788c2ecf20Sopenharmony_ci cpu, max_cnt * 1000000000ll * 64 / (time_get_ns() - start_time)); 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cistatic void test_array_lookup(int cpu) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci __u64 start_time; 2848c2ecf20Sopenharmony_ci int i; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci start_time = time_get_ns(); 2878c2ecf20Sopenharmony_ci for (i = 0; i < max_cnt; i++) 2888c2ecf20Sopenharmony_ci syscall(__NR_getppid, 0); 2898c2ecf20Sopenharmony_ci printf("%d:array_lookup %lld lookups per sec\n", 2908c2ecf20Sopenharmony_ci cpu, max_cnt * 1000000000ll * 64 / (time_get_ns() - start_time)); 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_citypedef int (*pre_test_func)(int tasks); 2948c2ecf20Sopenharmony_ciconst pre_test_func pre_test_funcs[] = { 2958c2ecf20Sopenharmony_ci [LRU_HASH_LOOKUP] = pre_test_lru_hash_lookup, 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_citypedef void (*test_func)(int cpu); 2998c2ecf20Sopenharmony_ciconst test_func test_funcs[] = { 3008c2ecf20Sopenharmony_ci [HASH_PREALLOC] = test_hash_prealloc, 3018c2ecf20Sopenharmony_ci [PERCPU_HASH_PREALLOC] = test_percpu_hash_prealloc, 3028c2ecf20Sopenharmony_ci [HASH_KMALLOC] = test_hash_kmalloc, 3038c2ecf20Sopenharmony_ci [PERCPU_HASH_KMALLOC] = test_percpu_hash_kmalloc, 3048c2ecf20Sopenharmony_ci [LRU_HASH_PREALLOC] = test_lru_hash_prealloc, 3058c2ecf20Sopenharmony_ci [NOCOMMON_LRU_HASH_PREALLOC] = test_nocommon_lru_hash_prealloc, 3068c2ecf20Sopenharmony_ci [LPM_KMALLOC] = test_lpm_kmalloc, 3078c2ecf20Sopenharmony_ci [HASH_LOOKUP] = test_hash_lookup, 3088c2ecf20Sopenharmony_ci [ARRAY_LOOKUP] = test_array_lookup, 3098c2ecf20Sopenharmony_ci [INNER_LRU_HASH_PREALLOC] = test_inner_lru_hash_prealloc, 3108c2ecf20Sopenharmony_ci [LRU_HASH_LOOKUP] = test_lru_hash_lookup, 3118c2ecf20Sopenharmony_ci}; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic int pre_test(int tasks) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci int i; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci for (i = 0; i < NR_TESTS; i++) { 3188c2ecf20Sopenharmony_ci if (pre_test_funcs[i] && check_test_flags(i)) { 3198c2ecf20Sopenharmony_ci int ret = pre_test_funcs[i](tasks); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (ret) 3228c2ecf20Sopenharmony_ci return ret; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci return 0; 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic void loop(int cpu) 3308c2ecf20Sopenharmony_ci{ 3318c2ecf20Sopenharmony_ci cpu_set_t cpuset; 3328c2ecf20Sopenharmony_ci int i; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci CPU_ZERO(&cpuset); 3358c2ecf20Sopenharmony_ci CPU_SET(cpu, &cpuset); 3368c2ecf20Sopenharmony_ci sched_setaffinity(0, sizeof(cpuset), &cpuset); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci for (i = 0; i < NR_TESTS; i++) { 3398c2ecf20Sopenharmony_ci if (check_test_flags(i)) 3408c2ecf20Sopenharmony_ci test_funcs[i](cpu); 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic void run_perf_test(int tasks) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci pid_t pid[tasks]; 3478c2ecf20Sopenharmony_ci int i; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci assert(!pre_test(tasks)); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci for (i = 0; i < tasks; i++) { 3528c2ecf20Sopenharmony_ci pid[i] = fork(); 3538c2ecf20Sopenharmony_ci if (pid[i] == 0) { 3548c2ecf20Sopenharmony_ci loop(i); 3558c2ecf20Sopenharmony_ci exit(0); 3568c2ecf20Sopenharmony_ci } else if (pid[i] == -1) { 3578c2ecf20Sopenharmony_ci printf("couldn't spawn #%d process\n", i); 3588c2ecf20Sopenharmony_ci exit(1); 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci for (i = 0; i < tasks; i++) { 3628c2ecf20Sopenharmony_ci int status; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci assert(waitpid(pid[i], &status, 0) == pid[i]); 3658c2ecf20Sopenharmony_ci assert(status == 0); 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistatic void fill_lpm_trie(void) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci struct bpf_lpm_trie_key *key; 3728c2ecf20Sopenharmony_ci unsigned long value = 0; 3738c2ecf20Sopenharmony_ci unsigned int i; 3748c2ecf20Sopenharmony_ci int r; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci key = alloca(sizeof(*key) + 4); 3778c2ecf20Sopenharmony_ci key->prefixlen = 32; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci for (i = 0; i < 512; ++i) { 3808c2ecf20Sopenharmony_ci key->prefixlen = rand() % 33; 3818c2ecf20Sopenharmony_ci key->data[0] = rand() & 0xff; 3828c2ecf20Sopenharmony_ci key->data[1] = rand() & 0xff; 3838c2ecf20Sopenharmony_ci key->data[2] = rand() & 0xff; 3848c2ecf20Sopenharmony_ci key->data[3] = rand() & 0xff; 3858c2ecf20Sopenharmony_ci r = bpf_map_update_elem(map_fd[hash_map_alloc_idx], 3868c2ecf20Sopenharmony_ci key, &value, 0); 3878c2ecf20Sopenharmony_ci assert(!r); 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci key->prefixlen = 32; 3918c2ecf20Sopenharmony_ci key->data[0] = 192; 3928c2ecf20Sopenharmony_ci key->data[1] = 168; 3938c2ecf20Sopenharmony_ci key->data[2] = 0; 3948c2ecf20Sopenharmony_ci key->data[3] = 1; 3958c2ecf20Sopenharmony_ci value = 128; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci r = bpf_map_update_elem(map_fd[hash_map_alloc_idx], key, &value, 0); 3988c2ecf20Sopenharmony_ci assert(!r); 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_cistatic void fixup_map(struct bpf_object *obj) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci struct bpf_map *map; 4048c2ecf20Sopenharmony_ci int i; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci bpf_object__for_each_map(map, obj) { 4078c2ecf20Sopenharmony_ci const char *name = bpf_map__name(map); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci /* Only change the max_entries for the enabled test(s) */ 4108c2ecf20Sopenharmony_ci for (i = 0; i < NR_TESTS; i++) { 4118c2ecf20Sopenharmony_ci if (!strcmp(test_map_names[i], name) && 4128c2ecf20Sopenharmony_ci (check_test_flags(i))) { 4138c2ecf20Sopenharmony_ci bpf_map__resize(map, num_map_entries); 4148c2ecf20Sopenharmony_ci continue; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci inner_lru_hash_size = num_map_entries; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ciint main(int argc, char **argv) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 4258c2ecf20Sopenharmony_ci int nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 4268c2ecf20Sopenharmony_ci struct bpf_link *links[8]; 4278c2ecf20Sopenharmony_ci struct bpf_program *prog; 4288c2ecf20Sopenharmony_ci struct bpf_object *obj; 4298c2ecf20Sopenharmony_ci struct bpf_map *map; 4308c2ecf20Sopenharmony_ci char filename[256]; 4318c2ecf20Sopenharmony_ci int i = 0; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci if (setrlimit(RLIMIT_MEMLOCK, &r)) { 4348c2ecf20Sopenharmony_ci perror("setrlimit(RLIMIT_MEMLOCK)"); 4358c2ecf20Sopenharmony_ci return 1; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci if (argc > 1) 4398c2ecf20Sopenharmony_ci test_flags = atoi(argv[1]) ? : test_flags; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci if (argc > 2) 4428c2ecf20Sopenharmony_ci nr_cpus = atoi(argv[2]) ? : nr_cpus; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci if (argc > 3) 4458c2ecf20Sopenharmony_ci num_map_entries = atoi(argv[3]); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci if (argc > 4) 4488c2ecf20Sopenharmony_ci max_cnt = atoi(argv[4]); 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 4518c2ecf20Sopenharmony_ci obj = bpf_object__open_file(filename, NULL); 4528c2ecf20Sopenharmony_ci if (libbpf_get_error(obj)) { 4538c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: opening BPF object file failed\n"); 4548c2ecf20Sopenharmony_ci return 0; 4558c2ecf20Sopenharmony_ci } 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci map = bpf_object__find_map_by_name(obj, "inner_lru_hash_map"); 4588c2ecf20Sopenharmony_ci if (libbpf_get_error(map)) { 4598c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 4608c2ecf20Sopenharmony_ci goto cleanup; 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci inner_lru_hash_size = bpf_map__max_entries(map); 4648c2ecf20Sopenharmony_ci if (!inner_lru_hash_size) { 4658c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: failed to get map attribute\n"); 4668c2ecf20Sopenharmony_ci goto cleanup; 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci /* resize BPF map prior to loading */ 4708c2ecf20Sopenharmony_ci if (num_map_entries > 0) 4718c2ecf20Sopenharmony_ci fixup_map(obj); 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci /* load BPF program */ 4748c2ecf20Sopenharmony_ci if (bpf_object__load(obj)) { 4758c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: loading BPF object file failed\n"); 4768c2ecf20Sopenharmony_ci goto cleanup; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci map_fd[0] = bpf_object__find_map_fd_by_name(obj, "array_of_lru_hashs"); 4808c2ecf20Sopenharmony_ci map_fd[1] = bpf_object__find_map_fd_by_name(obj, "hash_map_alloc"); 4818c2ecf20Sopenharmony_ci map_fd[2] = bpf_object__find_map_fd_by_name(obj, "lru_hash_lookup_map"); 4828c2ecf20Sopenharmony_ci if (map_fd[0] < 0 || map_fd[1] < 0 || map_fd[2] < 0) { 4838c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 4848c2ecf20Sopenharmony_ci goto cleanup; 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci bpf_object__for_each_program(prog, obj) { 4888c2ecf20Sopenharmony_ci links[i] = bpf_program__attach(prog); 4898c2ecf20Sopenharmony_ci if (libbpf_get_error(links[i])) { 4908c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 4918c2ecf20Sopenharmony_ci links[i] = NULL; 4928c2ecf20Sopenharmony_ci goto cleanup; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci i++; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci fill_lpm_trie(); 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci run_perf_test(nr_cpus); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cicleanup: 5028c2ecf20Sopenharmony_ci for (i--; i >= 0; i--) 5038c2ecf20Sopenharmony_ci bpf_link__destroy(links[i]); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci bpf_object__close(obj); 5068c2ecf20Sopenharmony_ci return 0; 5078c2ecf20Sopenharmony_ci} 508