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/detaching 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 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0); 575 if (!err) { 576 printf("Failed unknown prog attach\n"); 577 goto out_sockmap; 578 } 579 580 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER); 581 if (err) { 582 printf("Failed empty parser prog detach\n"); 583 goto out_sockmap; 584 } 585 586 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT); 587 if (err) { 588 printf("Failed empty verdict prog detach\n"); 589 goto out_sockmap; 590 } 591 592 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE); 593 if (!err) { 594 printf("Detach invalid prog successful\n"); 595 goto out_sockmap; 596 } 597 598 /* Load SK_SKB program and Attach */ 599 err = bpf_prog_load(SOCKMAP_PARSE_PROG, 600 BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog); 601 if (err) { 602 printf("Failed to load SK_SKB parse prog\n"); 603 goto out_sockmap; 604 } 605 606 err = bpf_prog_load(SOCKMAP_VERDICT_PROG, 607 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog); 608 if (err) { 609 printf("Failed to load SK_SKB verdict prog\n"); 610 goto out_sockmap; 611 } 612 613 bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx"); 614 if (IS_ERR(bpf_map_rx)) { 615 printf("Failed to load map rx from verdict prog\n"); 616 goto out_sockmap; 617 } 618 619 map_fd_rx = bpf_map__fd(bpf_map_rx); 620 if (map_fd_rx < 0) { 621 printf("Failed to get map fd\n"); 622 goto out_sockmap; 623 } 624 625 bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx"); 626 if (IS_ERR(bpf_map_tx)) { 627 printf("Failed to load map tx from verdict prog\n"); 628 goto out_sockmap; 629 } 630 631 map_fd_tx = bpf_map__fd(bpf_map_tx); 632 if (map_fd_tx < 0) { 633 printf("Failed to get map tx fd\n"); 634 goto out_sockmap; 635 } 636 637 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break"); 638 if (IS_ERR(bpf_map_break)) { 639 printf("Failed to load map tx from verdict prog\n"); 640 goto out_sockmap; 641 } 642 643 map_fd_break = bpf_map__fd(bpf_map_break); 644 if (map_fd_break < 0) { 645 printf("Failed to get map tx fd\n"); 646 goto out_sockmap; 647 } 648 649 err = bpf_prog_attach(parse_prog, map_fd_break, 650 BPF_SK_SKB_STREAM_PARSER, 0); 651 if (!err) { 652 printf("Allowed attaching SK_SKB program to invalid map\n"); 653 goto out_sockmap; 654 } 655 656 err = bpf_prog_attach(parse_prog, map_fd_rx, 657 BPF_SK_SKB_STREAM_PARSER, 0); 658 if (err) { 659 printf("Failed stream parser bpf prog attach\n"); 660 goto out_sockmap; 661 } 662 663 err = bpf_prog_attach(verdict_prog, map_fd_rx, 664 BPF_SK_SKB_STREAM_VERDICT, 0); 665 if (err) { 666 printf("Failed stream verdict bpf prog attach\n"); 667 goto out_sockmap; 668 } 669 670 err = bpf_prog_attach(verdict_prog, map_fd_rx, 671 __MAX_BPF_ATTACH_TYPE, 0); 672 if (!err) { 673 printf("Attached unknown bpf prog\n"); 674 goto out_sockmap; 675 } 676 677 /* Test map update elem afterwards fd lives in fd and map_fd */ 678 for (i = 0; i < 6; i++) { 679 err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY); 680 if (err) { 681 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n", 682 err, i, sfd[i]); 683 goto out_sockmap; 684 } 685 err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY); 686 if (err) { 687 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n", 688 err, i, sfd[i]); 689 goto out_sockmap; 690 } 691 } 692 693 /* Test map delete elem and remove send/recv sockets */ 694 for (i = 2; i < 4; i++) { 695 err = bpf_map_delete_elem(map_fd_rx, &i); 696 if (err) { 697 printf("Failed delete sockmap rx %i '%i:%i'\n", 698 err, i, sfd[i]); 699 goto out_sockmap; 700 } 701 err = bpf_map_delete_elem(map_fd_tx, &i); 702 if (err) { 703 printf("Failed delete sockmap tx %i '%i:%i'\n", 704 err, i, sfd[i]); 705 goto out_sockmap; 706 } 707 } 708 709 /* Test map send/recv */ 710 for (i = 0; i < 2; i++) { 711 buf[0] = i; 712 buf[1] = 0x5; 713 sc = send(sfd[2], buf, 20, 0); 714 if (sc < 0) { 715 printf("Failed sockmap send\n"); 716 goto out_sockmap; 717 } 718 719 FD_ZERO(&w); 720 FD_SET(sfd[3], &w); 721 to.tv_sec = 1; 722 to.tv_usec = 0; 723 s = select(sfd[3] + 1, &w, NULL, NULL, &to); 724 if (s == -1) { 725 perror("Failed sockmap select()"); 726 goto out_sockmap; 727 } else if (!s) { 728 printf("Failed sockmap unexpected timeout\n"); 729 goto out_sockmap; 730 } 731 732 if (!FD_ISSET(sfd[3], &w)) { 733 printf("Failed sockmap select/recv\n"); 734 goto out_sockmap; 735 } 736 737 rc = recv(sfd[3], buf, sizeof(buf), 0); 738 if (rc < 0) { 739 printf("Failed sockmap recv\n"); 740 goto out_sockmap; 741 } 742 } 743 744 /* Negative null entry lookup from datapath should be dropped */ 745 buf[0] = 1; 746 buf[1] = 12; 747 sc = send(sfd[2], buf, 20, 0); 748 if (sc < 0) { 749 printf("Failed sockmap send\n"); 750 goto out_sockmap; 751 } 752 753 /* Push fd into same slot */ 754 i = 2; 755 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 756 if (!err) { 757 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n"); 758 goto out_sockmap; 759 } 760 761 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 762 if (err) { 763 printf("Failed sockmap update new slot BPF_ANY\n"); 764 goto out_sockmap; 765 } 766 767 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 768 if (err) { 769 printf("Failed sockmap update new slot BPF_EXIST\n"); 770 goto out_sockmap; 771 } 772 773 /* Delete the elems without programs */ 774 for (i = 0; i < 6; i++) { 775 err = bpf_map_delete_elem(fd, &i); 776 if (err) { 777 printf("Failed delete sockmap %i '%i:%i'\n", 778 err, i, sfd[i]); 779 } 780 } 781 782 /* Test having multiple maps open and set with programs on same fds */ 783 err = bpf_prog_attach(parse_prog, fd, 784 BPF_SK_SKB_STREAM_PARSER, 0); 785 if (err) { 786 printf("Failed fd bpf parse prog attach\n"); 787 goto out_sockmap; 788 } 789 err = bpf_prog_attach(verdict_prog, fd, 790 BPF_SK_SKB_STREAM_VERDICT, 0); 791 if (err) { 792 printf("Failed fd bpf verdict prog attach\n"); 793 goto out_sockmap; 794 } 795 796 for (i = 4; i < 6; i++) { 797 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 798 if (!err) { 799 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n", 800 err, i, sfd[i]); 801 goto out_sockmap; 802 } 803 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 804 if (!err) { 805 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n", 806 err, i, sfd[i]); 807 goto out_sockmap; 808 } 809 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 810 if (!err) { 811 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n", 812 err, i, sfd[i]); 813 goto out_sockmap; 814 } 815 } 816 817 /* Test tasks number of forked operations */ 818 for (i = 0; i < tasks; i++) { 819 pid[i] = fork(); 820 if (pid[i] == 0) { 821 for (i = 0; i < 6; i++) { 822 bpf_map_delete_elem(map_fd_tx, &i); 823 bpf_map_delete_elem(map_fd_rx, &i); 824 bpf_map_update_elem(map_fd_tx, &i, 825 &sfd[i], BPF_ANY); 826 bpf_map_update_elem(map_fd_rx, &i, 827 &sfd[i], BPF_ANY); 828 } 829 exit(0); 830 } else if (pid[i] == -1) { 831 printf("Couldn't spawn #%d process!\n", i); 832 exit(1); 833 } 834 } 835 836 for (i = 0; i < tasks; i++) { 837 int status; 838 839 assert(waitpid(pid[i], &status, 0) == pid[i]); 840 assert(status == 0); 841 } 842 843 err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE); 844 if (!err) { 845 printf("Detached an invalid prog type.\n"); 846 goto out_sockmap; 847 } 848 849 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER); 850 if (err) { 851 printf("Failed parser prog detach\n"); 852 goto out_sockmap; 853 } 854 855 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT); 856 if (err) { 857 printf("Failed parser prog detach\n"); 858 goto out_sockmap; 859 } 860 861 /* Test map close sockets */ 862 for (i = 0; i < 6; i++) 863 close(sfd[i]); 864 close(fd); 865 close(map_fd_rx); 866 bpf_object__close(obj); 867 return; 868 out: 869 for (i = 0; i < 6; i++) 870 close(sfd[i]); 871 printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno)); 872 exit(1); 873 out_sockmap: 874 for (i = 0; i < 6; i++) 875 close(sfd[i]); 876 close(fd); 877 exit(1); 878 } 879 880 #define MAP_SIZE (32 * 1024) 881 882 static void test_map_large(void) 883 { 884 struct bigkey { 885 int a; 886 char b[116]; 887 long long c; 888 } key; 889 int fd, i, value; 890 891 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 892 MAP_SIZE, map_flags); 893 if (fd < 0) { 894 printf("Failed to create large map '%s'!\n", strerror(errno)); 895 exit(1); 896 } 897 898 for (i = 0; i < MAP_SIZE; i++) { 899 key = (struct bigkey) { .c = i }; 900 value = i; 901 902 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 903 } 904 905 key.c = -1; 906 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 907 errno == E2BIG); 908 909 /* Iterate through all elements. */ 910 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 911 key.c = -1; 912 for (i = 0; i < MAP_SIZE; i++) 913 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 914 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 915 916 key.c = 0; 917 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 918 key.a = 1; 919 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 920 921 close(fd); 922 } 923 924 static void run_parallel(int tasks, void (*fn)(int task, void *data), 925 void *data) 926 { 927 pid_t pid[tasks]; 928 int i; 929 930 for (i = 0; i < tasks; i++) { 931 pid[i] = fork(); 932 if (pid[i] == 0) { 933 fn(i, data); 934 exit(0); 935 } else if (pid[i] == -1) { 936 printf("Couldn't spawn #%d process!\n", i); 937 exit(1); 938 } 939 } 940 941 for (i = 0; i < tasks; i++) { 942 int status; 943 944 assert(waitpid(pid[i], &status, 0) == pid[i]); 945 assert(status == 0); 946 } 947 } 948 949 static void test_map_stress(void) 950 { 951 run_parallel(100, test_hashmap, NULL); 952 run_parallel(100, test_hashmap_percpu, NULL); 953 run_parallel(100, test_hashmap_sizes, NULL); 954 run_parallel(100, test_hashmap_walk, NULL); 955 956 run_parallel(100, test_arraymap, NULL); 957 run_parallel(100, test_arraymap_percpu, NULL); 958 } 959 960 #define TASKS 1024 961 962 #define DO_UPDATE 1 963 #define DO_DELETE 0 964 965 static void do_work(int fn, void *data) 966 { 967 int do_update = ((int *)data)[1]; 968 int fd = ((int *)data)[0]; 969 int i, key, value; 970 971 for (i = fn; i < MAP_SIZE; i += TASKS) { 972 key = value = i; 973 974 if (do_update) { 975 assert(bpf_map_update_elem(fd, &key, &value, 976 BPF_NOEXIST) == 0); 977 assert(bpf_map_update_elem(fd, &key, &value, 978 BPF_EXIST) == 0); 979 } else { 980 assert(bpf_map_delete_elem(fd, &key) == 0); 981 } 982 } 983 } 984 985 static void test_map_parallel(void) 986 { 987 int i, fd, key = 0, value = 0; 988 int data[2]; 989 990 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 991 MAP_SIZE, map_flags); 992 if (fd < 0) { 993 printf("Failed to create map for parallel test '%s'!\n", 994 strerror(errno)); 995 exit(1); 996 } 997 998 /* Use the same fd in children to add elements to this map: 999 * child_0 adds key=0, key=1024, key=2048, ... 1000 * child_1 adds key=1, key=1025, key=2049, ... 1001 * child_1023 adds key=1023, ... 1002 */ 1003 data[0] = fd; 1004 data[1] = DO_UPDATE; 1005 run_parallel(TASKS, do_work, data); 1006 1007 /* Check that key=0 is already there. */ 1008 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 1009 errno == EEXIST); 1010 1011 /* Check that all elements were inserted. */ 1012 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 1013 key = -1; 1014 for (i = 0; i < MAP_SIZE; i++) 1015 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 1016 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 1017 1018 /* Another check for all elements */ 1019 for (i = 0; i < MAP_SIZE; i++) { 1020 key = MAP_SIZE - i - 1; 1021 1022 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && 1023 value == key); 1024 } 1025 1026 /* Now let's delete all elemenets in parallel. */ 1027 data[1] = DO_DELETE; 1028 run_parallel(TASKS, do_work, data); 1029 1030 /* Nothing should be left. */ 1031 key = -1; 1032 assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT); 1033 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 1034 } 1035 1036 static void run_all_tests(void) 1037 { 1038 test_hashmap(0, NULL); 1039 test_hashmap_percpu(0, NULL); 1040 test_hashmap_walk(0, NULL); 1041 1042 test_arraymap(0, NULL); 1043 test_arraymap_percpu(0, NULL); 1044 1045 test_arraymap_percpu_many_keys(); 1046 1047 test_devmap(0, NULL); 1048 test_sockmap(0, NULL); 1049 1050 test_map_large(); 1051 test_map_parallel(); 1052 test_map_stress(); 1053 } 1054 1055 int main(void) 1056 { 1057 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; 1058 1059 setrlimit(RLIMIT_MEMLOCK, &rinf); 1060 1061 map_flags = 0; 1062 run_all_tests(); 1063 1064 map_flags = BPF_F_NO_PREALLOC; 1065 run_all_tests(); 1066 1067 printf("test_maps: OK\n"); 1068 return 0; 1069 } 1070