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