126e90931SAlexei Starovoitov /* Copyright (c) 2016 Facebook 226e90931SAlexei Starovoitov * 326e90931SAlexei Starovoitov * This program is free software; you can redistribute it and/or 426e90931SAlexei Starovoitov * modify it under the terms of version 2 of the GNU General Public 526e90931SAlexei Starovoitov * License as published by the Free Software Foundation. 626e90931SAlexei Starovoitov */ 726e90931SAlexei Starovoitov #define _GNU_SOURCE 826e90931SAlexei Starovoitov #include <sched.h> 926e90931SAlexei Starovoitov #include <stdio.h> 1026e90931SAlexei Starovoitov #include <sys/types.h> 1126e90931SAlexei Starovoitov #include <asm/unistd.h> 1226e90931SAlexei Starovoitov #include <unistd.h> 1326e90931SAlexei Starovoitov #include <assert.h> 1426e90931SAlexei Starovoitov #include <sys/wait.h> 1526e90931SAlexei Starovoitov #include <stdlib.h> 1626e90931SAlexei Starovoitov #include <signal.h> 1726e90931SAlexei Starovoitov #include <linux/bpf.h> 1826e90931SAlexei Starovoitov #include <string.h> 1926e90931SAlexei Starovoitov #include <time.h> 2077e63534SNaveen N. Rao #include <sys/resource.h> 2126e90931SAlexei Starovoitov #include "libbpf.h" 2226e90931SAlexei Starovoitov #include "bpf_load.h" 2326e90931SAlexei Starovoitov 2426e90931SAlexei Starovoitov #define MAX_CNT 1000000 2526e90931SAlexei Starovoitov 2626e90931SAlexei Starovoitov static __u64 time_get_ns(void) 2726e90931SAlexei Starovoitov { 2826e90931SAlexei Starovoitov struct timespec ts; 2926e90931SAlexei Starovoitov 3026e90931SAlexei Starovoitov clock_gettime(CLOCK_MONOTONIC, &ts); 3126e90931SAlexei Starovoitov return ts.tv_sec * 1000000000ull + ts.tv_nsec; 3226e90931SAlexei Starovoitov } 3326e90931SAlexei Starovoitov 3426e90931SAlexei Starovoitov #define HASH_PREALLOC (1 << 0) 3526e90931SAlexei Starovoitov #define PERCPU_HASH_PREALLOC (1 << 1) 3626e90931SAlexei Starovoitov #define HASH_KMALLOC (1 << 2) 3726e90931SAlexei Starovoitov #define PERCPU_HASH_KMALLOC (1 << 3) 385db58fafSMartin KaFai Lau #define LRU_HASH_PREALLOC (1 << 4) 395db58fafSMartin KaFai Lau #define PERCPU_LRU_HASH_PREALLOC (1 << 5) 40b8a943e2SDavid Herrmann #define LPM_KMALLOC (1 << 6) 41*95ff141eSAlexei Starovoitov #define HASH_LOOKUP (1 << 7) 42*95ff141eSAlexei Starovoitov #define ARRAY_LOOKUP (1 << 8) 4326e90931SAlexei Starovoitov 4426e90931SAlexei Starovoitov static int test_flags = ~0; 4526e90931SAlexei Starovoitov 4626e90931SAlexei Starovoitov static void test_hash_prealloc(int cpu) 4726e90931SAlexei Starovoitov { 4826e90931SAlexei Starovoitov __u64 start_time; 4926e90931SAlexei Starovoitov int i; 5026e90931SAlexei Starovoitov 5126e90931SAlexei Starovoitov start_time = time_get_ns(); 5226e90931SAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 5326e90931SAlexei Starovoitov syscall(__NR_getuid); 5426e90931SAlexei Starovoitov printf("%d:hash_map_perf pre-alloc %lld events per sec\n", 5526e90931SAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 5626e90931SAlexei Starovoitov } 5726e90931SAlexei Starovoitov 585db58fafSMartin KaFai Lau static void test_lru_hash_prealloc(int cpu) 595db58fafSMartin KaFai Lau { 605db58fafSMartin KaFai Lau __u64 start_time; 615db58fafSMartin KaFai Lau int i; 625db58fafSMartin KaFai Lau 635db58fafSMartin KaFai Lau start_time = time_get_ns(); 645db58fafSMartin KaFai Lau for (i = 0; i < MAX_CNT; i++) 655db58fafSMartin KaFai Lau syscall(__NR_getpid); 665db58fafSMartin KaFai Lau printf("%d:lru_hash_map_perf pre-alloc %lld events per sec\n", 675db58fafSMartin KaFai Lau cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 685db58fafSMartin KaFai Lau } 695db58fafSMartin KaFai Lau 705db58fafSMartin KaFai Lau static void test_percpu_lru_hash_prealloc(int cpu) 715db58fafSMartin KaFai Lau { 725db58fafSMartin KaFai Lau __u64 start_time; 735db58fafSMartin KaFai Lau int i; 745db58fafSMartin KaFai Lau 755db58fafSMartin KaFai Lau start_time = time_get_ns(); 765db58fafSMartin KaFai Lau for (i = 0; i < MAX_CNT; i++) 775db58fafSMartin KaFai Lau syscall(__NR_getppid); 785db58fafSMartin KaFai Lau printf("%d:lru_hash_map_perf pre-alloc %lld events per sec\n", 795db58fafSMartin KaFai Lau cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 805db58fafSMartin KaFai Lau } 815db58fafSMartin KaFai Lau 8226e90931SAlexei Starovoitov static void test_percpu_hash_prealloc(int cpu) 8326e90931SAlexei Starovoitov { 8426e90931SAlexei Starovoitov __u64 start_time; 8526e90931SAlexei Starovoitov int i; 8626e90931SAlexei Starovoitov 8726e90931SAlexei Starovoitov start_time = time_get_ns(); 8826e90931SAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 8926e90931SAlexei Starovoitov syscall(__NR_geteuid); 9026e90931SAlexei Starovoitov printf("%d:percpu_hash_map_perf pre-alloc %lld events per sec\n", 9126e90931SAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 9226e90931SAlexei Starovoitov } 9326e90931SAlexei Starovoitov 9426e90931SAlexei Starovoitov static void test_hash_kmalloc(int cpu) 9526e90931SAlexei Starovoitov { 9626e90931SAlexei Starovoitov __u64 start_time; 9726e90931SAlexei Starovoitov int i; 9826e90931SAlexei Starovoitov 9926e90931SAlexei Starovoitov start_time = time_get_ns(); 10026e90931SAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 10126e90931SAlexei Starovoitov syscall(__NR_getgid); 10226e90931SAlexei Starovoitov printf("%d:hash_map_perf kmalloc %lld events per sec\n", 10326e90931SAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 10426e90931SAlexei Starovoitov } 10526e90931SAlexei Starovoitov 10626e90931SAlexei Starovoitov static void test_percpu_hash_kmalloc(int cpu) 10726e90931SAlexei Starovoitov { 10826e90931SAlexei Starovoitov __u64 start_time; 10926e90931SAlexei Starovoitov int i; 11026e90931SAlexei Starovoitov 11126e90931SAlexei Starovoitov start_time = time_get_ns(); 11226e90931SAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 11326e90931SAlexei Starovoitov syscall(__NR_getegid); 11426e90931SAlexei Starovoitov printf("%d:percpu_hash_map_perf kmalloc %lld events per sec\n", 11526e90931SAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 11626e90931SAlexei Starovoitov } 11726e90931SAlexei Starovoitov 118b8a943e2SDavid Herrmann static void test_lpm_kmalloc(int cpu) 119b8a943e2SDavid Herrmann { 120b8a943e2SDavid Herrmann __u64 start_time; 121b8a943e2SDavid Herrmann int i; 122b8a943e2SDavid Herrmann 123b8a943e2SDavid Herrmann start_time = time_get_ns(); 124b8a943e2SDavid Herrmann for (i = 0; i < MAX_CNT; i++) 125b8a943e2SDavid Herrmann syscall(__NR_gettid); 126b8a943e2SDavid Herrmann printf("%d:lpm_perf kmalloc %lld events per sec\n", 127b8a943e2SDavid Herrmann cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 128b8a943e2SDavid Herrmann } 129b8a943e2SDavid Herrmann 130*95ff141eSAlexei Starovoitov static void test_hash_lookup(int cpu) 131*95ff141eSAlexei Starovoitov { 132*95ff141eSAlexei Starovoitov __u64 start_time; 133*95ff141eSAlexei Starovoitov int i; 134*95ff141eSAlexei Starovoitov 135*95ff141eSAlexei Starovoitov start_time = time_get_ns(); 136*95ff141eSAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 137*95ff141eSAlexei Starovoitov syscall(__NR_getpgid, 0); 138*95ff141eSAlexei Starovoitov printf("%d:hash_lookup %lld lookups per sec\n", 139*95ff141eSAlexei Starovoitov cpu, MAX_CNT * 1000000000ll * 64 / (time_get_ns() - start_time)); 140*95ff141eSAlexei Starovoitov } 141*95ff141eSAlexei Starovoitov 142*95ff141eSAlexei Starovoitov static void test_array_lookup(int cpu) 143*95ff141eSAlexei Starovoitov { 144*95ff141eSAlexei Starovoitov __u64 start_time; 145*95ff141eSAlexei Starovoitov int i; 146*95ff141eSAlexei Starovoitov 147*95ff141eSAlexei Starovoitov start_time = time_get_ns(); 148*95ff141eSAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 149*95ff141eSAlexei Starovoitov syscall(__NR_getpgrp, 0); 150*95ff141eSAlexei Starovoitov printf("%d:array_lookup %lld lookups per sec\n", 151*95ff141eSAlexei Starovoitov cpu, MAX_CNT * 1000000000ll * 64 / (time_get_ns() - start_time)); 152*95ff141eSAlexei Starovoitov } 153*95ff141eSAlexei Starovoitov 15426e90931SAlexei Starovoitov static void loop(int cpu) 15526e90931SAlexei Starovoitov { 15626e90931SAlexei Starovoitov cpu_set_t cpuset; 15726e90931SAlexei Starovoitov 15826e90931SAlexei Starovoitov CPU_ZERO(&cpuset); 15926e90931SAlexei Starovoitov CPU_SET(cpu, &cpuset); 16026e90931SAlexei Starovoitov sched_setaffinity(0, sizeof(cpuset), &cpuset); 16126e90931SAlexei Starovoitov 16226e90931SAlexei Starovoitov if (test_flags & HASH_PREALLOC) 16326e90931SAlexei Starovoitov test_hash_prealloc(cpu); 16426e90931SAlexei Starovoitov 16526e90931SAlexei Starovoitov if (test_flags & PERCPU_HASH_PREALLOC) 16626e90931SAlexei Starovoitov test_percpu_hash_prealloc(cpu); 16726e90931SAlexei Starovoitov 16826e90931SAlexei Starovoitov if (test_flags & HASH_KMALLOC) 16926e90931SAlexei Starovoitov test_hash_kmalloc(cpu); 17026e90931SAlexei Starovoitov 17126e90931SAlexei Starovoitov if (test_flags & PERCPU_HASH_KMALLOC) 17226e90931SAlexei Starovoitov test_percpu_hash_kmalloc(cpu); 1735db58fafSMartin KaFai Lau 1745db58fafSMartin KaFai Lau if (test_flags & LRU_HASH_PREALLOC) 1755db58fafSMartin KaFai Lau test_lru_hash_prealloc(cpu); 1765db58fafSMartin KaFai Lau 1775db58fafSMartin KaFai Lau if (test_flags & PERCPU_LRU_HASH_PREALLOC) 1785db58fafSMartin KaFai Lau test_percpu_lru_hash_prealloc(cpu); 179b8a943e2SDavid Herrmann 180b8a943e2SDavid Herrmann if (test_flags & LPM_KMALLOC) 181b8a943e2SDavid Herrmann test_lpm_kmalloc(cpu); 182*95ff141eSAlexei Starovoitov 183*95ff141eSAlexei Starovoitov if (test_flags & HASH_LOOKUP) 184*95ff141eSAlexei Starovoitov test_hash_lookup(cpu); 185*95ff141eSAlexei Starovoitov 186*95ff141eSAlexei Starovoitov if (test_flags & ARRAY_LOOKUP) 187*95ff141eSAlexei Starovoitov test_array_lookup(cpu); 18826e90931SAlexei Starovoitov } 18926e90931SAlexei Starovoitov 19026e90931SAlexei Starovoitov static void run_perf_test(int tasks) 19126e90931SAlexei Starovoitov { 19226e90931SAlexei Starovoitov pid_t pid[tasks]; 19326e90931SAlexei Starovoitov int i; 19426e90931SAlexei Starovoitov 19526e90931SAlexei Starovoitov for (i = 0; i < tasks; i++) { 19626e90931SAlexei Starovoitov pid[i] = fork(); 19726e90931SAlexei Starovoitov if (pid[i] == 0) { 19826e90931SAlexei Starovoitov loop(i); 19926e90931SAlexei Starovoitov exit(0); 20026e90931SAlexei Starovoitov } else if (pid[i] == -1) { 20126e90931SAlexei Starovoitov printf("couldn't spawn #%d process\n", i); 20226e90931SAlexei Starovoitov exit(1); 20326e90931SAlexei Starovoitov } 20426e90931SAlexei Starovoitov } 20526e90931SAlexei Starovoitov for (i = 0; i < tasks; i++) { 20626e90931SAlexei Starovoitov int status; 20726e90931SAlexei Starovoitov 20826e90931SAlexei Starovoitov assert(waitpid(pid[i], &status, 0) == pid[i]); 20926e90931SAlexei Starovoitov assert(status == 0); 21026e90931SAlexei Starovoitov } 21126e90931SAlexei Starovoitov } 21226e90931SAlexei Starovoitov 213b8a943e2SDavid Herrmann static void fill_lpm_trie(void) 214b8a943e2SDavid Herrmann { 215b8a943e2SDavid Herrmann struct bpf_lpm_trie_key *key; 216b8a943e2SDavid Herrmann unsigned long value = 0; 217b8a943e2SDavid Herrmann unsigned int i; 218b8a943e2SDavid Herrmann int r; 219b8a943e2SDavid Herrmann 220b8a943e2SDavid Herrmann key = alloca(sizeof(*key) + 4); 221b8a943e2SDavid Herrmann key->prefixlen = 32; 222b8a943e2SDavid Herrmann 223b8a943e2SDavid Herrmann for (i = 0; i < 512; ++i) { 224b8a943e2SDavid Herrmann key->prefixlen = rand() % 33; 225b8a943e2SDavid Herrmann key->data[0] = rand() & 0xff; 226b8a943e2SDavid Herrmann key->data[1] = rand() & 0xff; 227b8a943e2SDavid Herrmann key->data[2] = rand() & 0xff; 228b8a943e2SDavid Herrmann key->data[3] = rand() & 0xff; 229b8a943e2SDavid Herrmann r = bpf_map_update_elem(map_fd[6], key, &value, 0); 230b8a943e2SDavid Herrmann assert(!r); 231b8a943e2SDavid Herrmann } 232b8a943e2SDavid Herrmann 233b8a943e2SDavid Herrmann key->prefixlen = 32; 234b8a943e2SDavid Herrmann key->data[0] = 192; 235b8a943e2SDavid Herrmann key->data[1] = 168; 236b8a943e2SDavid Herrmann key->data[2] = 0; 237b8a943e2SDavid Herrmann key->data[3] = 1; 238b8a943e2SDavid Herrmann value = 128; 239b8a943e2SDavid Herrmann 240b8a943e2SDavid Herrmann r = bpf_map_update_elem(map_fd[6], key, &value, 0); 241b8a943e2SDavid Herrmann assert(!r); 242b8a943e2SDavid Herrmann } 243b8a943e2SDavid Herrmann 24426e90931SAlexei Starovoitov int main(int argc, char **argv) 24526e90931SAlexei Starovoitov { 24626e90931SAlexei Starovoitov struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 24726e90931SAlexei Starovoitov char filename[256]; 24826e90931SAlexei Starovoitov int num_cpu = 8; 24926e90931SAlexei Starovoitov 25026e90931SAlexei Starovoitov snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 25126e90931SAlexei Starovoitov setrlimit(RLIMIT_MEMLOCK, &r); 25226e90931SAlexei Starovoitov 25326e90931SAlexei Starovoitov if (argc > 1) 25426e90931SAlexei Starovoitov test_flags = atoi(argv[1]) ? : test_flags; 25526e90931SAlexei Starovoitov 25626e90931SAlexei Starovoitov if (argc > 2) 25726e90931SAlexei Starovoitov num_cpu = atoi(argv[2]) ? : num_cpu; 25826e90931SAlexei Starovoitov 25926e90931SAlexei Starovoitov if (load_bpf_file(filename)) { 26026e90931SAlexei Starovoitov printf("%s", bpf_log_buf); 26126e90931SAlexei Starovoitov return 1; 26226e90931SAlexei Starovoitov } 26326e90931SAlexei Starovoitov 264b8a943e2SDavid Herrmann fill_lpm_trie(); 265b8a943e2SDavid Herrmann 26626e90931SAlexei Starovoitov run_perf_test(num_cpu); 26726e90931SAlexei Starovoitov 26826e90931SAlexei Starovoitov return 0; 26926e90931SAlexei Starovoitov } 270