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