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