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/socket.h> 21 #include <netinet/in.h> 22 #include <linux/bpf.h> 23 24 #include <bpf/bpf.h> 25 #include <bpf/libbpf.h> 26 27 #include "bpf_util.h" 28 #include "bpf_rlimit.h" 29 30 #ifndef ENOTSUPP 31 #define ENOTSUPP 524 32 #endif 33 34 static int map_flags; 35 36 #define CHECK(condition, tag, format...) ({ \ 37 int __ret = !!(condition); \ 38 if (__ret) { \ 39 printf("%s(%d):FAIL:%s ", __func__, __LINE__, tag); \ 40 printf(format); \ 41 exit(-1); \ 42 } \ 43 }) 44 45 static void test_hashmap(int task, void *data) 46 { 47 long long key, next_key, first_key, value; 48 int fd; 49 50 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 51 2, map_flags); 52 if (fd < 0) { 53 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 54 exit(1); 55 } 56 57 key = 1; 58 value = 1234; 59 /* Insert key=1 element. */ 60 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 61 62 value = 0; 63 /* BPF_NOEXIST means add new element if it doesn't exist. */ 64 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 65 /* key=1 already exists. */ 66 errno == EEXIST); 67 68 /* -1 is an invalid flag. */ 69 assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 && 70 errno == EINVAL); 71 72 /* Check that key=1 can be found. */ 73 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); 74 75 key = 2; 76 /* Check that key=2 is not found. */ 77 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 78 79 /* BPF_EXIST means update existing element. */ 80 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 && 81 /* key=2 is not there. */ 82 errno == ENOENT); 83 84 /* Insert key=2 element. */ 85 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 86 87 /* key=1 and key=2 were inserted, check that key=0 cannot be 88 * inserted due to max_entries limit. 89 */ 90 key = 0; 91 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 92 errno == E2BIG); 93 94 /* Update existing element, though the map is full. */ 95 key = 1; 96 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); 97 key = 2; 98 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 99 key = 3; 100 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 101 errno == E2BIG); 102 103 /* Check that key = 0 doesn't exist. */ 104 key = 0; 105 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 106 107 /* Iterate over two elements. */ 108 assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 && 109 (first_key == 1 || first_key == 2)); 110 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 111 (next_key == first_key)); 112 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 113 (next_key == 1 || next_key == 2) && 114 (next_key != first_key)); 115 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && 116 errno == ENOENT); 117 118 /* Delete both elements. */ 119 key = 1; 120 assert(bpf_map_delete_elem(fd, &key) == 0); 121 key = 2; 122 assert(bpf_map_delete_elem(fd, &key) == 0); 123 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 124 125 key = 0; 126 /* Check that map is empty. */ 127 assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 && 128 errno == ENOENT); 129 assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 && 130 errno == ENOENT); 131 132 close(fd); 133 } 134 135 static void test_hashmap_sizes(int task, void *data) 136 { 137 int fd, i, j; 138 139 for (i = 1; i <= 512; i <<= 1) 140 for (j = 1; j <= 1 << 18; j <<= 1) { 141 fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j, 142 2, map_flags); 143 if (fd < 0) { 144 if (errno == ENOMEM) 145 return; 146 printf("Failed to create hashmap key=%d value=%d '%s'\n", 147 i, j, strerror(errno)); 148 exit(1); 149 } 150 close(fd); 151 usleep(10); /* give kernel time to destroy */ 152 } 153 } 154 155 static void test_hashmap_percpu(int task, void *data) 156 { 157 unsigned int nr_cpus = bpf_num_possible_cpus(); 158 BPF_DECLARE_PERCPU(long, value); 159 long long key, next_key, first_key; 160 int expected_key_mask = 0; 161 int fd, i; 162 163 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key), 164 sizeof(bpf_percpu(value, 0)), 2, map_flags); 165 if (fd < 0) { 166 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 167 exit(1); 168 } 169 170 for (i = 0; i < nr_cpus; i++) 171 bpf_percpu(value, i) = i + 100; 172 173 key = 1; 174 /* Insert key=1 element. */ 175 assert(!(expected_key_mask & key)); 176 assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0); 177 expected_key_mask |= key; 178 179 /* BPF_NOEXIST means add new element if it doesn't exist. */ 180 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 && 181 /* key=1 already exists. */ 182 errno == EEXIST); 183 184 /* -1 is an invalid flag. */ 185 assert(bpf_map_update_elem(fd, &key, value, -1) == -1 && 186 errno == EINVAL); 187 188 /* Check that key=1 can be found. Value could be 0 if the lookup 189 * was run from a different CPU. 190 */ 191 bpf_percpu(value, 0) = 1; 192 assert(bpf_map_lookup_elem(fd, &key, value) == 0 && 193 bpf_percpu(value, 0) == 100); 194 195 key = 2; 196 /* Check that key=2 is not found. */ 197 assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT); 198 199 /* BPF_EXIST means update existing element. */ 200 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 && 201 /* key=2 is not there. */ 202 errno == ENOENT); 203 204 /* Insert key=2 element. */ 205 assert(!(expected_key_mask & key)); 206 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0); 207 expected_key_mask |= key; 208 209 /* key=1 and key=2 were inserted, check that key=0 cannot be 210 * inserted due to max_entries limit. 211 */ 212 key = 0; 213 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 && 214 errno == E2BIG); 215 216 /* Check that key = 0 doesn't exist. */ 217 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 218 219 /* Iterate over two elements. */ 220 assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 && 221 ((expected_key_mask & first_key) == first_key)); 222 while (!bpf_map_get_next_key(fd, &key, &next_key)) { 223 if (first_key) { 224 assert(next_key == first_key); 225 first_key = 0; 226 } 227 assert((expected_key_mask & next_key) == next_key); 228 expected_key_mask &= ~next_key; 229 230 assert(bpf_map_lookup_elem(fd, &next_key, value) == 0); 231 232 for (i = 0; i < nr_cpus; i++) 233 assert(bpf_percpu(value, i) == i + 100); 234 235 key = next_key; 236 } 237 assert(errno == ENOENT); 238 239 /* Update with BPF_EXIST. */ 240 key = 1; 241 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0); 242 243 /* Delete both elements. */ 244 key = 1; 245 assert(bpf_map_delete_elem(fd, &key) == 0); 246 key = 2; 247 assert(bpf_map_delete_elem(fd, &key) == 0); 248 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 249 250 key = 0; 251 /* Check that map is empty. */ 252 assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 && 253 errno == ENOENT); 254 assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 && 255 errno == ENOENT); 256 257 close(fd); 258 } 259 260 static void test_hashmap_walk(int task, void *data) 261 { 262 int fd, i, max_entries = 1000; 263 long long key, value, next_key; 264 bool next_key_valid = true; 265 266 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 267 max_entries, map_flags); 268 if (fd < 0) { 269 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 270 exit(1); 271 } 272 273 for (i = 0; i < max_entries; i++) { 274 key = i; value = key; 275 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 276 } 277 278 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key, 279 &next_key) == 0; i++) { 280 key = next_key; 281 assert(bpf_map_lookup_elem(fd, &key, &value) == 0); 282 } 283 284 assert(i == max_entries); 285 286 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 287 for (i = 0; next_key_valid; i++) { 288 next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0; 289 assert(bpf_map_lookup_elem(fd, &key, &value) == 0); 290 value++; 291 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); 292 key = next_key; 293 } 294 295 assert(i == max_entries); 296 297 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key, 298 &next_key) == 0; i++) { 299 key = next_key; 300 assert(bpf_map_lookup_elem(fd, &key, &value) == 0); 301 assert(value - 1 == key); 302 } 303 304 assert(i == max_entries); 305 close(fd); 306 } 307 308 static void test_arraymap(int task, void *data) 309 { 310 int key, next_key, fd; 311 long long value; 312 313 fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), 314 2, 0); 315 if (fd < 0) { 316 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 317 exit(1); 318 } 319 320 key = 1; 321 value = 1234; 322 /* Insert key=1 element. */ 323 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 324 325 value = 0; 326 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 327 errno == EEXIST); 328 329 /* Check that key=1 can be found. */ 330 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); 331 332 key = 0; 333 /* Check that key=0 is also found and zero initialized. */ 334 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 335 336 /* key=0 and key=1 were inserted, check that key=2 cannot be inserted 337 * due to max_entries limit. 338 */ 339 key = 2; 340 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 && 341 errno == E2BIG); 342 343 /* Check that key = 2 doesn't exist. */ 344 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 345 346 /* Iterate over two elements. */ 347 assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 && 348 next_key == 0); 349 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 350 next_key == 0); 351 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 352 next_key == 1); 353 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && 354 errno == ENOENT); 355 356 /* Delete shouldn't succeed. */ 357 key = 1; 358 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL); 359 360 close(fd); 361 } 362 363 static void test_arraymap_percpu(int task, void *data) 364 { 365 unsigned int nr_cpus = bpf_num_possible_cpus(); 366 BPF_DECLARE_PERCPU(long, values); 367 int key, next_key, fd, i; 368 369 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), 370 sizeof(bpf_percpu(values, 0)), 2, 0); 371 if (fd < 0) { 372 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 373 exit(1); 374 } 375 376 for (i = 0; i < nr_cpus; i++) 377 bpf_percpu(values, i) = i + 100; 378 379 key = 1; 380 /* Insert key=1 element. */ 381 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); 382 383 bpf_percpu(values, 0) = 0; 384 assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 && 385 errno == EEXIST); 386 387 /* Check that key=1 can be found. */ 388 assert(bpf_map_lookup_elem(fd, &key, values) == 0 && 389 bpf_percpu(values, 0) == 100); 390 391 key = 0; 392 /* Check that key=0 is also found and zero initialized. */ 393 assert(bpf_map_lookup_elem(fd, &key, values) == 0 && 394 bpf_percpu(values, 0) == 0 && 395 bpf_percpu(values, nr_cpus - 1) == 0); 396 397 /* Check that key=2 cannot be inserted due to max_entries limit. */ 398 key = 2; 399 assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 && 400 errno == E2BIG); 401 402 /* Check that key = 2 doesn't exist. */ 403 assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT); 404 405 /* Iterate over two elements. */ 406 assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 && 407 next_key == 0); 408 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 409 next_key == 0); 410 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 411 next_key == 1); 412 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && 413 errno == ENOENT); 414 415 /* Delete shouldn't succeed. */ 416 key = 1; 417 assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL); 418 419 close(fd); 420 } 421 422 static void test_arraymap_percpu_many_keys(void) 423 { 424 unsigned int nr_cpus = bpf_num_possible_cpus(); 425 BPF_DECLARE_PERCPU(long, values); 426 /* nr_keys is not too large otherwise the test stresses percpu 427 * allocator more than anything else 428 */ 429 unsigned int nr_keys = 2000; 430 int key, fd, i; 431 432 fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), 433 sizeof(bpf_percpu(values, 0)), nr_keys, 0); 434 if (fd < 0) { 435 printf("Failed to create per-cpu arraymap '%s'!\n", 436 strerror(errno)); 437 exit(1); 438 } 439 440 for (i = 0; i < nr_cpus; i++) 441 bpf_percpu(values, i) = i + 10; 442 443 for (key = 0; key < nr_keys; key++) 444 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); 445 446 for (key = 0; key < nr_keys; key++) { 447 for (i = 0; i < nr_cpus; i++) 448 bpf_percpu(values, i) = 0; 449 450 assert(bpf_map_lookup_elem(fd, &key, values) == 0); 451 452 for (i = 0; i < nr_cpus; i++) 453 assert(bpf_percpu(values, i) == i + 10); 454 } 455 456 close(fd); 457 } 458 459 static void test_devmap(int task, void *data) 460 { 461 int fd; 462 __u32 key, value; 463 464 fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value), 465 2, 0); 466 if (fd < 0) { 467 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 468 exit(1); 469 } 470 471 close(fd); 472 } 473 474 #include <sys/socket.h> 475 #include <sys/ioctl.h> 476 #include <arpa/inet.h> 477 #include <sys/select.h> 478 #include <linux/err.h> 479 #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o" 480 #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o" 481 #define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o" 482 static void test_sockmap(int tasks, void *data) 483 { 484 struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break; 485 int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break; 486 int ports[] = {50200, 50201, 50202, 50204}; 487 int err, i, fd, udp, sfd[6] = {0xdeadbeef}; 488 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0}; 489 int parse_prog, verdict_prog, msg_prog; 490 struct sockaddr_in addr; 491 int one = 1, s, sc, rc; 492 struct bpf_object *obj; 493 struct timeval to; 494 __u32 key, value; 495 pid_t pid[tasks]; 496 fd_set w; 497 498 /* Create some sockets to use with sockmap */ 499 for (i = 0; i < 2; i++) { 500 sfd[i] = socket(AF_INET, SOCK_STREAM, 0); 501 if (sfd[i] < 0) 502 goto out; 503 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR, 504 (char *)&one, sizeof(one)); 505 if (err) { 506 printf("failed to setsockopt\n"); 507 goto out; 508 } 509 err = ioctl(sfd[i], FIONBIO, (char *)&one); 510 if (err < 0) { 511 printf("failed to ioctl\n"); 512 goto out; 513 } 514 memset(&addr, 0, sizeof(struct sockaddr_in)); 515 addr.sin_family = AF_INET; 516 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 517 addr.sin_port = htons(ports[i]); 518 err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr)); 519 if (err < 0) { 520 printf("failed to bind: err %i: %i:%i\n", 521 err, i, sfd[i]); 522 goto out; 523 } 524 err = listen(sfd[i], 32); 525 if (err < 0) { 526 printf("failed to listen\n"); 527 goto out; 528 } 529 } 530 531 for (i = 2; i < 4; i++) { 532 sfd[i] = socket(AF_INET, SOCK_STREAM, 0); 533 if (sfd[i] < 0) 534 goto out; 535 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR, 536 (char *)&one, sizeof(one)); 537 if (err) { 538 printf("set sock opt\n"); 539 goto out; 540 } 541 memset(&addr, 0, sizeof(struct sockaddr_in)); 542 addr.sin_family = AF_INET; 543 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 544 addr.sin_port = htons(ports[i - 2]); 545 err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr)); 546 if (err) { 547 printf("failed to connect\n"); 548 goto out; 549 } 550 } 551 552 553 for (i = 4; i < 6; i++) { 554 sfd[i] = accept(sfd[i - 4], NULL, NULL); 555 if (sfd[i] < 0) { 556 printf("accept failed\n"); 557 goto out; 558 } 559 } 560 561 /* Test sockmap with connected sockets */ 562 fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP, 563 sizeof(key), sizeof(value), 564 6, 0); 565 if (fd < 0) { 566 printf("Failed to create sockmap %i\n", fd); 567 goto out_sockmap; 568 } 569 570 /* Test update with unsupported UDP socket */ 571 udp = socket(AF_INET, SOCK_DGRAM, 0); 572 i = 0; 573 err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY); 574 if (!err) { 575 printf("Failed socket SOCK_DGRAM allowed '%i:%i'\n", 576 i, udp); 577 goto out_sockmap; 578 } 579 580 /* Test update without programs */ 581 for (i = 0; i < 6; i++) { 582 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 583 if (i < 2 && !err) { 584 printf("Allowed update sockmap '%i:%i' not in ESTABLISHED\n", 585 i, sfd[i]); 586 goto out_sockmap; 587 } else if (i >= 2 && err) { 588 printf("Failed noprog update sockmap '%i:%i'\n", 589 i, sfd[i]); 590 goto out_sockmap; 591 } 592 } 593 594 /* Test attaching/detaching bad fds */ 595 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0); 596 if (!err) { 597 printf("Failed invalid parser prog attach\n"); 598 goto out_sockmap; 599 } 600 601 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0); 602 if (!err) { 603 printf("Failed invalid verdict prog attach\n"); 604 goto out_sockmap; 605 } 606 607 err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0); 608 if (!err) { 609 printf("Failed invalid msg verdict prog attach\n"); 610 goto out_sockmap; 611 } 612 613 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0); 614 if (!err) { 615 printf("Failed unknown prog attach\n"); 616 goto out_sockmap; 617 } 618 619 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER); 620 if (err) { 621 printf("Failed empty parser prog detach\n"); 622 goto out_sockmap; 623 } 624 625 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT); 626 if (err) { 627 printf("Failed empty verdict prog detach\n"); 628 goto out_sockmap; 629 } 630 631 err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT); 632 if (err) { 633 printf("Failed empty msg verdict prog detach\n"); 634 goto out_sockmap; 635 } 636 637 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE); 638 if (!err) { 639 printf("Detach invalid prog successful\n"); 640 goto out_sockmap; 641 } 642 643 /* Load SK_SKB program and Attach */ 644 err = bpf_prog_load(SOCKMAP_PARSE_PROG, 645 BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog); 646 if (err) { 647 printf("Failed to load SK_SKB parse prog\n"); 648 goto out_sockmap; 649 } 650 651 err = bpf_prog_load(SOCKMAP_TCP_MSG_PROG, 652 BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog); 653 if (err) { 654 printf("Failed to load SK_SKB msg prog\n"); 655 goto out_sockmap; 656 } 657 658 err = bpf_prog_load(SOCKMAP_VERDICT_PROG, 659 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog); 660 if (err) { 661 printf("Failed to load SK_SKB verdict prog\n"); 662 goto out_sockmap; 663 } 664 665 bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx"); 666 if (IS_ERR(bpf_map_rx)) { 667 printf("Failed to load map rx from verdict prog\n"); 668 goto out_sockmap; 669 } 670 671 map_fd_rx = bpf_map__fd(bpf_map_rx); 672 if (map_fd_rx < 0) { 673 printf("Failed to get map rx fd\n"); 674 goto out_sockmap; 675 } 676 677 bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx"); 678 if (IS_ERR(bpf_map_tx)) { 679 printf("Failed to load map tx from verdict prog\n"); 680 goto out_sockmap; 681 } 682 683 map_fd_tx = bpf_map__fd(bpf_map_tx); 684 if (map_fd_tx < 0) { 685 printf("Failed to get map tx fd\n"); 686 goto out_sockmap; 687 } 688 689 bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg"); 690 if (IS_ERR(bpf_map_msg)) { 691 printf("Failed to load map msg from msg_verdict prog\n"); 692 goto out_sockmap; 693 } 694 695 map_fd_msg = bpf_map__fd(bpf_map_msg); 696 if (map_fd_msg < 0) { 697 printf("Failed to get map msg fd\n"); 698 goto out_sockmap; 699 } 700 701 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break"); 702 if (IS_ERR(bpf_map_break)) { 703 printf("Failed to load map tx from verdict prog\n"); 704 goto out_sockmap; 705 } 706 707 map_fd_break = bpf_map__fd(bpf_map_break); 708 if (map_fd_break < 0) { 709 printf("Failed to get map tx fd\n"); 710 goto out_sockmap; 711 } 712 713 err = bpf_prog_attach(parse_prog, map_fd_break, 714 BPF_SK_SKB_STREAM_PARSER, 0); 715 if (!err) { 716 printf("Allowed attaching SK_SKB program to invalid map\n"); 717 goto out_sockmap; 718 } 719 720 err = bpf_prog_attach(parse_prog, map_fd_rx, 721 BPF_SK_SKB_STREAM_PARSER, 0); 722 if (err) { 723 printf("Failed stream parser bpf prog attach\n"); 724 goto out_sockmap; 725 } 726 727 err = bpf_prog_attach(verdict_prog, map_fd_rx, 728 BPF_SK_SKB_STREAM_VERDICT, 0); 729 if (err) { 730 printf("Failed stream verdict bpf prog attach\n"); 731 goto out_sockmap; 732 } 733 734 err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0); 735 if (err) { 736 printf("Failed msg verdict bpf prog attach\n"); 737 goto out_sockmap; 738 } 739 740 err = bpf_prog_attach(verdict_prog, map_fd_rx, 741 __MAX_BPF_ATTACH_TYPE, 0); 742 if (!err) { 743 printf("Attached unknown bpf prog\n"); 744 goto out_sockmap; 745 } 746 747 /* Test map update elem afterwards fd lives in fd and map_fd */ 748 for (i = 2; i < 6; i++) { 749 err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY); 750 if (err) { 751 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n", 752 err, i, sfd[i]); 753 goto out_sockmap; 754 } 755 err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY); 756 if (err) { 757 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n", 758 err, i, sfd[i]); 759 goto out_sockmap; 760 } 761 } 762 763 /* Test map delete elem and remove send/recv sockets */ 764 for (i = 2; i < 4; i++) { 765 err = bpf_map_delete_elem(map_fd_rx, &i); 766 if (err) { 767 printf("Failed delete sockmap rx %i '%i:%i'\n", 768 err, i, sfd[i]); 769 goto out_sockmap; 770 } 771 err = bpf_map_delete_elem(map_fd_tx, &i); 772 if (err) { 773 printf("Failed delete sockmap tx %i '%i:%i'\n", 774 err, i, sfd[i]); 775 goto out_sockmap; 776 } 777 } 778 779 /* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */ 780 i = 0; 781 err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY); 782 if (err) { 783 printf("Failed map_fd_msg update sockmap %i\n", err); 784 goto out_sockmap; 785 } 786 787 /* Test map send/recv */ 788 for (i = 0; i < 2; i++) { 789 buf[0] = i; 790 buf[1] = 0x5; 791 sc = send(sfd[2], buf, 20, 0); 792 if (sc < 0) { 793 printf("Failed sockmap send\n"); 794 goto out_sockmap; 795 } 796 797 FD_ZERO(&w); 798 FD_SET(sfd[3], &w); 799 to.tv_sec = 1; 800 to.tv_usec = 0; 801 s = select(sfd[3] + 1, &w, NULL, NULL, &to); 802 if (s == -1) { 803 perror("Failed sockmap select()"); 804 goto out_sockmap; 805 } else if (!s) { 806 printf("Failed sockmap unexpected timeout\n"); 807 goto out_sockmap; 808 } 809 810 if (!FD_ISSET(sfd[3], &w)) { 811 printf("Failed sockmap select/recv\n"); 812 goto out_sockmap; 813 } 814 815 rc = recv(sfd[3], buf, sizeof(buf), 0); 816 if (rc < 0) { 817 printf("Failed sockmap recv\n"); 818 goto out_sockmap; 819 } 820 } 821 822 /* Negative null entry lookup from datapath should be dropped */ 823 buf[0] = 1; 824 buf[1] = 12; 825 sc = send(sfd[2], buf, 20, 0); 826 if (sc < 0) { 827 printf("Failed sockmap send\n"); 828 goto out_sockmap; 829 } 830 831 /* Push fd into same slot */ 832 i = 2; 833 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 834 if (!err) { 835 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n"); 836 goto out_sockmap; 837 } 838 839 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 840 if (err) { 841 printf("Failed sockmap update new slot BPF_ANY\n"); 842 goto out_sockmap; 843 } 844 845 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 846 if (err) { 847 printf("Failed sockmap update new slot BPF_EXIST\n"); 848 goto out_sockmap; 849 } 850 851 /* Delete the elems without programs */ 852 for (i = 2; i < 6; i++) { 853 err = bpf_map_delete_elem(fd, &i); 854 if (err) { 855 printf("Failed delete sockmap %i '%i:%i'\n", 856 err, i, sfd[i]); 857 } 858 } 859 860 /* Test having multiple maps open and set with programs on same fds */ 861 err = bpf_prog_attach(parse_prog, fd, 862 BPF_SK_SKB_STREAM_PARSER, 0); 863 if (err) { 864 printf("Failed fd bpf parse prog attach\n"); 865 goto out_sockmap; 866 } 867 err = bpf_prog_attach(verdict_prog, fd, 868 BPF_SK_SKB_STREAM_VERDICT, 0); 869 if (err) { 870 printf("Failed fd bpf verdict prog attach\n"); 871 goto out_sockmap; 872 } 873 874 for (i = 4; i < 6; i++) { 875 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 876 if (!err) { 877 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n", 878 err, i, sfd[i]); 879 goto out_sockmap; 880 } 881 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 882 if (!err) { 883 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n", 884 err, i, sfd[i]); 885 goto out_sockmap; 886 } 887 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 888 if (!err) { 889 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n", 890 err, i, sfd[i]); 891 goto out_sockmap; 892 } 893 } 894 895 /* Test tasks number of forked operations */ 896 for (i = 0; i < tasks; i++) { 897 pid[i] = fork(); 898 if (pid[i] == 0) { 899 for (i = 0; i < 6; i++) { 900 bpf_map_delete_elem(map_fd_tx, &i); 901 bpf_map_delete_elem(map_fd_rx, &i); 902 bpf_map_update_elem(map_fd_tx, &i, 903 &sfd[i], BPF_ANY); 904 bpf_map_update_elem(map_fd_rx, &i, 905 &sfd[i], BPF_ANY); 906 } 907 exit(0); 908 } else if (pid[i] == -1) { 909 printf("Couldn't spawn #%d process!\n", i); 910 exit(1); 911 } 912 } 913 914 for (i = 0; i < tasks; i++) { 915 int status; 916 917 assert(waitpid(pid[i], &status, 0) == pid[i]); 918 assert(status == 0); 919 } 920 921 err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE); 922 if (!err) { 923 printf("Detached an invalid prog type.\n"); 924 goto out_sockmap; 925 } 926 927 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER); 928 if (err) { 929 printf("Failed parser prog detach\n"); 930 goto out_sockmap; 931 } 932 933 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT); 934 if (err) { 935 printf("Failed parser prog detach\n"); 936 goto out_sockmap; 937 } 938 939 /* Test map close sockets and empty maps */ 940 for (i = 0; i < 6; i++) { 941 bpf_map_delete_elem(map_fd_tx, &i); 942 bpf_map_delete_elem(map_fd_rx, &i); 943 close(sfd[i]); 944 } 945 close(fd); 946 close(map_fd_rx); 947 bpf_object__close(obj); 948 return; 949 out: 950 for (i = 0; i < 6; i++) 951 close(sfd[i]); 952 printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno)); 953 exit(1); 954 out_sockmap: 955 for (i = 0; i < 6; i++) { 956 if (map_fd_tx) 957 bpf_map_delete_elem(map_fd_tx, &i); 958 if (map_fd_rx) 959 bpf_map_delete_elem(map_fd_rx, &i); 960 close(sfd[i]); 961 } 962 close(fd); 963 exit(1); 964 } 965 966 #define MAP_SIZE (32 * 1024) 967 968 static void test_map_large(void) 969 { 970 struct bigkey { 971 int a; 972 char b[116]; 973 long long c; 974 } key; 975 int fd, i, value; 976 977 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 978 MAP_SIZE, map_flags); 979 if (fd < 0) { 980 printf("Failed to create large map '%s'!\n", strerror(errno)); 981 exit(1); 982 } 983 984 for (i = 0; i < MAP_SIZE; i++) { 985 key = (struct bigkey) { .c = i }; 986 value = i; 987 988 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 989 } 990 991 key.c = -1; 992 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 993 errno == E2BIG); 994 995 /* Iterate through all elements. */ 996 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 997 key.c = -1; 998 for (i = 0; i < MAP_SIZE; i++) 999 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 1000 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 1001 1002 key.c = 0; 1003 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 1004 key.a = 1; 1005 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 1006 1007 close(fd); 1008 } 1009 1010 #define run_parallel(N, FN, DATA) \ 1011 printf("Fork %d tasks to '" #FN "'\n", N); \ 1012 __run_parallel(N, FN, DATA) 1013 1014 static void __run_parallel(int tasks, void (*fn)(int task, void *data), 1015 void *data) 1016 { 1017 pid_t pid[tasks]; 1018 int i; 1019 1020 for (i = 0; i < tasks; i++) { 1021 pid[i] = fork(); 1022 if (pid[i] == 0) { 1023 fn(i, data); 1024 exit(0); 1025 } else if (pid[i] == -1) { 1026 printf("Couldn't spawn #%d process!\n", i); 1027 exit(1); 1028 } 1029 } 1030 1031 for (i = 0; i < tasks; i++) { 1032 int status; 1033 1034 assert(waitpid(pid[i], &status, 0) == pid[i]); 1035 assert(status == 0); 1036 } 1037 } 1038 1039 static void test_map_stress(void) 1040 { 1041 run_parallel(100, test_hashmap, NULL); 1042 run_parallel(100, test_hashmap_percpu, NULL); 1043 run_parallel(100, test_hashmap_sizes, NULL); 1044 run_parallel(100, test_hashmap_walk, NULL); 1045 1046 run_parallel(100, test_arraymap, NULL); 1047 run_parallel(100, test_arraymap_percpu, NULL); 1048 } 1049 1050 #define TASKS 1024 1051 1052 #define DO_UPDATE 1 1053 #define DO_DELETE 0 1054 1055 static void test_update_delete(int fn, void *data) 1056 { 1057 int do_update = ((int *)data)[1]; 1058 int fd = ((int *)data)[0]; 1059 int i, key, value; 1060 1061 for (i = fn; i < MAP_SIZE; i += TASKS) { 1062 key = value = i; 1063 1064 if (do_update) { 1065 assert(bpf_map_update_elem(fd, &key, &value, 1066 BPF_NOEXIST) == 0); 1067 assert(bpf_map_update_elem(fd, &key, &value, 1068 BPF_EXIST) == 0); 1069 } else { 1070 assert(bpf_map_delete_elem(fd, &key) == 0); 1071 } 1072 } 1073 } 1074 1075 static void test_map_parallel(void) 1076 { 1077 int i, fd, key = 0, value = 0; 1078 int data[2]; 1079 1080 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1081 MAP_SIZE, map_flags); 1082 if (fd < 0) { 1083 printf("Failed to create map for parallel test '%s'!\n", 1084 strerror(errno)); 1085 exit(1); 1086 } 1087 1088 /* Use the same fd in children to add elements to this map: 1089 * child_0 adds key=0, key=1024, key=2048, ... 1090 * child_1 adds key=1, key=1025, key=2049, ... 1091 * child_1023 adds key=1023, ... 1092 */ 1093 data[0] = fd; 1094 data[1] = DO_UPDATE; 1095 run_parallel(TASKS, test_update_delete, data); 1096 1097 /* Check that key=0 is already there. */ 1098 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 1099 errno == EEXIST); 1100 1101 /* Check that all elements were inserted. */ 1102 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 1103 key = -1; 1104 for (i = 0; i < MAP_SIZE; i++) 1105 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 1106 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 1107 1108 /* Another check for all elements */ 1109 for (i = 0; i < MAP_SIZE; i++) { 1110 key = MAP_SIZE - i - 1; 1111 1112 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && 1113 value == key); 1114 } 1115 1116 /* Now let's delete all elemenets in parallel. */ 1117 data[1] = DO_DELETE; 1118 run_parallel(TASKS, test_update_delete, data); 1119 1120 /* Nothing should be left. */ 1121 key = -1; 1122 assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT); 1123 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 1124 } 1125 1126 static void test_map_rdonly(void) 1127 { 1128 int fd, key = 0, value = 0; 1129 1130 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1131 MAP_SIZE, map_flags | BPF_F_RDONLY); 1132 if (fd < 0) { 1133 printf("Failed to create map for read only test '%s'!\n", 1134 strerror(errno)); 1135 exit(1); 1136 } 1137 1138 key = 1; 1139 value = 1234; 1140 /* Insert key=1 element. */ 1141 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 && 1142 errno == EPERM); 1143 1144 /* Check that key=2 is not found. */ 1145 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 1146 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT); 1147 } 1148 1149 static void test_map_wronly(void) 1150 { 1151 int fd, key = 0, value = 0; 1152 1153 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1154 MAP_SIZE, map_flags | BPF_F_WRONLY); 1155 if (fd < 0) { 1156 printf("Failed to create map for read only test '%s'!\n", 1157 strerror(errno)); 1158 exit(1); 1159 } 1160 1161 key = 1; 1162 value = 1234; 1163 /* Insert key=1 element. */ 1164 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 1165 1166 /* Check that key=2 is not found. */ 1167 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM); 1168 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM); 1169 } 1170 1171 static void prepare_reuseport_grp(int type, int map_fd, 1172 __s64 *fds64, __u64 *sk_cookies, 1173 unsigned int n) 1174 { 1175 socklen_t optlen, addrlen; 1176 struct sockaddr_in6 s6; 1177 const __u32 index0 = 0; 1178 const int optval = 1; 1179 unsigned int i; 1180 u64 sk_cookie; 1181 __s64 fd64; 1182 int err; 1183 1184 s6.sin6_family = AF_INET6; 1185 s6.sin6_addr = in6addr_any; 1186 s6.sin6_port = 0; 1187 addrlen = sizeof(s6); 1188 optlen = sizeof(sk_cookie); 1189 1190 for (i = 0; i < n; i++) { 1191 fd64 = socket(AF_INET6, type, 0); 1192 CHECK(fd64 == -1, "socket()", 1193 "sock_type:%d fd64:%lld errno:%d\n", 1194 type, fd64, errno); 1195 1196 err = setsockopt(fd64, SOL_SOCKET, SO_REUSEPORT, 1197 &optval, sizeof(optval)); 1198 CHECK(err == -1, "setsockopt(SO_REUSEPORT)", 1199 "err:%d errno:%d\n", err, errno); 1200 1201 /* reuseport_array does not allow unbound sk */ 1202 err = bpf_map_update_elem(map_fd, &index0, &fd64, 1203 BPF_ANY); 1204 CHECK(err != -1 || errno != EINVAL, 1205 "reuseport array update unbound sk", 1206 "sock_type:%d err:%d errno:%d\n", 1207 type, err, errno); 1208 1209 err = bind(fd64, (struct sockaddr *)&s6, sizeof(s6)); 1210 CHECK(err == -1, "bind()", 1211 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1212 1213 if (i == 0) { 1214 err = getsockname(fd64, (struct sockaddr *)&s6, 1215 &addrlen); 1216 CHECK(err == -1, "getsockname()", 1217 "sock_type:%d err:%d errno:%d\n", 1218 type, err, errno); 1219 } 1220 1221 err = getsockopt(fd64, SOL_SOCKET, SO_COOKIE, &sk_cookie, 1222 &optlen); 1223 CHECK(err == -1, "getsockopt(SO_COOKIE)", 1224 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1225 1226 if (type == SOCK_STREAM) { 1227 /* 1228 * reuseport_array does not allow 1229 * non-listening tcp sk. 1230 */ 1231 err = bpf_map_update_elem(map_fd, &index0, &fd64, 1232 BPF_ANY); 1233 CHECK(err != -1 || errno != EINVAL, 1234 "reuseport array update non-listening sk", 1235 "sock_type:%d err:%d errno:%d\n", 1236 type, err, errno); 1237 err = listen(fd64, 0); 1238 CHECK(err == -1, "listen()", 1239 "sock_type:%d, err:%d errno:%d\n", 1240 type, err, errno); 1241 } 1242 1243 fds64[i] = fd64; 1244 sk_cookies[i] = sk_cookie; 1245 } 1246 } 1247 1248 static void test_reuseport_array(void) 1249 { 1250 #define REUSEPORT_FD_IDX(err, last) ({ (err) ? last : !last; }) 1251 1252 const __u32 array_size = 4, index0 = 0, index3 = 3; 1253 int types[2] = { SOCK_STREAM, SOCK_DGRAM }, type; 1254 __u64 grpa_cookies[2], sk_cookie, map_cookie; 1255 __s64 grpa_fds64[2] = { -1, -1 }, fd64 = -1; 1256 const __u32 bad_index = array_size; 1257 int map_fd, err, t, f; 1258 __u32 fds_idx = 0; 1259 int fd; 1260 1261 map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, 1262 sizeof(__u32), sizeof(__u64), array_size, 0); 1263 CHECK(map_fd == -1, "reuseport array create", 1264 "map_fd:%d, errno:%d\n", map_fd, errno); 1265 1266 /* Test lookup/update/delete with invalid index */ 1267 err = bpf_map_delete_elem(map_fd, &bad_index); 1268 CHECK(err != -1 || errno != E2BIG, "reuseport array del >=max_entries", 1269 "err:%d errno:%d\n", err, errno); 1270 1271 err = bpf_map_update_elem(map_fd, &bad_index, &fd64, BPF_ANY); 1272 CHECK(err != -1 || errno != E2BIG, 1273 "reuseport array update >=max_entries", 1274 "err:%d errno:%d\n", err, errno); 1275 1276 err = bpf_map_lookup_elem(map_fd, &bad_index, &map_cookie); 1277 CHECK(err != -1 || errno != ENOENT, 1278 "reuseport array update >=max_entries", 1279 "err:%d errno:%d\n", err, errno); 1280 1281 /* Test lookup/delete non existence elem */ 1282 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1283 CHECK(err != -1 || errno != ENOENT, 1284 "reuseport array lookup not-exist elem", 1285 "err:%d errno:%d\n", err, errno); 1286 err = bpf_map_delete_elem(map_fd, &index3); 1287 CHECK(err != -1 || errno != ENOENT, 1288 "reuseport array del not-exist elem", 1289 "err:%d errno:%d\n", err, errno); 1290 1291 for (t = 0; t < ARRAY_SIZE(types); t++) { 1292 type = types[t]; 1293 1294 prepare_reuseport_grp(type, map_fd, grpa_fds64, 1295 grpa_cookies, ARRAY_SIZE(grpa_fds64)); 1296 1297 /* Test BPF_* update flags */ 1298 /* BPF_EXIST failure case */ 1299 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1300 BPF_EXIST); 1301 CHECK(err != -1 || errno != ENOENT, 1302 "reuseport array update empty elem BPF_EXIST", 1303 "sock_type:%d err:%d errno:%d\n", 1304 type, err, errno); 1305 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1306 1307 /* BPF_NOEXIST success case */ 1308 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1309 BPF_NOEXIST); 1310 CHECK(err == -1, 1311 "reuseport array update empty elem BPF_NOEXIST", 1312 "sock_type:%d err:%d errno:%d\n", 1313 type, err, errno); 1314 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1315 1316 /* BPF_EXIST success case. */ 1317 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1318 BPF_EXIST); 1319 CHECK(err == -1, 1320 "reuseport array update same elem BPF_EXIST", 1321 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1322 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1323 1324 /* BPF_NOEXIST failure case */ 1325 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1326 BPF_NOEXIST); 1327 CHECK(err != -1 || errno != EEXIST, 1328 "reuseport array update non-empty elem BPF_NOEXIST", 1329 "sock_type:%d err:%d errno:%d\n", 1330 type, err, errno); 1331 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1332 1333 /* BPF_ANY case (always succeed) */ 1334 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1335 BPF_ANY); 1336 CHECK(err == -1, 1337 "reuseport array update same sk with BPF_ANY", 1338 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1339 1340 fd64 = grpa_fds64[fds_idx]; 1341 sk_cookie = grpa_cookies[fds_idx]; 1342 1343 /* The same sk cannot be added to reuseport_array twice */ 1344 err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_ANY); 1345 CHECK(err != -1 || errno != EBUSY, 1346 "reuseport array update same sk with same index", 1347 "sock_type:%d err:%d errno:%d\n", 1348 type, err, errno); 1349 1350 err = bpf_map_update_elem(map_fd, &index0, &fd64, BPF_ANY); 1351 CHECK(err != -1 || errno != EBUSY, 1352 "reuseport array update same sk with different index", 1353 "sock_type:%d err:%d errno:%d\n", 1354 type, err, errno); 1355 1356 /* Test delete elem */ 1357 err = bpf_map_delete_elem(map_fd, &index3); 1358 CHECK(err == -1, "reuseport array delete sk", 1359 "sock_type:%d err:%d errno:%d\n", 1360 type, err, errno); 1361 1362 /* Add it back with BPF_NOEXIST */ 1363 err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST); 1364 CHECK(err == -1, 1365 "reuseport array re-add with BPF_NOEXIST after del", 1366 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1367 1368 /* Test cookie */ 1369 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1370 CHECK(err == -1 || sk_cookie != map_cookie, 1371 "reuseport array lookup re-added sk", 1372 "sock_type:%d err:%d errno:%d sk_cookie:0x%llx map_cookie:0x%llxn", 1373 type, err, errno, sk_cookie, map_cookie); 1374 1375 /* Test elem removed by close() */ 1376 for (f = 0; f < ARRAY_SIZE(grpa_fds64); f++) 1377 close(grpa_fds64[f]); 1378 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1379 CHECK(err != -1 || errno != ENOENT, 1380 "reuseport array lookup after close()", 1381 "sock_type:%d err:%d errno:%d\n", 1382 type, err, errno); 1383 } 1384 1385 /* Test SOCK_RAW */ 1386 fd64 = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP); 1387 CHECK(fd64 == -1, "socket(SOCK_RAW)", "err:%d errno:%d\n", 1388 err, errno); 1389 err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST); 1390 CHECK(err != -1 || errno != ENOTSUPP, "reuseport array update SOCK_RAW", 1391 "err:%d errno:%d\n", err, errno); 1392 close(fd64); 1393 1394 /* Close the 64 bit value map */ 1395 close(map_fd); 1396 1397 /* Test 32 bit fd */ 1398 map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, 1399 sizeof(__u32), sizeof(__u32), array_size, 0); 1400 CHECK(map_fd == -1, "reuseport array create", 1401 "map_fd:%d, errno:%d\n", map_fd, errno); 1402 prepare_reuseport_grp(SOCK_STREAM, map_fd, &fd64, &sk_cookie, 1); 1403 fd = fd64; 1404 err = bpf_map_update_elem(map_fd, &index3, &fd, BPF_NOEXIST); 1405 CHECK(err == -1, "reuseport array update 32 bit fd", 1406 "err:%d errno:%d\n", err, errno); 1407 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1408 CHECK(err != -1 || errno != ENOSPC, 1409 "reuseport array lookup 32 bit fd", 1410 "err:%d errno:%d\n", err, errno); 1411 close(fd); 1412 close(map_fd); 1413 } 1414 1415 static void run_all_tests(void) 1416 { 1417 test_hashmap(0, NULL); 1418 test_hashmap_percpu(0, NULL); 1419 test_hashmap_walk(0, NULL); 1420 1421 test_arraymap(0, NULL); 1422 test_arraymap_percpu(0, NULL); 1423 1424 test_arraymap_percpu_many_keys(); 1425 1426 test_devmap(0, NULL); 1427 test_sockmap(0, NULL); 1428 1429 test_map_large(); 1430 test_map_parallel(); 1431 test_map_stress(); 1432 1433 test_map_rdonly(); 1434 test_map_wronly(); 1435 1436 test_reuseport_array(); 1437 } 1438 1439 int main(void) 1440 { 1441 map_flags = 0; 1442 run_all_tests(); 1443 1444 map_flags = BPF_F_NO_PREALLOC; 1445 run_all_tests(); 1446 1447 printf("test_maps: OK\n"); 1448 return 0; 1449 } 1450