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 (err) { 584 printf("Failed noprog update sockmap '%i:%i'\n", 585 i, sfd[i]); 586 goto out_sockmap; 587 } 588 } 589 590 /* Test attaching/detaching bad fds */ 591 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0); 592 if (!err) { 593 printf("Failed invalid parser prog attach\n"); 594 goto out_sockmap; 595 } 596 597 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0); 598 if (!err) { 599 printf("Failed invalid verdict prog attach\n"); 600 goto out_sockmap; 601 } 602 603 err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0); 604 if (!err) { 605 printf("Failed invalid msg verdict prog attach\n"); 606 goto out_sockmap; 607 } 608 609 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0); 610 if (!err) { 611 printf("Failed unknown prog attach\n"); 612 goto out_sockmap; 613 } 614 615 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER); 616 if (err) { 617 printf("Failed empty parser prog detach\n"); 618 goto out_sockmap; 619 } 620 621 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT); 622 if (err) { 623 printf("Failed empty verdict prog detach\n"); 624 goto out_sockmap; 625 } 626 627 err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT); 628 if (err) { 629 printf("Failed empty msg verdict prog detach\n"); 630 goto out_sockmap; 631 } 632 633 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE); 634 if (!err) { 635 printf("Detach invalid prog successful\n"); 636 goto out_sockmap; 637 } 638 639 /* Load SK_SKB program and Attach */ 640 err = bpf_prog_load(SOCKMAP_PARSE_PROG, 641 BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog); 642 if (err) { 643 printf("Failed to load SK_SKB parse prog\n"); 644 goto out_sockmap; 645 } 646 647 err = bpf_prog_load(SOCKMAP_TCP_MSG_PROG, 648 BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog); 649 if (err) { 650 printf("Failed to load SK_SKB msg prog\n"); 651 goto out_sockmap; 652 } 653 654 err = bpf_prog_load(SOCKMAP_VERDICT_PROG, 655 BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog); 656 if (err) { 657 printf("Failed to load SK_SKB verdict prog\n"); 658 goto out_sockmap; 659 } 660 661 bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx"); 662 if (IS_ERR(bpf_map_rx)) { 663 printf("Failed to load map rx from verdict prog\n"); 664 goto out_sockmap; 665 } 666 667 map_fd_rx = bpf_map__fd(bpf_map_rx); 668 if (map_fd_rx < 0) { 669 printf("Failed to get map rx fd\n"); 670 goto out_sockmap; 671 } 672 673 bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx"); 674 if (IS_ERR(bpf_map_tx)) { 675 printf("Failed to load map tx from verdict prog\n"); 676 goto out_sockmap; 677 } 678 679 map_fd_tx = bpf_map__fd(bpf_map_tx); 680 if (map_fd_tx < 0) { 681 printf("Failed to get map tx fd\n"); 682 goto out_sockmap; 683 } 684 685 bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg"); 686 if (IS_ERR(bpf_map_msg)) { 687 printf("Failed to load map msg from msg_verdict prog\n"); 688 goto out_sockmap; 689 } 690 691 map_fd_msg = bpf_map__fd(bpf_map_msg); 692 if (map_fd_msg < 0) { 693 printf("Failed to get map msg fd\n"); 694 goto out_sockmap; 695 } 696 697 bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break"); 698 if (IS_ERR(bpf_map_break)) { 699 printf("Failed to load map tx from verdict prog\n"); 700 goto out_sockmap; 701 } 702 703 map_fd_break = bpf_map__fd(bpf_map_break); 704 if (map_fd_break < 0) { 705 printf("Failed to get map tx fd\n"); 706 goto out_sockmap; 707 } 708 709 err = bpf_prog_attach(parse_prog, map_fd_break, 710 BPF_SK_SKB_STREAM_PARSER, 0); 711 if (!err) { 712 printf("Allowed attaching SK_SKB program to invalid map\n"); 713 goto out_sockmap; 714 } 715 716 err = bpf_prog_attach(parse_prog, map_fd_rx, 717 BPF_SK_SKB_STREAM_PARSER, 0); 718 if (err) { 719 printf("Failed stream parser bpf prog attach\n"); 720 goto out_sockmap; 721 } 722 723 err = bpf_prog_attach(verdict_prog, map_fd_rx, 724 BPF_SK_SKB_STREAM_VERDICT, 0); 725 if (err) { 726 printf("Failed stream verdict bpf prog attach\n"); 727 goto out_sockmap; 728 } 729 730 err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0); 731 if (err) { 732 printf("Failed msg verdict bpf prog attach\n"); 733 goto out_sockmap; 734 } 735 736 err = bpf_prog_attach(verdict_prog, map_fd_rx, 737 __MAX_BPF_ATTACH_TYPE, 0); 738 if (!err) { 739 printf("Attached unknown bpf prog\n"); 740 goto out_sockmap; 741 } 742 743 /* Test map update elem afterwards fd lives in fd and map_fd */ 744 for (i = 0; i < 6; i++) { 745 err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY); 746 if (err) { 747 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n", 748 err, i, sfd[i]); 749 goto out_sockmap; 750 } 751 err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY); 752 if (err) { 753 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n", 754 err, i, sfd[i]); 755 goto out_sockmap; 756 } 757 } 758 759 /* Test map delete elem and remove send/recv sockets */ 760 for (i = 2; i < 4; i++) { 761 err = bpf_map_delete_elem(map_fd_rx, &i); 762 if (err) { 763 printf("Failed delete sockmap rx %i '%i:%i'\n", 764 err, i, sfd[i]); 765 goto out_sockmap; 766 } 767 err = bpf_map_delete_elem(map_fd_tx, &i); 768 if (err) { 769 printf("Failed delete sockmap tx %i '%i:%i'\n", 770 err, i, sfd[i]); 771 goto out_sockmap; 772 } 773 } 774 775 /* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */ 776 i = 0; 777 err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY); 778 if (err) { 779 printf("Failed map_fd_msg update sockmap %i\n", err); 780 goto out_sockmap; 781 } 782 783 /* Test map send/recv */ 784 for (i = 0; i < 2; i++) { 785 buf[0] = i; 786 buf[1] = 0x5; 787 sc = send(sfd[2], buf, 20, 0); 788 if (sc < 0) { 789 printf("Failed sockmap send\n"); 790 goto out_sockmap; 791 } 792 793 FD_ZERO(&w); 794 FD_SET(sfd[3], &w); 795 to.tv_sec = 1; 796 to.tv_usec = 0; 797 s = select(sfd[3] + 1, &w, NULL, NULL, &to); 798 if (s == -1) { 799 perror("Failed sockmap select()"); 800 goto out_sockmap; 801 } else if (!s) { 802 printf("Failed sockmap unexpected timeout\n"); 803 goto out_sockmap; 804 } 805 806 if (!FD_ISSET(sfd[3], &w)) { 807 printf("Failed sockmap select/recv\n"); 808 goto out_sockmap; 809 } 810 811 rc = recv(sfd[3], buf, sizeof(buf), 0); 812 if (rc < 0) { 813 printf("Failed sockmap recv\n"); 814 goto out_sockmap; 815 } 816 } 817 818 /* Negative null entry lookup from datapath should be dropped */ 819 buf[0] = 1; 820 buf[1] = 12; 821 sc = send(sfd[2], buf, 20, 0); 822 if (sc < 0) { 823 printf("Failed sockmap send\n"); 824 goto out_sockmap; 825 } 826 827 /* Push fd into same slot */ 828 i = 2; 829 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 830 if (!err) { 831 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n"); 832 goto out_sockmap; 833 } 834 835 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 836 if (err) { 837 printf("Failed sockmap update new slot BPF_ANY\n"); 838 goto out_sockmap; 839 } 840 841 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 842 if (err) { 843 printf("Failed sockmap update new slot BPF_EXIST\n"); 844 goto out_sockmap; 845 } 846 847 /* Delete the elems without programs */ 848 for (i = 0; i < 6; i++) { 849 err = bpf_map_delete_elem(fd, &i); 850 if (err) { 851 printf("Failed delete sockmap %i '%i:%i'\n", 852 err, i, sfd[i]); 853 } 854 } 855 856 /* Test having multiple maps open and set with programs on same fds */ 857 err = bpf_prog_attach(parse_prog, fd, 858 BPF_SK_SKB_STREAM_PARSER, 0); 859 if (err) { 860 printf("Failed fd bpf parse prog attach\n"); 861 goto out_sockmap; 862 } 863 err = bpf_prog_attach(verdict_prog, fd, 864 BPF_SK_SKB_STREAM_VERDICT, 0); 865 if (err) { 866 printf("Failed fd bpf verdict prog attach\n"); 867 goto out_sockmap; 868 } 869 870 for (i = 4; i < 6; i++) { 871 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 872 if (!err) { 873 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n", 874 err, i, sfd[i]); 875 goto out_sockmap; 876 } 877 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 878 if (!err) { 879 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n", 880 err, i, sfd[i]); 881 goto out_sockmap; 882 } 883 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 884 if (!err) { 885 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n", 886 err, i, sfd[i]); 887 goto out_sockmap; 888 } 889 } 890 891 /* Test tasks number of forked operations */ 892 for (i = 0; i < tasks; i++) { 893 pid[i] = fork(); 894 if (pid[i] == 0) { 895 for (i = 0; i < 6; i++) { 896 bpf_map_delete_elem(map_fd_tx, &i); 897 bpf_map_delete_elem(map_fd_rx, &i); 898 bpf_map_update_elem(map_fd_tx, &i, 899 &sfd[i], BPF_ANY); 900 bpf_map_update_elem(map_fd_rx, &i, 901 &sfd[i], BPF_ANY); 902 } 903 exit(0); 904 } else if (pid[i] == -1) { 905 printf("Couldn't spawn #%d process!\n", i); 906 exit(1); 907 } 908 } 909 910 for (i = 0; i < tasks; i++) { 911 int status; 912 913 assert(waitpid(pid[i], &status, 0) == pid[i]); 914 assert(status == 0); 915 } 916 917 err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE); 918 if (!err) { 919 printf("Detached an invalid prog type.\n"); 920 goto out_sockmap; 921 } 922 923 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER); 924 if (err) { 925 printf("Failed parser prog detach\n"); 926 goto out_sockmap; 927 } 928 929 err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT); 930 if (err) { 931 printf("Failed parser prog detach\n"); 932 goto out_sockmap; 933 } 934 935 /* Test map close sockets and empty maps */ 936 for (i = 0; i < 6; i++) { 937 bpf_map_delete_elem(map_fd_tx, &i); 938 bpf_map_delete_elem(map_fd_rx, &i); 939 close(sfd[i]); 940 } 941 close(fd); 942 close(map_fd_rx); 943 bpf_object__close(obj); 944 return; 945 out: 946 for (i = 0; i < 6; i++) 947 close(sfd[i]); 948 printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno)); 949 exit(1); 950 out_sockmap: 951 for (i = 0; i < 6; i++) { 952 if (map_fd_tx) 953 bpf_map_delete_elem(map_fd_tx, &i); 954 if (map_fd_rx) 955 bpf_map_delete_elem(map_fd_rx, &i); 956 close(sfd[i]); 957 } 958 close(fd); 959 exit(1); 960 } 961 962 #define MAP_SIZE (32 * 1024) 963 964 static void test_map_large(void) 965 { 966 struct bigkey { 967 int a; 968 char b[116]; 969 long long c; 970 } key; 971 int fd, i, value; 972 973 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 974 MAP_SIZE, map_flags); 975 if (fd < 0) { 976 printf("Failed to create large map '%s'!\n", strerror(errno)); 977 exit(1); 978 } 979 980 for (i = 0; i < MAP_SIZE; i++) { 981 key = (struct bigkey) { .c = i }; 982 value = i; 983 984 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 985 } 986 987 key.c = -1; 988 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 989 errno == E2BIG); 990 991 /* Iterate through all elements. */ 992 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 993 key.c = -1; 994 for (i = 0; i < MAP_SIZE; i++) 995 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 996 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 997 998 key.c = 0; 999 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 1000 key.a = 1; 1001 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 1002 1003 close(fd); 1004 } 1005 1006 #define run_parallel(N, FN, DATA) \ 1007 printf("Fork %d tasks to '" #FN "'\n", N); \ 1008 __run_parallel(N, FN, DATA) 1009 1010 static void __run_parallel(int tasks, void (*fn)(int task, void *data), 1011 void *data) 1012 { 1013 pid_t pid[tasks]; 1014 int i; 1015 1016 for (i = 0; i < tasks; i++) { 1017 pid[i] = fork(); 1018 if (pid[i] == 0) { 1019 fn(i, data); 1020 exit(0); 1021 } else if (pid[i] == -1) { 1022 printf("Couldn't spawn #%d process!\n", i); 1023 exit(1); 1024 } 1025 } 1026 1027 for (i = 0; i < tasks; i++) { 1028 int status; 1029 1030 assert(waitpid(pid[i], &status, 0) == pid[i]); 1031 assert(status == 0); 1032 } 1033 } 1034 1035 static void test_map_stress(void) 1036 { 1037 run_parallel(100, test_hashmap, NULL); 1038 run_parallel(100, test_hashmap_percpu, NULL); 1039 run_parallel(100, test_hashmap_sizes, NULL); 1040 run_parallel(100, test_hashmap_walk, NULL); 1041 1042 run_parallel(100, test_arraymap, NULL); 1043 run_parallel(100, test_arraymap_percpu, NULL); 1044 } 1045 1046 #define TASKS 1024 1047 1048 #define DO_UPDATE 1 1049 #define DO_DELETE 0 1050 1051 static void test_update_delete(int fn, void *data) 1052 { 1053 int do_update = ((int *)data)[1]; 1054 int fd = ((int *)data)[0]; 1055 int i, key, value; 1056 1057 for (i = fn; i < MAP_SIZE; i += TASKS) { 1058 key = value = i; 1059 1060 if (do_update) { 1061 assert(bpf_map_update_elem(fd, &key, &value, 1062 BPF_NOEXIST) == 0); 1063 assert(bpf_map_update_elem(fd, &key, &value, 1064 BPF_EXIST) == 0); 1065 } else { 1066 assert(bpf_map_delete_elem(fd, &key) == 0); 1067 } 1068 } 1069 } 1070 1071 static void test_map_parallel(void) 1072 { 1073 int i, fd, key = 0, value = 0; 1074 int data[2]; 1075 1076 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1077 MAP_SIZE, map_flags); 1078 if (fd < 0) { 1079 printf("Failed to create map for parallel test '%s'!\n", 1080 strerror(errno)); 1081 exit(1); 1082 } 1083 1084 /* Use the same fd in children to add elements to this map: 1085 * child_0 adds key=0, key=1024, key=2048, ... 1086 * child_1 adds key=1, key=1025, key=2049, ... 1087 * child_1023 adds key=1023, ... 1088 */ 1089 data[0] = fd; 1090 data[1] = DO_UPDATE; 1091 run_parallel(TASKS, test_update_delete, data); 1092 1093 /* Check that key=0 is already there. */ 1094 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 1095 errno == EEXIST); 1096 1097 /* Check that all elements were inserted. */ 1098 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 1099 key = -1; 1100 for (i = 0; i < MAP_SIZE; i++) 1101 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 1102 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 1103 1104 /* Another check for all elements */ 1105 for (i = 0; i < MAP_SIZE; i++) { 1106 key = MAP_SIZE - i - 1; 1107 1108 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && 1109 value == key); 1110 } 1111 1112 /* Now let's delete all elemenets in parallel. */ 1113 data[1] = DO_DELETE; 1114 run_parallel(TASKS, test_update_delete, data); 1115 1116 /* Nothing should be left. */ 1117 key = -1; 1118 assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT); 1119 assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 1120 } 1121 1122 static void test_map_rdonly(void) 1123 { 1124 int fd, key = 0, value = 0; 1125 1126 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1127 MAP_SIZE, map_flags | BPF_F_RDONLY); 1128 if (fd < 0) { 1129 printf("Failed to create map for read only test '%s'!\n", 1130 strerror(errno)); 1131 exit(1); 1132 } 1133 1134 key = 1; 1135 value = 1234; 1136 /* Insert key=1 element. */ 1137 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 && 1138 errno == EPERM); 1139 1140 /* Check that key=2 is not found. */ 1141 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 1142 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT); 1143 } 1144 1145 static void test_map_wronly(void) 1146 { 1147 int fd, key = 0, value = 0; 1148 1149 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 1150 MAP_SIZE, map_flags | BPF_F_WRONLY); 1151 if (fd < 0) { 1152 printf("Failed to create map for read only test '%s'!\n", 1153 strerror(errno)); 1154 exit(1); 1155 } 1156 1157 key = 1; 1158 value = 1234; 1159 /* Insert key=1 element. */ 1160 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 1161 1162 /* Check that key=2 is not found. */ 1163 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM); 1164 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM); 1165 } 1166 1167 static void prepare_reuseport_grp(int type, int map_fd, 1168 __s64 *fds64, __u64 *sk_cookies, 1169 unsigned int n) 1170 { 1171 socklen_t optlen, addrlen; 1172 struct sockaddr_in6 s6; 1173 const __u32 index0 = 0; 1174 const int optval = 1; 1175 unsigned int i; 1176 u64 sk_cookie; 1177 __s64 fd64; 1178 int err; 1179 1180 s6.sin6_family = AF_INET6; 1181 s6.sin6_addr = in6addr_any; 1182 s6.sin6_port = 0; 1183 addrlen = sizeof(s6); 1184 optlen = sizeof(sk_cookie); 1185 1186 for (i = 0; i < n; i++) { 1187 fd64 = socket(AF_INET6, type, 0); 1188 CHECK(fd64 == -1, "socket()", 1189 "sock_type:%d fd64:%lld errno:%d\n", 1190 type, fd64, errno); 1191 1192 err = setsockopt(fd64, SOL_SOCKET, SO_REUSEPORT, 1193 &optval, sizeof(optval)); 1194 CHECK(err == -1, "setsockopt(SO_REUSEPORT)", 1195 "err:%d errno:%d\n", err, errno); 1196 1197 /* reuseport_array does not allow unbound sk */ 1198 err = bpf_map_update_elem(map_fd, &index0, &fd64, 1199 BPF_ANY); 1200 CHECK(err != -1 || errno != EINVAL, 1201 "reuseport array update unbound sk", 1202 "sock_type:%d err:%d errno:%d\n", 1203 type, err, errno); 1204 1205 err = bind(fd64, (struct sockaddr *)&s6, sizeof(s6)); 1206 CHECK(err == -1, "bind()", 1207 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1208 1209 if (i == 0) { 1210 err = getsockname(fd64, (struct sockaddr *)&s6, 1211 &addrlen); 1212 CHECK(err == -1, "getsockname()", 1213 "sock_type:%d err:%d errno:%d\n", 1214 type, err, errno); 1215 } 1216 1217 err = getsockopt(fd64, SOL_SOCKET, SO_COOKIE, &sk_cookie, 1218 &optlen); 1219 CHECK(err == -1, "getsockopt(SO_COOKIE)", 1220 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1221 1222 if (type == SOCK_STREAM) { 1223 /* 1224 * reuseport_array does not allow 1225 * non-listening tcp sk. 1226 */ 1227 err = bpf_map_update_elem(map_fd, &index0, &fd64, 1228 BPF_ANY); 1229 CHECK(err != -1 || errno != EINVAL, 1230 "reuseport array update non-listening sk", 1231 "sock_type:%d err:%d errno:%d\n", 1232 type, err, errno); 1233 err = listen(fd64, 0); 1234 CHECK(err == -1, "listen()", 1235 "sock_type:%d, err:%d errno:%d\n", 1236 type, err, errno); 1237 } 1238 1239 fds64[i] = fd64; 1240 sk_cookies[i] = sk_cookie; 1241 } 1242 } 1243 1244 static void test_reuseport_array(void) 1245 { 1246 #define REUSEPORT_FD_IDX(err, last) ({ (err) ? last : !last; }) 1247 1248 const __u32 array_size = 4, index0 = 0, index3 = 3; 1249 int types[2] = { SOCK_STREAM, SOCK_DGRAM }, type; 1250 __u64 grpa_cookies[2], sk_cookie, map_cookie; 1251 __s64 grpa_fds64[2] = { -1, -1 }, fd64 = -1; 1252 const __u32 bad_index = array_size; 1253 int map_fd, err, t, f; 1254 __u32 fds_idx = 0; 1255 int fd; 1256 1257 map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, 1258 sizeof(__u32), sizeof(__u64), array_size, 0); 1259 CHECK(map_fd == -1, "reuseport array create", 1260 "map_fd:%d, errno:%d\n", map_fd, errno); 1261 1262 /* Test lookup/update/delete with invalid index */ 1263 err = bpf_map_delete_elem(map_fd, &bad_index); 1264 CHECK(err != -1 || errno != E2BIG, "reuseport array del >=max_entries", 1265 "err:%d errno:%d\n", err, errno); 1266 1267 err = bpf_map_update_elem(map_fd, &bad_index, &fd64, BPF_ANY); 1268 CHECK(err != -1 || errno != E2BIG, 1269 "reuseport array update >=max_entries", 1270 "err:%d errno:%d\n", err, errno); 1271 1272 err = bpf_map_lookup_elem(map_fd, &bad_index, &map_cookie); 1273 CHECK(err != -1 || errno != ENOENT, 1274 "reuseport array update >=max_entries", 1275 "err:%d errno:%d\n", err, errno); 1276 1277 /* Test lookup/delete non existence elem */ 1278 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1279 CHECK(err != -1 || errno != ENOENT, 1280 "reuseport array lookup not-exist elem", 1281 "err:%d errno:%d\n", err, errno); 1282 err = bpf_map_delete_elem(map_fd, &index3); 1283 CHECK(err != -1 || errno != ENOENT, 1284 "reuseport array del not-exist elem", 1285 "err:%d errno:%d\n", err, errno); 1286 1287 for (t = 0; t < ARRAY_SIZE(types); t++) { 1288 type = types[t]; 1289 1290 prepare_reuseport_grp(type, map_fd, grpa_fds64, 1291 grpa_cookies, ARRAY_SIZE(grpa_fds64)); 1292 1293 /* Test BPF_* update flags */ 1294 /* BPF_EXIST failure case */ 1295 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1296 BPF_EXIST); 1297 CHECK(err != -1 || errno != ENOENT, 1298 "reuseport array update empty elem BPF_EXIST", 1299 "sock_type:%d err:%d errno:%d\n", 1300 type, err, errno); 1301 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1302 1303 /* BPF_NOEXIST success case */ 1304 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1305 BPF_NOEXIST); 1306 CHECK(err == -1, 1307 "reuseport array update empty elem BPF_NOEXIST", 1308 "sock_type:%d err:%d errno:%d\n", 1309 type, err, errno); 1310 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1311 1312 /* BPF_EXIST success case. */ 1313 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1314 BPF_EXIST); 1315 CHECK(err == -1, 1316 "reuseport array update same elem BPF_EXIST", 1317 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1318 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1319 1320 /* BPF_NOEXIST failure case */ 1321 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1322 BPF_NOEXIST); 1323 CHECK(err != -1 || errno != EEXIST, 1324 "reuseport array update non-empty elem BPF_NOEXIST", 1325 "sock_type:%d err:%d errno:%d\n", 1326 type, err, errno); 1327 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1328 1329 /* BPF_ANY case (always succeed) */ 1330 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1331 BPF_ANY); 1332 CHECK(err == -1, 1333 "reuseport array update same sk with BPF_ANY", 1334 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1335 1336 fd64 = grpa_fds64[fds_idx]; 1337 sk_cookie = grpa_cookies[fds_idx]; 1338 1339 /* The same sk cannot be added to reuseport_array twice */ 1340 err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_ANY); 1341 CHECK(err != -1 || errno != EBUSY, 1342 "reuseport array update same sk with same index", 1343 "sock_type:%d err:%d errno:%d\n", 1344 type, err, errno); 1345 1346 err = bpf_map_update_elem(map_fd, &index0, &fd64, BPF_ANY); 1347 CHECK(err != -1 || errno != EBUSY, 1348 "reuseport array update same sk with different index", 1349 "sock_type:%d err:%d errno:%d\n", 1350 type, err, errno); 1351 1352 /* Test delete elem */ 1353 err = bpf_map_delete_elem(map_fd, &index3); 1354 CHECK(err == -1, "reuseport array delete sk", 1355 "sock_type:%d err:%d errno:%d\n", 1356 type, err, errno); 1357 1358 /* Add it back with BPF_NOEXIST */ 1359 err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST); 1360 CHECK(err == -1, 1361 "reuseport array re-add with BPF_NOEXIST after del", 1362 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1363 1364 /* Test cookie */ 1365 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1366 CHECK(err == -1 || sk_cookie != map_cookie, 1367 "reuseport array lookup re-added sk", 1368 "sock_type:%d err:%d errno:%d sk_cookie:0x%llx map_cookie:0x%llxn", 1369 type, err, errno, sk_cookie, map_cookie); 1370 1371 /* Test elem removed by close() */ 1372 for (f = 0; f < ARRAY_SIZE(grpa_fds64); f++) 1373 close(grpa_fds64[f]); 1374 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1375 CHECK(err != -1 || errno != ENOENT, 1376 "reuseport array lookup after close()", 1377 "sock_type:%d err:%d errno:%d\n", 1378 type, err, errno); 1379 } 1380 1381 /* Test SOCK_RAW */ 1382 fd64 = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP); 1383 CHECK(fd64 == -1, "socket(SOCK_RAW)", "err:%d errno:%d\n", 1384 err, errno); 1385 err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST); 1386 CHECK(err != -1 || errno != ENOTSUPP, "reuseport array update SOCK_RAW", 1387 "err:%d errno:%d\n", err, errno); 1388 close(fd64); 1389 1390 /* Close the 64 bit value map */ 1391 close(map_fd); 1392 1393 /* Test 32 bit fd */ 1394 map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, 1395 sizeof(__u32), sizeof(__u32), array_size, 0); 1396 CHECK(map_fd == -1, "reuseport array create", 1397 "map_fd:%d, errno:%d\n", map_fd, errno); 1398 prepare_reuseport_grp(SOCK_STREAM, map_fd, &fd64, &sk_cookie, 1); 1399 fd = fd64; 1400 err = bpf_map_update_elem(map_fd, &index3, &fd, BPF_NOEXIST); 1401 CHECK(err == -1, "reuseport array update 32 bit fd", 1402 "err:%d errno:%d\n", err, errno); 1403 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1404 CHECK(err != -1 || errno != ENOSPC, 1405 "reuseport array lookup 32 bit fd", 1406 "err:%d errno:%d\n", err, errno); 1407 close(fd); 1408 close(map_fd); 1409 } 1410 1411 static void run_all_tests(void) 1412 { 1413 test_hashmap(0, NULL); 1414 test_hashmap_percpu(0, NULL); 1415 test_hashmap_walk(0, NULL); 1416 1417 test_arraymap(0, NULL); 1418 test_arraymap_percpu(0, NULL); 1419 1420 test_arraymap_percpu_many_keys(); 1421 1422 test_devmap(0, NULL); 1423 test_sockmap(0, NULL); 1424 1425 test_map_large(); 1426 test_map_parallel(); 1427 test_map_stress(); 1428 1429 test_map_rdonly(); 1430 test_map_wronly(); 1431 1432 test_reuseport_array(); 1433 } 1434 1435 int main(void) 1436 { 1437 map_flags = 0; 1438 run_all_tests(); 1439 1440 map_flags = BPF_F_NO_PREALLOC; 1441 run_all_tests(); 1442 1443 printf("test_maps: OK\n"); 1444 return 0; 1445 } 1446