1 /* 2 * Testsuite for eBPF maps 3 * 4 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com 5 * Copyright (c) 2016 Facebook 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of version 2 of the GNU General Public 9 * License as published by the Free Software Foundation. 10 */ 11 12 #include <stdio.h> 13 #include <unistd.h> 14 #include <errno.h> 15 #include <string.h> 16 #include <assert.h> 17 #include <stdlib.h> 18 19 #include <sys/wait.h> 20 #include <sys/resource.h> 21 22 #include <linux/bpf.h> 23 24 #include <bpf/bpf.h> 25 #include <bpf/libbpf.h> 26 #include "bpf_util.h" 27 28 static int map_flags; 29 30 static void test_hashmap(int task, void *data) 31 { 32 long long key, next_key, first_key, value; 33 int fd; 34 35 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 36 2, map_flags); 37 if (fd < 0) { 38 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 39 exit(1); 40 } 41 42 key = 1; 43 value = 1234; 44 /* Insert key=1 element. */ 45 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 46 47 value = 0; 48 /* BPF_NOEXIST means add new element if it doesn't exist. */ 49 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 50 /* key=1 already exists. */ 51 errno == EEXIST); 52 53 /* -1 is an invalid flag. */ 54 assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 && 55 errno == EINVAL); 56 57 /* Check that key=1 can be found. */ 58 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); 59 60 key = 2; 61 /* Check that key=2 is not found. */ 62 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 63 64 /* BPF_EXIST means update existing element. */ 65 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 && 66 /* key=2 is not there. */ 67 errno == ENOENT); 68 69 /* Insert key=2 element. */ 70 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 71 72 /* key=1 and key=2 were inserted, check that key=0 cannot be 73 * inserted due to max_entries limit. 74 */ 75 key = 0; 76 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 77 errno == E2BIG); 78 79 /* Update existing element, though the map is full. */ 80 key = 1; 81 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); 82 key = 2; 83 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 84 key = 3; 85 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 86 errno == E2BIG); 87 88 /* Check that key = 0 doesn't exist. */ 89 key = 0; 90 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 91 92 /* Iterate over two elements. */ 93 assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 && 94 (first_key == 1 || first_key == 2)); 95 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 96 (next_key == first_key)); 97 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 98 (next_key == 1 || next_key == 2) && 99 (next_key != first_key)); 100 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && 101 errno == ENOENT); 102 103 /* Delete both elements. */ 104 key = 1; 105 assert(bpf_map_delete_elem(fd, &key) == 0); 106 key = 2; 107 assert(bpf_map_delete_elem(fd, &key) == 0); 108 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 109 110 key = 0; 111 /* Check that map is empty. */ 112 assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 && 113 errno == ENOENT); 114 assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 && 115 errno == ENOENT); 116 117 close(fd); 118 } 119 120 static void test_hashmap_sizes(int task, void *data) 121 { 122 int fd, i, j; 123 124 for (i = 1; i <= 512; i <<= 1) 125 for (j = 1; j <= 1 << 18; j <<= 1) { 126 fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j, 127 2, map_flags); 128 if (fd < 0) { 129 printf("Failed to create hashmap key=%d value=%d '%s'\n", 130 i, j, strerror(errno)); 131 exit(1); 132 } 133 close(fd); 134 usleep(10); /* give kernel time to destroy */ 135 } 136 } 137 138 static void test_hashmap_percpu(int task, void *data) 139 { 140 unsigned int nr_cpus = bpf_num_possible_cpus(); 141 BPF_DECLARE_PERCPU(long, value); 142 long long key, next_key, first_key; 143 int expected_key_mask = 0; 144 int fd, i; 145 146 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key), 147 sizeof(bpf_percpu(value, 0)), 2, map_flags); 148 if (fd < 0) { 149 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 150 exit(1); 151 } 152 153 for (i = 0; i < nr_cpus; i++) 154 bpf_percpu(value, i) = i + 100; 155 156 key = 1; 157 /* Insert key=1 element. */ 158 assert(!(expected_key_mask & key)); 159 assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0); 160 expected_key_mask |= key; 161 162 /* BPF_NOEXIST means add new element if it doesn't exist. */ 163 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 && 164 /* key=1 already exists. */ 165 errno == EEXIST); 166 167 /* -1 is an invalid flag. */ 168 assert(bpf_map_update_elem(fd, &key, value, -1) == -1 && 169 errno == EINVAL); 170 171 /* Check that key=1 can be found. Value could be 0 if the lookup 172 * was run from a different CPU. 173 */ 174 bpf_percpu(value, 0) = 1; 175 assert(bpf_map_lookup_elem(fd, &key, value) == 0 && 176 bpf_percpu(value, 0) == 100); 177 178 key = 2; 179 /* Check that key=2 is not found. */ 180 assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT); 181 182 /* BPF_EXIST means update existing element. */ 183 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 && 184 /* key=2 is not there. */ 185 errno == ENOENT); 186 187 /* Insert key=2 element. */ 188 assert(!(expected_key_mask & key)); 189 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0); 190 expected_key_mask |= key; 191 192 /* key=1 and key=2 were inserted, check that key=0 cannot be 193 * inserted due to max_entries limit. 194 */ 195 key = 0; 196 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 && 197 errno == E2BIG); 198 199 /* Check that key = 0 doesn't exist. */ 200 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 201 202 /* Iterate over two elements. */ 203 assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 && 204 ((expected_key_mask & first_key) == first_key)); 205 while (!bpf_map_get_next_key(fd, &key, &next_key)) { 206 if (first_key) { 207 assert(next_key == first_key); 208 first_key = 0; 209 } 210 assert((expected_key_mask & next_key) == next_key); 211 expected_key_mask &= ~next_key; 212 213 assert(bpf_map_lookup_elem(fd, &next_key, value) == 0); 214 215 for (i = 0; i < nr_cpus; i++) 216 assert(bpf_percpu(value, i) == i + 100); 217 218 key = next_key; 219 } 220 assert(errno == ENOENT); 221 222 /* Update with BPF_EXIST. */ 223 key = 1; 224 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0); 225 226 /* Delete both elements. */ 227 key = 1; 228 assert(bpf_map_delete_elem(fd, &key) == 0); 229 key = 2; 230 assert(bpf_map_delete_elem(fd, &key) == 0); 231 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 232 233 key = 0; 234 /* Check that map is empty. */ 235 assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 && 236 errno == ENOENT); 237 assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 && 238 errno == ENOENT); 239 240 close(fd); 241 } 242 243 static void test_hashmap_walk(int task, void *data) 244 { 245 int fd, i, max_entries = 100000; 246 long long key, value, next_key; 247 bool next_key_valid = true; 248 249 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 250 max_entries, map_flags); 251 if (fd < 0) { 252 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 253 exit(1); 254 } 255 256 for (i = 0; i < max_entries; i++) { 257 key = i; value = key; 258 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 259 } 260 261 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key, 262 &next_key) == 0; i++) { 263 key = next_key; 264 assert(bpf_map_lookup_elem(fd, &key, &value) == 0); 265 } 266 267 assert(i == max_entries); 268 269 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 270 for (i = 0; next_key_valid; i++) { 271 next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0; 272 assert(bpf_map_lookup_elem(fd, &key, &value) == 0); 273 value++; 274 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); 275 key = next_key; 276 } 277 278 assert(i == max_entries); 279 280 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key, 281 &next_key) == 0; i++) { 282 key = next_key; 283 assert(bpf_map_lookup_elem(fd, &key, &value) == 0); 284 assert(value - 1 == key); 285 } 286 287 assert(i == max_entries); 288 close(fd); 289 } 290 291 static void test_arraymap(int task, void *data) 292 { 293 int key, next_key, fd; 294 long long value; 295 296 fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), 297 2, 0); 298 if (fd < 0) { 299 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 300 exit(1); 301 } 302 303 key = 1; 304 value = 1234; 305 /* Insert key=1 element. */ 306 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 307 308 value = 0; 309 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 310 errno == EEXIST); 311 312 /* Check that key=1 can be found. */ 313 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); 314 315 key = 0; 316 /* Check that key=0 is also found and zero initialized. */ 317 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 318 319 /* key=0 and key=1 were inserted, check that key=2 cannot be inserted 320 * due to max_entries limit. 321 */ 322 key = 2; 323 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 && 324 errno == E2BIG); 325 326 /* Check that key = 2 doesn't exist. */ 327 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 328 329 /* Iterate over two elements. */ 330 assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 && 331 next_key == 0); 332 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 333 next_key == 0); 334 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 335 next_key == 1); 336 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && 337 errno == ENOENT); 338 339 /* Delete shouldn't succeed. */ 340 key = 1; 341 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL); 342 343 close(fd); 344 } 345 346 static void test_arraymap_percpu(int task, void *data) 347 { 348 unsigned int nr_cpus = bpf_num_possible_cpus(); 349 BPF_DECLARE_PERCPU(long, values); 350 int key, next_key, fd, i; 351 352 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), 353 sizeof(bpf_percpu(values, 0)), 2, 0); 354 if (fd < 0) { 355 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 356 exit(1); 357 } 358 359 for (i = 0; i < nr_cpus; i++) 360 bpf_percpu(values, i) = i + 100; 361 362 key = 1; 363 /* Insert key=1 element. */ 364 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); 365 366 bpf_percpu(values, 0) = 0; 367 assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 && 368 errno == EEXIST); 369 370 /* Check that key=1 can be found. */ 371 assert(bpf_map_lookup_elem(fd, &key, values) == 0 && 372 bpf_percpu(values, 0) == 100); 373 374 key = 0; 375 /* Check that key=0 is also found and zero initialized. */ 376 assert(bpf_map_lookup_elem(fd, &key, values) == 0 && 377 bpf_percpu(values, 0) == 0 && 378 bpf_percpu(values, nr_cpus - 1) == 0); 379 380 /* Check that key=2 cannot be inserted due to max_entries limit. */ 381 key = 2; 382 assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 && 383 errno == E2BIG); 384 385 /* Check that key = 2 doesn't exist. */ 386 assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT); 387 388 /* Iterate over two elements. */ 389 assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 && 390 next_key == 0); 391 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 392 next_key == 0); 393 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 394 next_key == 1); 395 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && 396 errno == ENOENT); 397 398 /* Delete shouldn't succeed. */ 399 key = 1; 400 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL); 401 402 close(fd); 403 } 404 405 static void test_arraymap_percpu_many_keys(void) 406 { 407 unsigned int nr_cpus = bpf_num_possible_cpus(); 408 BPF_DECLARE_PERCPU(long, values); 409 /* nr_keys is not too large otherwise the test stresses percpu 410 * allocator more than anything else 411 */ 412 unsigned int nr_keys = 2000; 413 int key, fd, i; 414 415 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), 416 sizeof(bpf_percpu(values, 0)), nr_keys, 0); 417 if (fd < 0) { 418 printf("Failed to create per-cpu arraymap '%s'!\n", 419 strerror(errno)); 420 exit(1); 421 } 422 423 for (i = 0; i < nr_cpus; i++) 424 bpf_percpu(values, i) = i + 10; 425 426 for (key = 0; key < nr_keys; key++) 427 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); 428 429 for (key = 0; key < nr_keys; key++) { 430 for (i = 0; i < nr_cpus; i++) 431 bpf_percpu(values, i) = 0; 432 433 assert(bpf_map_lookup_elem(fd, &key, values) == 0); 434 435 for (i = 0; i < nr_cpus; i++) 436 assert(bpf_percpu(values, i) == i + 10); 437 } 438 439 close(fd); 440 } 441 442 static void test_devmap(int task, void *data) 443 { 444 int fd; 445 __u32 key, value; 446 447 fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value), 448 2, 0); 449 if (fd < 0) { 450 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 451 exit(1); 452 } 453 454 close(fd); 455 } 456 457 #include <sys/socket.h> 458 #include <sys/ioctl.h> 459 #include <arpa/inet.h> 460 #include <sys/select.h> 461 #include <linux/err.h> 462 #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o" 463 #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o" 464 static void test_sockmap(int tasks, void *data) 465 { 466 int one = 1, map_fd_rx, map_fd_tx, map_fd_break, s, sc, rc; 467 struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_break; 468 int ports[] = {50200, 50201, 50202, 50204}; 469 int err, i, fd, sfd[6] = {0xdeadbeef}; 470 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0}; 471 int parse_prog, verdict_prog; 472 struct sockaddr_in addr; 473 struct bpf_object *obj; 474 struct timeval to; 475 __u32 key, value; 476 pid_t pid[tasks]; 477 fd_set w; 478 479 /* Create some sockets to use with sockmap */ 480 for (i = 0; i < 2; i++) { 481 sfd[i] = socket(AF_INET, SOCK_STREAM, 0); 482 if (sfd[i] < 0) 483 goto out; 484 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR, 485 (char *)&one, sizeof(one)); 486 if (err) { 487 printf("failed to setsockopt\n"); 488 goto out; 489 } 490 err = ioctl(sfd[i], FIONBIO, (char *)&one); 491 if (err < 0) { 492 printf("failed to ioctl\n"); 493 goto out; 494 } 495 memset(&addr, 0, sizeof(struct sockaddr_in)); 496 addr.sin_family = AF_INET; 497 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 498 addr.sin_port = htons(ports[i]); 499 err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr)); 500 if (err < 0) { 501 printf("failed to bind: err %i: %i:%i\n", 502 err, i, sfd[i]); 503 goto out; 504 } 505 err = listen(sfd[i], 32); 506 if (err < 0) { 507 printf("failed to listen\n"); 508 goto out; 509 } 510 } 511 512 for (i = 2; i < 4; i++) { 513 sfd[i] = socket(AF_INET, SOCK_STREAM, 0); 514 if (sfd[i] < 0) 515 goto out; 516 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR, 517 (char *)&one, sizeof(one)); 518 if (err) { 519 printf("set sock opt\n"); 520 goto out; 521 } 522 memset(&addr, 0, sizeof(struct sockaddr_in)); 523 addr.sin_family = AF_INET; 524 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 525 addr.sin_port = htons(ports[i - 2]); 526 err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr)); 527 if (err) { 528 printf("failed to connect\n"); 529 goto out; 530 } 531 } 532 533 534 for (i = 4; i < 6; i++) { 535 sfd[i] = accept(sfd[i - 4], NULL, NULL); 536 if (sfd[i] < 0) { 537 printf("accept failed\n"); 538 goto out; 539 } 540 } 541 542 /* Test sockmap with connected sockets */ 543 fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP, 544 sizeof(key), sizeof(value), 545 6, 0); 546 if (fd < 0) { 547 printf("Failed to create sockmap %i\n", fd); 548 goto out_sockmap; 549 } 550 551 /* Test update without programs */ 552 for (i = 0; i < 6; i++) { 553 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 554 if (err) { 555 printf("Failed noprog update sockmap '%i:%i'\n", 556 i, sfd[i]); 557 goto out_sockmap; 558 } 559 } 560 561 /* Test attaching bad fds */ 562 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0); 563 if (!err) { 564 printf("Failed invalid parser prog attach\n"); 565 goto out_sockmap; 566 } 567 568 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0); 569 if (!err) { 570 printf("Failed invalid verdict prog attach\n"); 571 goto out_sockmap; 572 } 573 574 /* Load SK_SKB program and Attach */ 575 err = bpf_prog_load(SOCKMAP_PARSE_PROG, 576 BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog); 577 if (err) { 578 printf("Failed to load SK_SKB parse prog\n"); 579 goto out_sockmap; 580 } 581 582 err = bpf_prog_load(SOCKMAP_VERDICT_PROG, 583 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog); 584 if (err) { 585 printf("Failed to load SK_SKB verdict prog\n"); 586 goto out_sockmap; 587 } 588 589 bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx"); 590 if (IS_ERR(bpf_map_rx)) { 591 printf("Failed to load map rx from verdict prog\n"); 592 goto out_sockmap; 593 } 594 595 map_fd_rx = bpf_map__fd(bpf_map_rx); 596 if (map_fd_rx < 0) { 597 printf("Failed to get map fd\n"); 598 goto out_sockmap; 599 } 600 601 bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx"); 602 if (IS_ERR(bpf_map_tx)) { 603 printf("Failed to load map tx from verdict prog\n"); 604 goto out_sockmap; 605 } 606 607 map_fd_tx = bpf_map__fd(bpf_map_tx); 608 if (map_fd_tx < 0) { 609 printf("Failed to get map tx fd\n"); 610 goto out_sockmap; 611 } 612 613 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break"); 614 if (IS_ERR(bpf_map_break)) { 615 printf("Failed to load map tx from verdict prog\n"); 616 goto out_sockmap; 617 } 618 619 map_fd_break = bpf_map__fd(bpf_map_break); 620 if (map_fd_break < 0) { 621 printf("Failed to get map tx fd\n"); 622 goto out_sockmap; 623 } 624 625 err = bpf_prog_attach(parse_prog, map_fd_break, 626 BPF_SK_SKB_STREAM_PARSER, 0); 627 if (!err) { 628 printf("Allowed attaching SK_SKB program to invalid map\n"); 629 goto out_sockmap; 630 } 631 632 err = bpf_prog_attach(parse_prog, map_fd_rx, 633 BPF_SK_SKB_STREAM_PARSER, 0); 634 if (err) { 635 printf("Failed stream parser bpf prog attach\n"); 636 goto out_sockmap; 637 } 638 639 err = bpf_prog_attach(verdict_prog, map_fd_rx, 640 BPF_SK_SKB_STREAM_VERDICT, 0); 641 if (err) { 642 printf("Failed stream verdict bpf prog attach\n"); 643 goto out_sockmap; 644 } 645 646 /* Test map update elem afterwards fd lives in fd and map_fd */ 647 for (i = 0; i < 6; i++) { 648 err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY); 649 if (err) { 650 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n", 651 err, i, sfd[i]); 652 goto out_sockmap; 653 } 654 err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY); 655 if (err) { 656 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n", 657 err, i, sfd[i]); 658 goto out_sockmap; 659 } 660 } 661 662 /* Test map delete elem and remove send/recv sockets */ 663 for (i = 2; i < 4; i++) { 664 err = bpf_map_delete_elem(map_fd_rx, &i); 665 if (err) { 666 printf("Failed delete sockmap rx %i '%i:%i'\n", 667 err, i, sfd[i]); 668 goto out_sockmap; 669 } 670 err = bpf_map_delete_elem(map_fd_tx, &i); 671 if (err) { 672 printf("Failed delete sockmap tx %i '%i:%i'\n", 673 err, i, sfd[i]); 674 goto out_sockmap; 675 } 676 } 677 678 /* Test map send/recv */ 679 for (i = 0; i < 2; i++) { 680 buf[0] = i; 681 buf[1] = 0x5; 682 sc = send(sfd[2], buf, 20, 0); 683 if (sc < 0) { 684 printf("Failed sockmap send\n"); 685 goto out_sockmap; 686 } 687 688 FD_ZERO(&w); 689 FD_SET(sfd[3], &w); 690 to.tv_sec = 1; 691 to.tv_usec = 0; 692 s = select(sfd[3] + 1, &w, NULL, NULL, &to); 693 if (s == -1) { 694 perror("Failed sockmap select()"); 695 goto out_sockmap; 696 } else if (!s) { 697 printf("Failed sockmap unexpected timeout\n"); 698 goto out_sockmap; 699 } 700 701 if (!FD_ISSET(sfd[3], &w)) { 702 printf("Failed sockmap select/recv\n"); 703 goto out_sockmap; 704 } 705 706 rc = recv(sfd[3], buf, sizeof(buf), 0); 707 if (rc < 0) { 708 printf("Failed sockmap recv\n"); 709 goto out_sockmap; 710 } 711 } 712 713 /* Negative null entry lookup from datapath should be dropped */ 714 buf[0] = 1; 715 buf[1] = 12; 716 sc = send(sfd[2], buf, 20, 0); 717 if (sc < 0) { 718 printf("Failed sockmap send\n"); 719 goto out_sockmap; 720 } 721 722 /* Push fd into same slot */ 723 i = 2; 724 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 725 if (!err) { 726 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n"); 727 goto out_sockmap; 728 } 729 730 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 731 if (err) { 732 printf("Failed sockmap update new slot BPF_ANY\n"); 733 goto out_sockmap; 734 } 735 736 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 737 if (err) { 738 printf("Failed sockmap update new slot BPF_EXIST\n"); 739 goto out_sockmap; 740 } 741 742 /* Delete the elems without programs */ 743 for (i = 0; i < 6; i++) { 744 err = bpf_map_delete_elem(fd, &i); 745 if (err) { 746 printf("Failed delete sockmap %i '%i:%i'\n", 747 err, i, sfd[i]); 748 } 749 } 750 751 /* Test having multiple maps open and set with programs on same fds */ 752 err = bpf_prog_attach(parse_prog, fd, 753 BPF_SK_SKB_STREAM_PARSER, 0); 754 if (err) { 755 printf("Failed fd bpf parse prog attach\n"); 756 goto out_sockmap; 757 } 758 err = bpf_prog_attach(verdict_prog, fd, 759 BPF_SK_SKB_STREAM_VERDICT, 0); 760 if (err) { 761 printf("Failed fd bpf verdict prog attach\n"); 762 goto out_sockmap; 763 } 764 765 for (i = 4; i < 6; i++) { 766 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 767 if (!err) { 768 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n", 769 err, i, sfd[i]); 770 goto out_sockmap; 771 } 772 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 773 if (!err) { 774 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n", 775 err, i, sfd[i]); 776 goto out_sockmap; 777 } 778 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 779 if (!err) { 780 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n", 781 err, i, sfd[i]); 782 goto out_sockmap; 783 } 784 } 785 786 /* Test tasks number of forked operations */ 787 for (i = 0; i < tasks; i++) { 788 pid[i] = fork(); 789 if (pid[i] == 0) { 790 for (i = 0; i < 6; i++) { 791 bpf_map_delete_elem(map_fd_tx, &i); 792 bpf_map_delete_elem(map_fd_rx, &i); 793 bpf_map_update_elem(map_fd_tx, &i, 794 &sfd[i], BPF_ANY); 795 bpf_map_update_elem(map_fd_rx, &i, 796 &sfd[i], BPF_ANY); 797 } 798 exit(0); 799 } else if (pid[i] == -1) { 800 printf("Couldn't spawn #%d process!\n", i); 801 exit(1); 802 } 803 } 804 805 for (i = 0; i < tasks; i++) { 806 int status; 807 808 assert(waitpid(pid[i], &status, 0) == pid[i]); 809 assert(status == 0); 810 } 811 812 /* Test map close sockets */ 813 for (i = 0; i < 6; i++) 814 close(sfd[i]); 815 close(fd); 816 close(map_fd_rx); 817 bpf_object__close(obj); 818 return; 819 out: 820 for (i = 0; i < 6; i++) 821 close(sfd[i]); 822 printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno)); 823 exit(1); 824 out_sockmap: 825 for (i = 0; i < 6; i++) 826 close(sfd[i]); 827 close(fd); 828 exit(1); 829 } 830 831 #define MAP_SIZE (32 * 1024) 832 833 static void test_map_large(void) 834 { 835 struct bigkey { 836 int a; 837 char b[116]; 838 long long c; 839 } key; 840 int fd, i, value; 841 842 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 843 MAP_SIZE, map_flags); 844 if (fd < 0) { 845 printf("Failed to create large map '%s'!\n", strerror(errno)); 846 exit(1); 847 } 848 849 for (i = 0; i < MAP_SIZE; i++) { 850 key = (struct bigkey) { .c = i }; 851 value = i; 852 853 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 854 } 855 856 key.c = -1; 857 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 858 errno == E2BIG); 859 860 /* Iterate through all elements. */ 861 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 862 key.c = -1; 863 for (i = 0; i < MAP_SIZE; i++) 864 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 865 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 866 867 key.c = 0; 868 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 869 key.a = 1; 870 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 871 872 close(fd); 873 } 874 875 static void run_parallel(int tasks, void (*fn)(int task, void *data), 876 void *data) 877 { 878 pid_t pid[tasks]; 879 int i; 880 881 for (i = 0; i < tasks; i++) { 882 pid[i] = fork(); 883 if (pid[i] == 0) { 884 fn(i, data); 885 exit(0); 886 } else if (pid[i] == -1) { 887 printf("Couldn't spawn #%d process!\n", i); 888 exit(1); 889 } 890 } 891 892 for (i = 0; i < tasks; i++) { 893 int status; 894 895 assert(waitpid(pid[i], &status, 0) == pid[i]); 896 assert(status == 0); 897 } 898 } 899 900 static void test_map_stress(void) 901 { 902 run_parallel(100, test_hashmap, NULL); 903 run_parallel(100, test_hashmap_percpu, NULL); 904 run_parallel(100, test_hashmap_sizes, NULL); 905 run_parallel(100, test_hashmap_walk, NULL); 906 907 run_parallel(100, test_arraymap, NULL); 908 run_parallel(100, test_arraymap_percpu, NULL); 909 } 910 911 #define TASKS 1024 912 913 #define DO_UPDATE 1 914 #define DO_DELETE 0 915 916 static void do_work(int fn, void *data) 917 { 918 int do_update = ((int *)data)[1]; 919 int fd = ((int *)data)[0]; 920 int i, key, value; 921 922 for (i = fn; i < MAP_SIZE; i += TASKS) { 923 key = value = i; 924 925 if (do_update) { 926 assert(bpf_map_update_elem(fd, &key, &value, 927 BPF_NOEXIST) == 0); 928 assert(bpf_map_update_elem(fd, &key, &value, 929 BPF_EXIST) == 0); 930 } else { 931 assert(bpf_map_delete_elem(fd, &key) == 0); 932 } 933 } 934 } 935 936 static void test_map_parallel(void) 937 { 938 int i, fd, key = 0, value = 0; 939 int data[2]; 940 941 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 942 MAP_SIZE, map_flags); 943 if (fd < 0) { 944 printf("Failed to create map for parallel test '%s'!\n", 945 strerror(errno)); 946 exit(1); 947 } 948 949 /* Use the same fd in children to add elements to this map: 950 * child_0 adds key=0, key=1024, key=2048, ... 951 * child_1 adds key=1, key=1025, key=2049, ... 952 * child_1023 adds key=1023, ... 953 */ 954 data[0] = fd; 955 data[1] = DO_UPDATE; 956 run_parallel(TASKS, do_work, data); 957 958 /* Check that key=0 is already there. */ 959 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 960 errno == EEXIST); 961 962 /* Check that all elements were inserted. */ 963 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 964 key = -1; 965 for (i = 0; i < MAP_SIZE; i++) 966 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 967 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 968 969 /* Another check for all elements */ 970 for (i = 0; i < MAP_SIZE; i++) { 971 key = MAP_SIZE - i - 1; 972 973 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && 974 value == key); 975 } 976 977 /* Now let's delete all elemenets in parallel. */ 978 data[1] = DO_DELETE; 979 run_parallel(TASKS, do_work, data); 980 981 /* Nothing should be left. */ 982 key = -1; 983 assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT); 984 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 985 } 986 987 static void run_all_tests(void) 988 { 989 test_hashmap(0, NULL); 990 test_hashmap_percpu(0, NULL); 991 test_hashmap_walk(0, NULL); 992 993 test_arraymap(0, NULL); 994 test_arraymap_percpu(0, NULL); 995 996 test_arraymap_percpu_many_keys(); 997 998 test_devmap(0, NULL); 999 test_sockmap(0, NULL); 1000 1001 test_map_large(); 1002 test_map_parallel(); 1003 test_map_stress(); 1004 } 1005 1006 int main(void) 1007 { 1008 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; 1009 1010 setrlimit(RLIMIT_MEMLOCK, &rinf); 1011 1012 map_flags = 0; 1013 run_all_tests(); 1014 1015 map_flags = BPF_F_NO_PREALLOC; 1016 run_all_tests(); 1017 1018 printf("test_maps: OK\n"); 1019 return 0; 1020 } 1021