at v4.11-rc4 237 lines 5.1 kB view raw
1/* Copyright (c) 2016 Facebook 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#define _GNU_SOURCE 8#include <sched.h> 9#include <stdio.h> 10#include <sys/types.h> 11#include <asm/unistd.h> 12#include <unistd.h> 13#include <assert.h> 14#include <sys/wait.h> 15#include <stdlib.h> 16#include <signal.h> 17#include <linux/bpf.h> 18#include <string.h> 19#include <time.h> 20#include <sys/resource.h> 21#include "libbpf.h" 22#include "bpf_load.h" 23 24#define MAX_CNT 1000000 25 26static __u64 time_get_ns(void) 27{ 28 struct timespec ts; 29 30 clock_gettime(CLOCK_MONOTONIC, &ts); 31 return ts.tv_sec * 1000000000ull + ts.tv_nsec; 32} 33 34#define HASH_PREALLOC (1 << 0) 35#define PERCPU_HASH_PREALLOC (1 << 1) 36#define HASH_KMALLOC (1 << 2) 37#define PERCPU_HASH_KMALLOC (1 << 3) 38#define LRU_HASH_PREALLOC (1 << 4) 39#define PERCPU_LRU_HASH_PREALLOC (1 << 5) 40#define LPM_KMALLOC (1 << 6) 41 42static int test_flags = ~0; 43 44static void test_hash_prealloc(int cpu) 45{ 46 __u64 start_time; 47 int i; 48 49 start_time = time_get_ns(); 50 for (i = 0; i < MAX_CNT; i++) 51 syscall(__NR_getuid); 52 printf("%d:hash_map_perf pre-alloc %lld events per sec\n", 53 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 54} 55 56static void test_lru_hash_prealloc(int cpu) 57{ 58 __u64 start_time; 59 int i; 60 61 start_time = time_get_ns(); 62 for (i = 0; i < MAX_CNT; i++) 63 syscall(__NR_getpid); 64 printf("%d:lru_hash_map_perf pre-alloc %lld events per sec\n", 65 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 66} 67 68static void test_percpu_lru_hash_prealloc(int cpu) 69{ 70 __u64 start_time; 71 int i; 72 73 start_time = time_get_ns(); 74 for (i = 0; i < MAX_CNT; i++) 75 syscall(__NR_getppid); 76 printf("%d:lru_hash_map_perf pre-alloc %lld events per sec\n", 77 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 78} 79 80static void test_percpu_hash_prealloc(int cpu) 81{ 82 __u64 start_time; 83 int i; 84 85 start_time = time_get_ns(); 86 for (i = 0; i < MAX_CNT; i++) 87 syscall(__NR_geteuid); 88 printf("%d:percpu_hash_map_perf pre-alloc %lld events per sec\n", 89 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 90} 91 92static void test_hash_kmalloc(int cpu) 93{ 94 __u64 start_time; 95 int i; 96 97 start_time = time_get_ns(); 98 for (i = 0; i < MAX_CNT; i++) 99 syscall(__NR_getgid); 100 printf("%d:hash_map_perf kmalloc %lld events per sec\n", 101 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 102} 103 104static void test_percpu_hash_kmalloc(int cpu) 105{ 106 __u64 start_time; 107 int i; 108 109 start_time = time_get_ns(); 110 for (i = 0; i < MAX_CNT; i++) 111 syscall(__NR_getegid); 112 printf("%d:percpu_hash_map_perf kmalloc %lld events per sec\n", 113 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 114} 115 116static void test_lpm_kmalloc(int cpu) 117{ 118 __u64 start_time; 119 int i; 120 121 start_time = time_get_ns(); 122 for (i = 0; i < MAX_CNT; i++) 123 syscall(__NR_gettid); 124 printf("%d:lpm_perf kmalloc %lld events per sec\n", 125 cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 126} 127 128static void loop(int cpu) 129{ 130 cpu_set_t cpuset; 131 132 CPU_ZERO(&cpuset); 133 CPU_SET(cpu, &cpuset); 134 sched_setaffinity(0, sizeof(cpuset), &cpuset); 135 136 if (test_flags & HASH_PREALLOC) 137 test_hash_prealloc(cpu); 138 139 if (test_flags & PERCPU_HASH_PREALLOC) 140 test_percpu_hash_prealloc(cpu); 141 142 if (test_flags & HASH_KMALLOC) 143 test_hash_kmalloc(cpu); 144 145 if (test_flags & PERCPU_HASH_KMALLOC) 146 test_percpu_hash_kmalloc(cpu); 147 148 if (test_flags & LRU_HASH_PREALLOC) 149 test_lru_hash_prealloc(cpu); 150 151 if (test_flags & PERCPU_LRU_HASH_PREALLOC) 152 test_percpu_lru_hash_prealloc(cpu); 153 154 if (test_flags & LPM_KMALLOC) 155 test_lpm_kmalloc(cpu); 156} 157 158static void run_perf_test(int tasks) 159{ 160 pid_t pid[tasks]; 161 int i; 162 163 for (i = 0; i < tasks; i++) { 164 pid[i] = fork(); 165 if (pid[i] == 0) { 166 loop(i); 167 exit(0); 168 } else if (pid[i] == -1) { 169 printf("couldn't spawn #%d process\n", i); 170 exit(1); 171 } 172 } 173 for (i = 0; i < tasks; i++) { 174 int status; 175 176 assert(waitpid(pid[i], &status, 0) == pid[i]); 177 assert(status == 0); 178 } 179} 180 181static void fill_lpm_trie(void) 182{ 183 struct bpf_lpm_trie_key *key; 184 unsigned long value = 0; 185 unsigned int i; 186 int r; 187 188 key = alloca(sizeof(*key) + 4); 189 key->prefixlen = 32; 190 191 for (i = 0; i < 512; ++i) { 192 key->prefixlen = rand() % 33; 193 key->data[0] = rand() & 0xff; 194 key->data[1] = rand() & 0xff; 195 key->data[2] = rand() & 0xff; 196 key->data[3] = rand() & 0xff; 197 r = bpf_map_update_elem(map_fd[6], key, &value, 0); 198 assert(!r); 199 } 200 201 key->prefixlen = 32; 202 key->data[0] = 192; 203 key->data[1] = 168; 204 key->data[2] = 0; 205 key->data[3] = 1; 206 value = 128; 207 208 r = bpf_map_update_elem(map_fd[6], key, &value, 0); 209 assert(!r); 210} 211 212int main(int argc, char **argv) 213{ 214 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 215 char filename[256]; 216 int num_cpu = 8; 217 218 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 219 setrlimit(RLIMIT_MEMLOCK, &r); 220 221 if (argc > 1) 222 test_flags = atoi(argv[1]) ? : test_flags; 223 224 if (argc > 2) 225 num_cpu = atoi(argv[2]) ? : num_cpu; 226 227 if (load_bpf_file(filename)) { 228 printf("%s", bpf_log_buf); 229 return 1; 230 } 231 232 fill_lpm_trie(); 233 234 run_perf_test(num_cpu); 235 236 return 0; 237}