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