18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Testsuite for eBPF maps 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2014 PLUMgrid, http://plumgrid.com 68c2ecf20Sopenharmony_ci * Copyright (c) 2016 Facebook 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <stdio.h> 108c2ecf20Sopenharmony_ci#include <unistd.h> 118c2ecf20Sopenharmony_ci#include <errno.h> 128c2ecf20Sopenharmony_ci#include <string.h> 138c2ecf20Sopenharmony_ci#include <assert.h> 148c2ecf20Sopenharmony_ci#include <stdlib.h> 158c2ecf20Sopenharmony_ci#include <time.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <sys/wait.h> 188c2ecf20Sopenharmony_ci#include <sys/socket.h> 198c2ecf20Sopenharmony_ci#include <netinet/in.h> 208c2ecf20Sopenharmony_ci#include <linux/bpf.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 238c2ecf20Sopenharmony_ci#include <bpf/libbpf.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include "bpf_util.h" 268c2ecf20Sopenharmony_ci#include "bpf_rlimit.h" 278c2ecf20Sopenharmony_ci#include "test_maps.h" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#ifndef ENOTSUPP 308c2ecf20Sopenharmony_ci#define ENOTSUPP 524 318c2ecf20Sopenharmony_ci#endif 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int skips; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic int map_flags; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic void test_hashmap(unsigned int task, void *data) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci long long key, next_key, first_key, value; 408c2ecf20Sopenharmony_ci int fd; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 438c2ecf20Sopenharmony_ci 2, map_flags); 448c2ecf20Sopenharmony_ci if (fd < 0) { 458c2ecf20Sopenharmony_ci printf("Failed to create hashmap '%s'!\n", strerror(errno)); 468c2ecf20Sopenharmony_ci exit(1); 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci key = 1; 508c2ecf20Sopenharmony_ci value = 1234; 518c2ecf20Sopenharmony_ci /* Insert key=1 element. */ 528c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci value = 0; 558c2ecf20Sopenharmony_ci /* BPF_NOEXIST means add new element if it doesn't exist. */ 568c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 578c2ecf20Sopenharmony_ci /* key=1 already exists. */ 588c2ecf20Sopenharmony_ci errno == EEXIST); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* -1 is an invalid flag. */ 618c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 && 628c2ecf20Sopenharmony_ci errno == EINVAL); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /* Check that key=1 can be found. */ 658c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci key = 2; 688c2ecf20Sopenharmony_ci /* Check that key=2 is not found. */ 698c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci /* BPF_EXIST means update existing element. */ 728c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 && 738c2ecf20Sopenharmony_ci /* key=2 is not there. */ 748c2ecf20Sopenharmony_ci errno == ENOENT); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* Insert key=2 element. */ 778c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* key=1 and key=2 were inserted, check that key=0 cannot be 808c2ecf20Sopenharmony_ci * inserted due to max_entries limit. 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci key = 0; 838c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 848c2ecf20Sopenharmony_ci errno == E2BIG); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* Update existing element, though the map is full. */ 878c2ecf20Sopenharmony_ci key = 1; 888c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); 898c2ecf20Sopenharmony_ci key = 2; 908c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 918c2ecf20Sopenharmony_ci key = 3; 928c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 938c2ecf20Sopenharmony_ci errno == E2BIG); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* Check that key = 0 doesn't exist. */ 968c2ecf20Sopenharmony_ci key = 0; 978c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* Iterate over two elements. */ 1008c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 && 1018c2ecf20Sopenharmony_ci (first_key == 1 || first_key == 2)); 1028c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 1038c2ecf20Sopenharmony_ci (next_key == first_key)); 1048c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 1058c2ecf20Sopenharmony_ci (next_key == 1 || next_key == 2) && 1068c2ecf20Sopenharmony_ci (next_key != first_key)); 1078c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && 1088c2ecf20Sopenharmony_ci errno == ENOENT); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* Delete both elements. */ 1118c2ecf20Sopenharmony_ci key = 1; 1128c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == 0); 1138c2ecf20Sopenharmony_ci key = 2; 1148c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == 0); 1158c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci key = 0; 1188c2ecf20Sopenharmony_ci /* Check that map is empty. */ 1198c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 && 1208c2ecf20Sopenharmony_ci errno == ENOENT); 1218c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 && 1228c2ecf20Sopenharmony_ci errno == ENOENT); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci close(fd); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic void test_hashmap_sizes(unsigned int task, void *data) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci int fd, i, j; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci for (i = 1; i <= 512; i <<= 1) 1328c2ecf20Sopenharmony_ci for (j = 1; j <= 1 << 18; j <<= 1) { 1338c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j, 1348c2ecf20Sopenharmony_ci 2, map_flags); 1358c2ecf20Sopenharmony_ci if (fd < 0) { 1368c2ecf20Sopenharmony_ci if (errno == ENOMEM) 1378c2ecf20Sopenharmony_ci return; 1388c2ecf20Sopenharmony_ci printf("Failed to create hashmap key=%d value=%d '%s'\n", 1398c2ecf20Sopenharmony_ci i, j, strerror(errno)); 1408c2ecf20Sopenharmony_ci exit(1); 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci close(fd); 1438c2ecf20Sopenharmony_ci usleep(10); /* give kernel time to destroy */ 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic void test_hashmap_percpu(unsigned int task, void *data) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci unsigned int nr_cpus = bpf_num_possible_cpus(); 1508c2ecf20Sopenharmony_ci BPF_DECLARE_PERCPU(long, value); 1518c2ecf20Sopenharmony_ci long long key, next_key, first_key; 1528c2ecf20Sopenharmony_ci int expected_key_mask = 0; 1538c2ecf20Sopenharmony_ci int fd, i; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key), 1568c2ecf20Sopenharmony_ci sizeof(bpf_percpu(value, 0)), 2, map_flags); 1578c2ecf20Sopenharmony_ci if (fd < 0) { 1588c2ecf20Sopenharmony_ci printf("Failed to create hashmap '%s'!\n", strerror(errno)); 1598c2ecf20Sopenharmony_ci exit(1); 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci for (i = 0; i < nr_cpus; i++) 1638c2ecf20Sopenharmony_ci bpf_percpu(value, i) = i + 100; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci key = 1; 1668c2ecf20Sopenharmony_ci /* Insert key=1 element. */ 1678c2ecf20Sopenharmony_ci assert(!(expected_key_mask & key)); 1688c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0); 1698c2ecf20Sopenharmony_ci expected_key_mask |= key; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci /* BPF_NOEXIST means add new element if it doesn't exist. */ 1728c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 && 1738c2ecf20Sopenharmony_ci /* key=1 already exists. */ 1748c2ecf20Sopenharmony_ci errno == EEXIST); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* -1 is an invalid flag. */ 1778c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, value, -1) == -1 && 1788c2ecf20Sopenharmony_ci errno == EINVAL); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* Check that key=1 can be found. Value could be 0 if the lookup 1818c2ecf20Sopenharmony_ci * was run from a different CPU. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_ci bpf_percpu(value, 0) = 1; 1848c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, value) == 0 && 1858c2ecf20Sopenharmony_ci bpf_percpu(value, 0) == 100); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci key = 2; 1888c2ecf20Sopenharmony_ci /* Check that key=2 is not found. */ 1898c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* BPF_EXIST means update existing element. */ 1928c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 && 1938c2ecf20Sopenharmony_ci /* key=2 is not there. */ 1948c2ecf20Sopenharmony_ci errno == ENOENT); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci /* Insert key=2 element. */ 1978c2ecf20Sopenharmony_ci assert(!(expected_key_mask & key)); 1988c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0); 1998c2ecf20Sopenharmony_ci expected_key_mask |= key; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* key=1 and key=2 were inserted, check that key=0 cannot be 2028c2ecf20Sopenharmony_ci * inserted due to max_entries limit. 2038c2ecf20Sopenharmony_ci */ 2048c2ecf20Sopenharmony_ci key = 0; 2058c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 && 2068c2ecf20Sopenharmony_ci errno == E2BIG); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci /* Check that key = 0 doesn't exist. */ 2098c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* Iterate over two elements. */ 2128c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 && 2138c2ecf20Sopenharmony_ci ((expected_key_mask & first_key) == first_key)); 2148c2ecf20Sopenharmony_ci while (!bpf_map_get_next_key(fd, &key, &next_key)) { 2158c2ecf20Sopenharmony_ci if (first_key) { 2168c2ecf20Sopenharmony_ci assert(next_key == first_key); 2178c2ecf20Sopenharmony_ci first_key = 0; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci assert((expected_key_mask & next_key) == next_key); 2208c2ecf20Sopenharmony_ci expected_key_mask &= ~next_key; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &next_key, value) == 0); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci for (i = 0; i < nr_cpus; i++) 2258c2ecf20Sopenharmony_ci assert(bpf_percpu(value, i) == i + 100); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci key = next_key; 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci assert(errno == ENOENT); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* Update with BPF_EXIST. */ 2328c2ecf20Sopenharmony_ci key = 1; 2338c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* Delete both elements. */ 2368c2ecf20Sopenharmony_ci key = 1; 2378c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == 0); 2388c2ecf20Sopenharmony_ci key = 2; 2398c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == 0); 2408c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci key = 0; 2438c2ecf20Sopenharmony_ci /* Check that map is empty. */ 2448c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 && 2458c2ecf20Sopenharmony_ci errno == ENOENT); 2468c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 && 2478c2ecf20Sopenharmony_ci errno == ENOENT); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci close(fd); 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistatic int helper_fill_hashmap(int max_entries) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci int i, fd, ret; 2558c2ecf20Sopenharmony_ci long long key, value; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 2588c2ecf20Sopenharmony_ci max_entries, map_flags); 2598c2ecf20Sopenharmony_ci CHECK(fd < 0, 2608c2ecf20Sopenharmony_ci "failed to create hashmap", 2618c2ecf20Sopenharmony_ci "err: %s, flags: 0x%x\n", strerror(errno), map_flags); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci for (i = 0; i < max_entries; i++) { 2648c2ecf20Sopenharmony_ci key = i; value = key; 2658c2ecf20Sopenharmony_ci ret = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST); 2668c2ecf20Sopenharmony_ci CHECK(ret != 0, 2678c2ecf20Sopenharmony_ci "can't update hashmap", 2688c2ecf20Sopenharmony_ci "err: %s\n", strerror(ret)); 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci return fd; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic void test_hashmap_walk(unsigned int task, void *data) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci int fd, i, max_entries = 1000; 2778c2ecf20Sopenharmony_ci long long key, value, next_key; 2788c2ecf20Sopenharmony_ci bool next_key_valid = true; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci fd = helper_fill_hashmap(max_entries); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key, 2838c2ecf20Sopenharmony_ci &next_key) == 0; i++) { 2848c2ecf20Sopenharmony_ci key = next_key; 2858c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == 0); 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci assert(i == max_entries); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 2918c2ecf20Sopenharmony_ci for (i = 0; next_key_valid; i++) { 2928c2ecf20Sopenharmony_ci next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0; 2938c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == 0); 2948c2ecf20Sopenharmony_ci value++; 2958c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); 2968c2ecf20Sopenharmony_ci key = next_key; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci assert(i == max_entries); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key, 3028c2ecf20Sopenharmony_ci &next_key) == 0; i++) { 3038c2ecf20Sopenharmony_ci key = next_key; 3048c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == 0); 3058c2ecf20Sopenharmony_ci assert(value - 1 == key); 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci assert(i == max_entries); 3098c2ecf20Sopenharmony_ci close(fd); 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic void test_hashmap_zero_seed(void) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci int i, first, second, old_flags; 3158c2ecf20Sopenharmony_ci long long key, next_first, next_second; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci old_flags = map_flags; 3188c2ecf20Sopenharmony_ci map_flags |= BPF_F_ZERO_SEED; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci first = helper_fill_hashmap(3); 3218c2ecf20Sopenharmony_ci second = helper_fill_hashmap(3); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci for (i = 0; ; i++) { 3248c2ecf20Sopenharmony_ci void *key_ptr = !i ? NULL : &key; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (bpf_map_get_next_key(first, key_ptr, &next_first) != 0) 3278c2ecf20Sopenharmony_ci break; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci CHECK(bpf_map_get_next_key(second, key_ptr, &next_second) != 0, 3308c2ecf20Sopenharmony_ci "next_key for second map must succeed", 3318c2ecf20Sopenharmony_ci "key_ptr: %p", key_ptr); 3328c2ecf20Sopenharmony_ci CHECK(next_first != next_second, 3338c2ecf20Sopenharmony_ci "keys must match", 3348c2ecf20Sopenharmony_ci "i: %d first: %lld second: %lld\n", i, 3358c2ecf20Sopenharmony_ci next_first, next_second); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci key = next_first; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci map_flags = old_flags; 3418c2ecf20Sopenharmony_ci close(first); 3428c2ecf20Sopenharmony_ci close(second); 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic void test_arraymap(unsigned int task, void *data) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci int key, next_key, fd; 3488c2ecf20Sopenharmony_ci long long value; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), 3518c2ecf20Sopenharmony_ci 2, 0); 3528c2ecf20Sopenharmony_ci if (fd < 0) { 3538c2ecf20Sopenharmony_ci printf("Failed to create arraymap '%s'!\n", strerror(errno)); 3548c2ecf20Sopenharmony_ci exit(1); 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci key = 1; 3588c2ecf20Sopenharmony_ci value = 1234; 3598c2ecf20Sopenharmony_ci /* Insert key=1 element. */ 3608c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci value = 0; 3638c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 3648c2ecf20Sopenharmony_ci errno == EEXIST); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci /* Check that key=1 can be found. */ 3678c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci key = 0; 3708c2ecf20Sopenharmony_ci /* Check that key=0 is also found and zero initialized. */ 3718c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /* key=0 and key=1 were inserted, check that key=2 cannot be inserted 3748c2ecf20Sopenharmony_ci * due to max_entries limit. 3758c2ecf20Sopenharmony_ci */ 3768c2ecf20Sopenharmony_ci key = 2; 3778c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 && 3788c2ecf20Sopenharmony_ci errno == E2BIG); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* Check that key = 2 doesn't exist. */ 3818c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* Iterate over two elements. */ 3848c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 && 3858c2ecf20Sopenharmony_ci next_key == 0); 3868c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 3878c2ecf20Sopenharmony_ci next_key == 0); 3888c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 3898c2ecf20Sopenharmony_ci next_key == 1); 3908c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && 3918c2ecf20Sopenharmony_ci errno == ENOENT); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci /* Delete shouldn't succeed. */ 3948c2ecf20Sopenharmony_ci key = 1; 3958c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci close(fd); 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic void test_arraymap_percpu(unsigned int task, void *data) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci unsigned int nr_cpus = bpf_num_possible_cpus(); 4038c2ecf20Sopenharmony_ci BPF_DECLARE_PERCPU(long, values); 4048c2ecf20Sopenharmony_ci int key, next_key, fd, i; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), 4078c2ecf20Sopenharmony_ci sizeof(bpf_percpu(values, 0)), 2, 0); 4088c2ecf20Sopenharmony_ci if (fd < 0) { 4098c2ecf20Sopenharmony_ci printf("Failed to create arraymap '%s'!\n", strerror(errno)); 4108c2ecf20Sopenharmony_ci exit(1); 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci for (i = 0; i < nr_cpus; i++) 4148c2ecf20Sopenharmony_ci bpf_percpu(values, i) = i + 100; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci key = 1; 4178c2ecf20Sopenharmony_ci /* Insert key=1 element. */ 4188c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci bpf_percpu(values, 0) = 0; 4218c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 && 4228c2ecf20Sopenharmony_ci errno == EEXIST); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci /* Check that key=1 can be found. */ 4258c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, values) == 0 && 4268c2ecf20Sopenharmony_ci bpf_percpu(values, 0) == 100); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci key = 0; 4298c2ecf20Sopenharmony_ci /* Check that key=0 is also found and zero initialized. */ 4308c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, values) == 0 && 4318c2ecf20Sopenharmony_ci bpf_percpu(values, 0) == 0 && 4328c2ecf20Sopenharmony_ci bpf_percpu(values, nr_cpus - 1) == 0); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci /* Check that key=2 cannot be inserted due to max_entries limit. */ 4358c2ecf20Sopenharmony_ci key = 2; 4368c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 && 4378c2ecf20Sopenharmony_ci errno == E2BIG); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* Check that key = 2 doesn't exist. */ 4408c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci /* Iterate over two elements. */ 4438c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 && 4448c2ecf20Sopenharmony_ci next_key == 0); 4458c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 4468c2ecf20Sopenharmony_ci next_key == 0); 4478c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 4488c2ecf20Sopenharmony_ci next_key == 1); 4498c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 && 4508c2ecf20Sopenharmony_ci errno == ENOENT); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci /* Delete shouldn't succeed. */ 4538c2ecf20Sopenharmony_ci key = 1; 4548c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci close(fd); 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_cistatic void test_arraymap_percpu_many_keys(void) 4608c2ecf20Sopenharmony_ci{ 4618c2ecf20Sopenharmony_ci unsigned int nr_cpus = bpf_num_possible_cpus(); 4628c2ecf20Sopenharmony_ci BPF_DECLARE_PERCPU(long, values); 4638c2ecf20Sopenharmony_ci /* nr_keys is not too large otherwise the test stresses percpu 4648c2ecf20Sopenharmony_ci * allocator more than anything else 4658c2ecf20Sopenharmony_ci */ 4668c2ecf20Sopenharmony_ci unsigned int nr_keys = 2000; 4678c2ecf20Sopenharmony_ci int key, fd, i; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), 4708c2ecf20Sopenharmony_ci sizeof(bpf_percpu(values, 0)), nr_keys, 0); 4718c2ecf20Sopenharmony_ci if (fd < 0) { 4728c2ecf20Sopenharmony_ci printf("Failed to create per-cpu arraymap '%s'!\n", 4738c2ecf20Sopenharmony_ci strerror(errno)); 4748c2ecf20Sopenharmony_ci exit(1); 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci for (i = 0; i < nr_cpus; i++) 4788c2ecf20Sopenharmony_ci bpf_percpu(values, i) = i + 10; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci for (key = 0; key < nr_keys; key++) 4818c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci for (key = 0; key < nr_keys; key++) { 4848c2ecf20Sopenharmony_ci for (i = 0; i < nr_cpus; i++) 4858c2ecf20Sopenharmony_ci bpf_percpu(values, i) = 0; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, values) == 0); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci for (i = 0; i < nr_cpus; i++) 4908c2ecf20Sopenharmony_ci assert(bpf_percpu(values, i) == i + 10); 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci close(fd); 4948c2ecf20Sopenharmony_ci} 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cistatic void test_devmap(unsigned int task, void *data) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci int fd; 4998c2ecf20Sopenharmony_ci __u32 key, value; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value), 5028c2ecf20Sopenharmony_ci 2, 0); 5038c2ecf20Sopenharmony_ci if (fd < 0) { 5048c2ecf20Sopenharmony_ci printf("Failed to create devmap '%s'!\n", strerror(errno)); 5058c2ecf20Sopenharmony_ci exit(1); 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci close(fd); 5098c2ecf20Sopenharmony_ci} 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_cistatic void test_devmap_hash(unsigned int task, void *data) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci int fd; 5148c2ecf20Sopenharmony_ci __u32 key, value; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP_HASH, sizeof(key), sizeof(value), 5178c2ecf20Sopenharmony_ci 2, 0); 5188c2ecf20Sopenharmony_ci if (fd < 0) { 5198c2ecf20Sopenharmony_ci printf("Failed to create devmap_hash '%s'!\n", strerror(errno)); 5208c2ecf20Sopenharmony_ci exit(1); 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci close(fd); 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic void test_queuemap(unsigned int task, void *data) 5278c2ecf20Sopenharmony_ci{ 5288c2ecf20Sopenharmony_ci const int MAP_SIZE = 32; 5298c2ecf20Sopenharmony_ci __u32 vals[MAP_SIZE + MAP_SIZE/2], val; 5308c2ecf20Sopenharmony_ci int fd, i; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci /* Fill test values to be used */ 5338c2ecf20Sopenharmony_ci for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++) 5348c2ecf20Sopenharmony_ci vals[i] = rand(); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci /* Invalid key size */ 5378c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 4, sizeof(val), MAP_SIZE, 5388c2ecf20Sopenharmony_ci map_flags); 5398c2ecf20Sopenharmony_ci assert(fd < 0 && errno == EINVAL); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 0, sizeof(val), MAP_SIZE, 5428c2ecf20Sopenharmony_ci map_flags); 5438c2ecf20Sopenharmony_ci /* Queue map does not support BPF_F_NO_PREALLOC */ 5448c2ecf20Sopenharmony_ci if (map_flags & BPF_F_NO_PREALLOC) { 5458c2ecf20Sopenharmony_ci assert(fd < 0 && errno == EINVAL); 5468c2ecf20Sopenharmony_ci return; 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci if (fd < 0) { 5498c2ecf20Sopenharmony_ci printf("Failed to create queuemap '%s'!\n", strerror(errno)); 5508c2ecf20Sopenharmony_ci exit(1); 5518c2ecf20Sopenharmony_ci } 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci /* Push MAP_SIZE elements */ 5548c2ecf20Sopenharmony_ci for (i = 0; i < MAP_SIZE; i++) 5558c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci /* Check that element cannot be pushed due to max_entries limit */ 5588c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 && 5598c2ecf20Sopenharmony_ci errno == E2BIG); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci /* Peek element */ 5628c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[0]); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci /* Replace half elements */ 5658c2ecf20Sopenharmony_ci for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++) 5668c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci /* Pop all elements */ 5698c2ecf20Sopenharmony_ci for (i = MAP_SIZE/2; i < MAP_SIZE + MAP_SIZE/2; i++) 5708c2ecf20Sopenharmony_ci assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 && 5718c2ecf20Sopenharmony_ci val == vals[i]); 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci /* Check that there are not elements left */ 5748c2ecf20Sopenharmony_ci assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == -1 && 5758c2ecf20Sopenharmony_ci errno == ENOENT); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci /* Check that non supported functions set errno to EINVAL */ 5788c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL); 5798c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci close(fd); 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic void test_stackmap(unsigned int task, void *data) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci const int MAP_SIZE = 32; 5878c2ecf20Sopenharmony_ci __u32 vals[MAP_SIZE + MAP_SIZE/2], val; 5888c2ecf20Sopenharmony_ci int fd, i; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci /* Fill test values to be used */ 5918c2ecf20Sopenharmony_ci for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++) 5928c2ecf20Sopenharmony_ci vals[i] = rand(); 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci /* Invalid key size */ 5958c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_STACK, 4, sizeof(val), MAP_SIZE, 5968c2ecf20Sopenharmony_ci map_flags); 5978c2ecf20Sopenharmony_ci assert(fd < 0 && errno == EINVAL); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_STACK, 0, sizeof(val), MAP_SIZE, 6008c2ecf20Sopenharmony_ci map_flags); 6018c2ecf20Sopenharmony_ci /* Stack map does not support BPF_F_NO_PREALLOC */ 6028c2ecf20Sopenharmony_ci if (map_flags & BPF_F_NO_PREALLOC) { 6038c2ecf20Sopenharmony_ci assert(fd < 0 && errno == EINVAL); 6048c2ecf20Sopenharmony_ci return; 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci if (fd < 0) { 6078c2ecf20Sopenharmony_ci printf("Failed to create stackmap '%s'!\n", strerror(errno)); 6088c2ecf20Sopenharmony_ci exit(1); 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci /* Push MAP_SIZE elements */ 6128c2ecf20Sopenharmony_ci for (i = 0; i < MAP_SIZE; i++) 6138c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci /* Check that element cannot be pushed due to max_entries limit */ 6168c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 && 6178c2ecf20Sopenharmony_ci errno == E2BIG); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci /* Peek element */ 6208c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[i - 1]); 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci /* Replace half elements */ 6238c2ecf20Sopenharmony_ci for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++) 6248c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /* Pop all elements */ 6278c2ecf20Sopenharmony_ci for (i = MAP_SIZE + MAP_SIZE/2 - 1; i >= MAP_SIZE/2; i--) 6288c2ecf20Sopenharmony_ci assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 && 6298c2ecf20Sopenharmony_ci val == vals[i]); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci /* Check that there are not elements left */ 6328c2ecf20Sopenharmony_ci assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == -1 && 6338c2ecf20Sopenharmony_ci errno == ENOENT); 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* Check that non supported functions set errno to EINVAL */ 6368c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL); 6378c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL); 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci close(fd); 6408c2ecf20Sopenharmony_ci} 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci#include <sys/ioctl.h> 6438c2ecf20Sopenharmony_ci#include <arpa/inet.h> 6448c2ecf20Sopenharmony_ci#include <sys/select.h> 6458c2ecf20Sopenharmony_ci#include <linux/err.h> 6468c2ecf20Sopenharmony_ci#define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o" 6478c2ecf20Sopenharmony_ci#define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o" 6488c2ecf20Sopenharmony_ci#define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o" 6498c2ecf20Sopenharmony_cistatic void test_sockmap(unsigned int tasks, void *data) 6508c2ecf20Sopenharmony_ci{ 6518c2ecf20Sopenharmony_ci struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break; 6528c2ecf20Sopenharmony_ci int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break; 6538c2ecf20Sopenharmony_ci int ports[] = {50200, 50201, 50202, 50204}; 6548c2ecf20Sopenharmony_ci int err, i, fd, udp, sfd[6] = {0xdeadbeef}; 6558c2ecf20Sopenharmony_ci u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0}; 6568c2ecf20Sopenharmony_ci int parse_prog, verdict_prog, msg_prog; 6578c2ecf20Sopenharmony_ci struct sockaddr_in addr; 6588c2ecf20Sopenharmony_ci int one = 1, s, sc, rc; 6598c2ecf20Sopenharmony_ci struct bpf_object *obj; 6608c2ecf20Sopenharmony_ci struct timeval to; 6618c2ecf20Sopenharmony_ci __u32 key, value; 6628c2ecf20Sopenharmony_ci pid_t pid[tasks]; 6638c2ecf20Sopenharmony_ci fd_set w; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci /* Create some sockets to use with sockmap */ 6668c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 6678c2ecf20Sopenharmony_ci sfd[i] = socket(AF_INET, SOCK_STREAM, 0); 6688c2ecf20Sopenharmony_ci if (sfd[i] < 0) 6698c2ecf20Sopenharmony_ci goto out; 6708c2ecf20Sopenharmony_ci err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR, 6718c2ecf20Sopenharmony_ci (char *)&one, sizeof(one)); 6728c2ecf20Sopenharmony_ci if (err) { 6738c2ecf20Sopenharmony_ci printf("failed to setsockopt\n"); 6748c2ecf20Sopenharmony_ci goto out; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci err = ioctl(sfd[i], FIONBIO, (char *)&one); 6778c2ecf20Sopenharmony_ci if (err < 0) { 6788c2ecf20Sopenharmony_ci printf("failed to ioctl\n"); 6798c2ecf20Sopenharmony_ci goto out; 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci memset(&addr, 0, sizeof(struct sockaddr_in)); 6828c2ecf20Sopenharmony_ci addr.sin_family = AF_INET; 6838c2ecf20Sopenharmony_ci addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 6848c2ecf20Sopenharmony_ci addr.sin_port = htons(ports[i]); 6858c2ecf20Sopenharmony_ci err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr)); 6868c2ecf20Sopenharmony_ci if (err < 0) { 6878c2ecf20Sopenharmony_ci printf("failed to bind: err %i: %i:%i\n", 6888c2ecf20Sopenharmony_ci err, i, sfd[i]); 6898c2ecf20Sopenharmony_ci goto out; 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci err = listen(sfd[i], 32); 6928c2ecf20Sopenharmony_ci if (err < 0) { 6938c2ecf20Sopenharmony_ci printf("failed to listen\n"); 6948c2ecf20Sopenharmony_ci goto out; 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci } 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci for (i = 2; i < 4; i++) { 6998c2ecf20Sopenharmony_ci sfd[i] = socket(AF_INET, SOCK_STREAM, 0); 7008c2ecf20Sopenharmony_ci if (sfd[i] < 0) 7018c2ecf20Sopenharmony_ci goto out; 7028c2ecf20Sopenharmony_ci err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR, 7038c2ecf20Sopenharmony_ci (char *)&one, sizeof(one)); 7048c2ecf20Sopenharmony_ci if (err) { 7058c2ecf20Sopenharmony_ci printf("set sock opt\n"); 7068c2ecf20Sopenharmony_ci goto out; 7078c2ecf20Sopenharmony_ci } 7088c2ecf20Sopenharmony_ci memset(&addr, 0, sizeof(struct sockaddr_in)); 7098c2ecf20Sopenharmony_ci addr.sin_family = AF_INET; 7108c2ecf20Sopenharmony_ci addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 7118c2ecf20Sopenharmony_ci addr.sin_port = htons(ports[i - 2]); 7128c2ecf20Sopenharmony_ci err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr)); 7138c2ecf20Sopenharmony_ci if (err) { 7148c2ecf20Sopenharmony_ci printf("failed to connect\n"); 7158c2ecf20Sopenharmony_ci goto out; 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci for (i = 4; i < 6; i++) { 7218c2ecf20Sopenharmony_ci sfd[i] = accept(sfd[i - 4], NULL, NULL); 7228c2ecf20Sopenharmony_ci if (sfd[i] < 0) { 7238c2ecf20Sopenharmony_ci printf("accept failed\n"); 7248c2ecf20Sopenharmony_ci goto out; 7258c2ecf20Sopenharmony_ci } 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci /* Test sockmap with connected sockets */ 7298c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP, 7308c2ecf20Sopenharmony_ci sizeof(key), sizeof(value), 7318c2ecf20Sopenharmony_ci 6, 0); 7328c2ecf20Sopenharmony_ci if (fd < 0) { 7338c2ecf20Sopenharmony_ci if (!bpf_probe_map_type(BPF_MAP_TYPE_SOCKMAP, 0)) { 7348c2ecf20Sopenharmony_ci printf("%s SKIP (unsupported map type BPF_MAP_TYPE_SOCKMAP)\n", 7358c2ecf20Sopenharmony_ci __func__); 7368c2ecf20Sopenharmony_ci skips++; 7378c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) 7388c2ecf20Sopenharmony_ci close(sfd[i]); 7398c2ecf20Sopenharmony_ci return; 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci printf("Failed to create sockmap %i\n", fd); 7438c2ecf20Sopenharmony_ci goto out_sockmap; 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci /* Test update with unsupported UDP socket */ 7478c2ecf20Sopenharmony_ci udp = socket(AF_INET, SOCK_DGRAM, 0); 7488c2ecf20Sopenharmony_ci i = 0; 7498c2ecf20Sopenharmony_ci err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY); 7508c2ecf20Sopenharmony_ci if (!err) { 7518c2ecf20Sopenharmony_ci printf("Failed socket SOCK_DGRAM allowed '%i:%i'\n", 7528c2ecf20Sopenharmony_ci i, udp); 7538c2ecf20Sopenharmony_ci goto out_sockmap; 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci /* Test update without programs */ 7578c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 7588c2ecf20Sopenharmony_ci err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 7598c2ecf20Sopenharmony_ci if (err) { 7608c2ecf20Sopenharmony_ci printf("Failed noprog update sockmap '%i:%i'\n", 7618c2ecf20Sopenharmony_ci i, sfd[i]); 7628c2ecf20Sopenharmony_ci goto out_sockmap; 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci /* Test attaching/detaching bad fds */ 7678c2ecf20Sopenharmony_ci err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0); 7688c2ecf20Sopenharmony_ci if (!err) { 7698c2ecf20Sopenharmony_ci printf("Failed invalid parser prog attach\n"); 7708c2ecf20Sopenharmony_ci goto out_sockmap; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0); 7748c2ecf20Sopenharmony_ci if (!err) { 7758c2ecf20Sopenharmony_ci printf("Failed invalid verdict prog attach\n"); 7768c2ecf20Sopenharmony_ci goto out_sockmap; 7778c2ecf20Sopenharmony_ci } 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0); 7808c2ecf20Sopenharmony_ci if (!err) { 7818c2ecf20Sopenharmony_ci printf("Failed invalid msg verdict prog attach\n"); 7828c2ecf20Sopenharmony_ci goto out_sockmap; 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0); 7868c2ecf20Sopenharmony_ci if (!err) { 7878c2ecf20Sopenharmony_ci printf("Failed unknown prog attach\n"); 7888c2ecf20Sopenharmony_ci goto out_sockmap; 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER); 7928c2ecf20Sopenharmony_ci if (!err) { 7938c2ecf20Sopenharmony_ci printf("Failed empty parser prog detach\n"); 7948c2ecf20Sopenharmony_ci goto out_sockmap; 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT); 7988c2ecf20Sopenharmony_ci if (!err) { 7998c2ecf20Sopenharmony_ci printf("Failed empty verdict prog detach\n"); 8008c2ecf20Sopenharmony_ci goto out_sockmap; 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT); 8048c2ecf20Sopenharmony_ci if (!err) { 8058c2ecf20Sopenharmony_ci printf("Failed empty msg verdict prog detach\n"); 8068c2ecf20Sopenharmony_ci goto out_sockmap; 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE); 8108c2ecf20Sopenharmony_ci if (!err) { 8118c2ecf20Sopenharmony_ci printf("Detach invalid prog successful\n"); 8128c2ecf20Sopenharmony_ci goto out_sockmap; 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci /* Load SK_SKB program and Attach */ 8168c2ecf20Sopenharmony_ci err = bpf_prog_load(SOCKMAP_PARSE_PROG, 8178c2ecf20Sopenharmony_ci BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog); 8188c2ecf20Sopenharmony_ci if (err) { 8198c2ecf20Sopenharmony_ci printf("Failed to load SK_SKB parse prog\n"); 8208c2ecf20Sopenharmony_ci goto out_sockmap; 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci err = bpf_prog_load(SOCKMAP_TCP_MSG_PROG, 8248c2ecf20Sopenharmony_ci BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog); 8258c2ecf20Sopenharmony_ci if (err) { 8268c2ecf20Sopenharmony_ci printf("Failed to load SK_SKB msg prog\n"); 8278c2ecf20Sopenharmony_ci goto out_sockmap; 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci err = bpf_prog_load(SOCKMAP_VERDICT_PROG, 8318c2ecf20Sopenharmony_ci BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog); 8328c2ecf20Sopenharmony_ci if (err) { 8338c2ecf20Sopenharmony_ci printf("Failed to load SK_SKB verdict prog\n"); 8348c2ecf20Sopenharmony_ci goto out_sockmap; 8358c2ecf20Sopenharmony_ci } 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx"); 8388c2ecf20Sopenharmony_ci if (IS_ERR(bpf_map_rx)) { 8398c2ecf20Sopenharmony_ci printf("Failed to load map rx from verdict prog\n"); 8408c2ecf20Sopenharmony_ci goto out_sockmap; 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci map_fd_rx = bpf_map__fd(bpf_map_rx); 8448c2ecf20Sopenharmony_ci if (map_fd_rx < 0) { 8458c2ecf20Sopenharmony_ci printf("Failed to get map rx fd\n"); 8468c2ecf20Sopenharmony_ci goto out_sockmap; 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx"); 8508c2ecf20Sopenharmony_ci if (IS_ERR(bpf_map_tx)) { 8518c2ecf20Sopenharmony_ci printf("Failed to load map tx from verdict prog\n"); 8528c2ecf20Sopenharmony_ci goto out_sockmap; 8538c2ecf20Sopenharmony_ci } 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci map_fd_tx = bpf_map__fd(bpf_map_tx); 8568c2ecf20Sopenharmony_ci if (map_fd_tx < 0) { 8578c2ecf20Sopenharmony_ci printf("Failed to get map tx fd\n"); 8588c2ecf20Sopenharmony_ci goto out_sockmap; 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg"); 8628c2ecf20Sopenharmony_ci if (IS_ERR(bpf_map_msg)) { 8638c2ecf20Sopenharmony_ci printf("Failed to load map msg from msg_verdict prog\n"); 8648c2ecf20Sopenharmony_ci goto out_sockmap; 8658c2ecf20Sopenharmony_ci } 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci map_fd_msg = bpf_map__fd(bpf_map_msg); 8688c2ecf20Sopenharmony_ci if (map_fd_msg < 0) { 8698c2ecf20Sopenharmony_ci printf("Failed to get map msg fd\n"); 8708c2ecf20Sopenharmony_ci goto out_sockmap; 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break"); 8748c2ecf20Sopenharmony_ci if (IS_ERR(bpf_map_break)) { 8758c2ecf20Sopenharmony_ci printf("Failed to load map tx from verdict prog\n"); 8768c2ecf20Sopenharmony_ci goto out_sockmap; 8778c2ecf20Sopenharmony_ci } 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci map_fd_break = bpf_map__fd(bpf_map_break); 8808c2ecf20Sopenharmony_ci if (map_fd_break < 0) { 8818c2ecf20Sopenharmony_ci printf("Failed to get map tx fd\n"); 8828c2ecf20Sopenharmony_ci goto out_sockmap; 8838c2ecf20Sopenharmony_ci } 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci err = bpf_prog_attach(parse_prog, map_fd_break, 8868c2ecf20Sopenharmony_ci BPF_SK_SKB_STREAM_PARSER, 0); 8878c2ecf20Sopenharmony_ci if (!err) { 8888c2ecf20Sopenharmony_ci printf("Allowed attaching SK_SKB program to invalid map\n"); 8898c2ecf20Sopenharmony_ci goto out_sockmap; 8908c2ecf20Sopenharmony_ci } 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci err = bpf_prog_attach(parse_prog, map_fd_rx, 8938c2ecf20Sopenharmony_ci BPF_SK_SKB_STREAM_PARSER, 0); 8948c2ecf20Sopenharmony_ci if (err) { 8958c2ecf20Sopenharmony_ci printf("Failed stream parser bpf prog attach\n"); 8968c2ecf20Sopenharmony_ci goto out_sockmap; 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci err = bpf_prog_attach(verdict_prog, map_fd_rx, 9008c2ecf20Sopenharmony_ci BPF_SK_SKB_STREAM_VERDICT, 0); 9018c2ecf20Sopenharmony_ci if (err) { 9028c2ecf20Sopenharmony_ci printf("Failed stream verdict bpf prog attach\n"); 9038c2ecf20Sopenharmony_ci goto out_sockmap; 9048c2ecf20Sopenharmony_ci } 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0); 9078c2ecf20Sopenharmony_ci if (err) { 9088c2ecf20Sopenharmony_ci printf("Failed msg verdict bpf prog attach\n"); 9098c2ecf20Sopenharmony_ci goto out_sockmap; 9108c2ecf20Sopenharmony_ci } 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci err = bpf_prog_attach(verdict_prog, map_fd_rx, 9138c2ecf20Sopenharmony_ci __MAX_BPF_ATTACH_TYPE, 0); 9148c2ecf20Sopenharmony_ci if (!err) { 9158c2ecf20Sopenharmony_ci printf("Attached unknown bpf prog\n"); 9168c2ecf20Sopenharmony_ci goto out_sockmap; 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci /* Test map update elem afterwards fd lives in fd and map_fd */ 9208c2ecf20Sopenharmony_ci for (i = 2; i < 6; i++) { 9218c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY); 9228c2ecf20Sopenharmony_ci if (err) { 9238c2ecf20Sopenharmony_ci printf("Failed map_fd_rx update sockmap %i '%i:%i'\n", 9248c2ecf20Sopenharmony_ci err, i, sfd[i]); 9258c2ecf20Sopenharmony_ci goto out_sockmap; 9268c2ecf20Sopenharmony_ci } 9278c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY); 9288c2ecf20Sopenharmony_ci if (err) { 9298c2ecf20Sopenharmony_ci printf("Failed map_fd_tx update sockmap %i '%i:%i'\n", 9308c2ecf20Sopenharmony_ci err, i, sfd[i]); 9318c2ecf20Sopenharmony_ci goto out_sockmap; 9328c2ecf20Sopenharmony_ci } 9338c2ecf20Sopenharmony_ci } 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci /* Test map delete elem and remove send/recv sockets */ 9368c2ecf20Sopenharmony_ci for (i = 2; i < 4; i++) { 9378c2ecf20Sopenharmony_ci err = bpf_map_delete_elem(map_fd_rx, &i); 9388c2ecf20Sopenharmony_ci if (err) { 9398c2ecf20Sopenharmony_ci printf("Failed delete sockmap rx %i '%i:%i'\n", 9408c2ecf20Sopenharmony_ci err, i, sfd[i]); 9418c2ecf20Sopenharmony_ci goto out_sockmap; 9428c2ecf20Sopenharmony_ci } 9438c2ecf20Sopenharmony_ci err = bpf_map_delete_elem(map_fd_tx, &i); 9448c2ecf20Sopenharmony_ci if (err) { 9458c2ecf20Sopenharmony_ci printf("Failed delete sockmap tx %i '%i:%i'\n", 9468c2ecf20Sopenharmony_ci err, i, sfd[i]); 9478c2ecf20Sopenharmony_ci goto out_sockmap; 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci } 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci /* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */ 9528c2ecf20Sopenharmony_ci i = 0; 9538c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY); 9548c2ecf20Sopenharmony_ci if (err) { 9558c2ecf20Sopenharmony_ci printf("Failed map_fd_msg update sockmap %i\n", err); 9568c2ecf20Sopenharmony_ci goto out_sockmap; 9578c2ecf20Sopenharmony_ci } 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci /* Test map send/recv */ 9608c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 9618c2ecf20Sopenharmony_ci buf[0] = i; 9628c2ecf20Sopenharmony_ci buf[1] = 0x5; 9638c2ecf20Sopenharmony_ci sc = send(sfd[2], buf, 20, 0); 9648c2ecf20Sopenharmony_ci if (sc < 0) { 9658c2ecf20Sopenharmony_ci printf("Failed sockmap send\n"); 9668c2ecf20Sopenharmony_ci goto out_sockmap; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci FD_ZERO(&w); 9708c2ecf20Sopenharmony_ci FD_SET(sfd[3], &w); 9718c2ecf20Sopenharmony_ci to.tv_sec = 30; 9728c2ecf20Sopenharmony_ci to.tv_usec = 0; 9738c2ecf20Sopenharmony_ci s = select(sfd[3] + 1, &w, NULL, NULL, &to); 9748c2ecf20Sopenharmony_ci if (s == -1) { 9758c2ecf20Sopenharmony_ci perror("Failed sockmap select()"); 9768c2ecf20Sopenharmony_ci goto out_sockmap; 9778c2ecf20Sopenharmony_ci } else if (!s) { 9788c2ecf20Sopenharmony_ci printf("Failed sockmap unexpected timeout\n"); 9798c2ecf20Sopenharmony_ci goto out_sockmap; 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci if (!FD_ISSET(sfd[3], &w)) { 9838c2ecf20Sopenharmony_ci printf("Failed sockmap select/recv\n"); 9848c2ecf20Sopenharmony_ci goto out_sockmap; 9858c2ecf20Sopenharmony_ci } 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci rc = recv(sfd[3], buf, sizeof(buf), 0); 9888c2ecf20Sopenharmony_ci if (rc < 0) { 9898c2ecf20Sopenharmony_ci printf("Failed sockmap recv\n"); 9908c2ecf20Sopenharmony_ci goto out_sockmap; 9918c2ecf20Sopenharmony_ci } 9928c2ecf20Sopenharmony_ci } 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* Negative null entry lookup from datapath should be dropped */ 9958c2ecf20Sopenharmony_ci buf[0] = 1; 9968c2ecf20Sopenharmony_ci buf[1] = 12; 9978c2ecf20Sopenharmony_ci sc = send(sfd[2], buf, 20, 0); 9988c2ecf20Sopenharmony_ci if (sc < 0) { 9998c2ecf20Sopenharmony_ci printf("Failed sockmap send\n"); 10008c2ecf20Sopenharmony_ci goto out_sockmap; 10018c2ecf20Sopenharmony_ci } 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci /* Push fd into same slot */ 10048c2ecf20Sopenharmony_ci i = 2; 10058c2ecf20Sopenharmony_ci err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 10068c2ecf20Sopenharmony_ci if (!err) { 10078c2ecf20Sopenharmony_ci printf("Failed allowed sockmap dup slot BPF_NOEXIST\n"); 10088c2ecf20Sopenharmony_ci goto out_sockmap; 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 10128c2ecf20Sopenharmony_ci if (err) { 10138c2ecf20Sopenharmony_ci printf("Failed sockmap update new slot BPF_ANY\n"); 10148c2ecf20Sopenharmony_ci goto out_sockmap; 10158c2ecf20Sopenharmony_ci } 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 10188c2ecf20Sopenharmony_ci if (err) { 10198c2ecf20Sopenharmony_ci printf("Failed sockmap update new slot BPF_EXIST\n"); 10208c2ecf20Sopenharmony_ci goto out_sockmap; 10218c2ecf20Sopenharmony_ci } 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci /* Delete the elems without programs */ 10248c2ecf20Sopenharmony_ci for (i = 2; i < 6; i++) { 10258c2ecf20Sopenharmony_ci err = bpf_map_delete_elem(fd, &i); 10268c2ecf20Sopenharmony_ci if (err) { 10278c2ecf20Sopenharmony_ci printf("Failed delete sockmap %i '%i:%i'\n", 10288c2ecf20Sopenharmony_ci err, i, sfd[i]); 10298c2ecf20Sopenharmony_ci } 10308c2ecf20Sopenharmony_ci } 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci /* Test having multiple maps open and set with programs on same fds */ 10338c2ecf20Sopenharmony_ci err = bpf_prog_attach(parse_prog, fd, 10348c2ecf20Sopenharmony_ci BPF_SK_SKB_STREAM_PARSER, 0); 10358c2ecf20Sopenharmony_ci if (err) { 10368c2ecf20Sopenharmony_ci printf("Failed fd bpf parse prog attach\n"); 10378c2ecf20Sopenharmony_ci goto out_sockmap; 10388c2ecf20Sopenharmony_ci } 10398c2ecf20Sopenharmony_ci err = bpf_prog_attach(verdict_prog, fd, 10408c2ecf20Sopenharmony_ci BPF_SK_SKB_STREAM_VERDICT, 0); 10418c2ecf20Sopenharmony_ci if (err) { 10428c2ecf20Sopenharmony_ci printf("Failed fd bpf verdict prog attach\n"); 10438c2ecf20Sopenharmony_ci goto out_sockmap; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci for (i = 4; i < 6; i++) { 10478c2ecf20Sopenharmony_ci err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 10488c2ecf20Sopenharmony_ci if (!err) { 10498c2ecf20Sopenharmony_ci printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n", 10508c2ecf20Sopenharmony_ci err, i, sfd[i]); 10518c2ecf20Sopenharmony_ci goto out_sockmap; 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 10548c2ecf20Sopenharmony_ci if (!err) { 10558c2ecf20Sopenharmony_ci printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n", 10568c2ecf20Sopenharmony_ci err, i, sfd[i]); 10578c2ecf20Sopenharmony_ci goto out_sockmap; 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 10608c2ecf20Sopenharmony_ci if (!err) { 10618c2ecf20Sopenharmony_ci printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n", 10628c2ecf20Sopenharmony_ci err, i, sfd[i]); 10638c2ecf20Sopenharmony_ci goto out_sockmap; 10648c2ecf20Sopenharmony_ci } 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci /* Test tasks number of forked operations */ 10688c2ecf20Sopenharmony_ci for (i = 0; i < tasks; i++) { 10698c2ecf20Sopenharmony_ci pid[i] = fork(); 10708c2ecf20Sopenharmony_ci if (pid[i] == 0) { 10718c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 10728c2ecf20Sopenharmony_ci bpf_map_delete_elem(map_fd_tx, &i); 10738c2ecf20Sopenharmony_ci bpf_map_delete_elem(map_fd_rx, &i); 10748c2ecf20Sopenharmony_ci bpf_map_update_elem(map_fd_tx, &i, 10758c2ecf20Sopenharmony_ci &sfd[i], BPF_ANY); 10768c2ecf20Sopenharmony_ci bpf_map_update_elem(map_fd_rx, &i, 10778c2ecf20Sopenharmony_ci &sfd[i], BPF_ANY); 10788c2ecf20Sopenharmony_ci } 10798c2ecf20Sopenharmony_ci exit(0); 10808c2ecf20Sopenharmony_ci } else if (pid[i] == -1) { 10818c2ecf20Sopenharmony_ci printf("Couldn't spawn #%d process!\n", i); 10828c2ecf20Sopenharmony_ci exit(1); 10838c2ecf20Sopenharmony_ci } 10848c2ecf20Sopenharmony_ci } 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci for (i = 0; i < tasks; i++) { 10878c2ecf20Sopenharmony_ci int status; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci assert(waitpid(pid[i], &status, 0) == pid[i]); 10908c2ecf20Sopenharmony_ci assert(status == 0); 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE); 10948c2ecf20Sopenharmony_ci if (!err) { 10958c2ecf20Sopenharmony_ci printf("Detached an invalid prog type.\n"); 10968c2ecf20Sopenharmony_ci goto out_sockmap; 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER); 11008c2ecf20Sopenharmony_ci if (err) { 11018c2ecf20Sopenharmony_ci printf("Failed parser prog detach\n"); 11028c2ecf20Sopenharmony_ci goto out_sockmap; 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT); 11068c2ecf20Sopenharmony_ci if (err) { 11078c2ecf20Sopenharmony_ci printf("Failed parser prog detach\n"); 11088c2ecf20Sopenharmony_ci goto out_sockmap; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci /* Test map close sockets and empty maps */ 11128c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 11138c2ecf20Sopenharmony_ci bpf_map_delete_elem(map_fd_tx, &i); 11148c2ecf20Sopenharmony_ci bpf_map_delete_elem(map_fd_rx, &i); 11158c2ecf20Sopenharmony_ci close(sfd[i]); 11168c2ecf20Sopenharmony_ci } 11178c2ecf20Sopenharmony_ci close(fd); 11188c2ecf20Sopenharmony_ci close(map_fd_rx); 11198c2ecf20Sopenharmony_ci bpf_object__close(obj); 11208c2ecf20Sopenharmony_ci return; 11218c2ecf20Sopenharmony_ciout: 11228c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) 11238c2ecf20Sopenharmony_ci close(sfd[i]); 11248c2ecf20Sopenharmony_ci printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno)); 11258c2ecf20Sopenharmony_ci exit(1); 11268c2ecf20Sopenharmony_ciout_sockmap: 11278c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 11288c2ecf20Sopenharmony_ci if (map_fd_tx) 11298c2ecf20Sopenharmony_ci bpf_map_delete_elem(map_fd_tx, &i); 11308c2ecf20Sopenharmony_ci if (map_fd_rx) 11318c2ecf20Sopenharmony_ci bpf_map_delete_elem(map_fd_rx, &i); 11328c2ecf20Sopenharmony_ci close(sfd[i]); 11338c2ecf20Sopenharmony_ci } 11348c2ecf20Sopenharmony_ci close(fd); 11358c2ecf20Sopenharmony_ci exit(1); 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci#define MAPINMAP_PROG "./test_map_in_map.o" 11398c2ecf20Sopenharmony_cistatic void test_map_in_map(void) 11408c2ecf20Sopenharmony_ci{ 11418c2ecf20Sopenharmony_ci struct bpf_object *obj; 11428c2ecf20Sopenharmony_ci struct bpf_map *map; 11438c2ecf20Sopenharmony_ci int mim_fd, fd, err; 11448c2ecf20Sopenharmony_ci int pos = 0; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci obj = bpf_object__open(MAPINMAP_PROG); 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int), sizeof(int), 11498c2ecf20Sopenharmony_ci 2, 0); 11508c2ecf20Sopenharmony_ci if (fd < 0) { 11518c2ecf20Sopenharmony_ci printf("Failed to create hashmap '%s'!\n", strerror(errno)); 11528c2ecf20Sopenharmony_ci exit(1); 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci map = bpf_object__find_map_by_name(obj, "mim_array"); 11568c2ecf20Sopenharmony_ci if (IS_ERR(map)) { 11578c2ecf20Sopenharmony_ci printf("Failed to load array of maps from test prog\n"); 11588c2ecf20Sopenharmony_ci goto out_map_in_map; 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci err = bpf_map__set_inner_map_fd(map, fd); 11618c2ecf20Sopenharmony_ci if (err) { 11628c2ecf20Sopenharmony_ci printf("Failed to set inner_map_fd for array of maps\n"); 11638c2ecf20Sopenharmony_ci goto out_map_in_map; 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci map = bpf_object__find_map_by_name(obj, "mim_hash"); 11678c2ecf20Sopenharmony_ci if (IS_ERR(map)) { 11688c2ecf20Sopenharmony_ci printf("Failed to load hash of maps from test prog\n"); 11698c2ecf20Sopenharmony_ci goto out_map_in_map; 11708c2ecf20Sopenharmony_ci } 11718c2ecf20Sopenharmony_ci err = bpf_map__set_inner_map_fd(map, fd); 11728c2ecf20Sopenharmony_ci if (err) { 11738c2ecf20Sopenharmony_ci printf("Failed to set inner_map_fd for hash of maps\n"); 11748c2ecf20Sopenharmony_ci goto out_map_in_map; 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci bpf_object__load(obj); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci map = bpf_object__find_map_by_name(obj, "mim_array"); 11808c2ecf20Sopenharmony_ci if (IS_ERR(map)) { 11818c2ecf20Sopenharmony_ci printf("Failed to load array of maps from test prog\n"); 11828c2ecf20Sopenharmony_ci goto out_map_in_map; 11838c2ecf20Sopenharmony_ci } 11848c2ecf20Sopenharmony_ci mim_fd = bpf_map__fd(map); 11858c2ecf20Sopenharmony_ci if (mim_fd < 0) { 11868c2ecf20Sopenharmony_ci printf("Failed to get descriptor for array of maps\n"); 11878c2ecf20Sopenharmony_ci goto out_map_in_map; 11888c2ecf20Sopenharmony_ci } 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci err = bpf_map_update_elem(mim_fd, &pos, &fd, 0); 11918c2ecf20Sopenharmony_ci if (err) { 11928c2ecf20Sopenharmony_ci printf("Failed to update array of maps\n"); 11938c2ecf20Sopenharmony_ci goto out_map_in_map; 11948c2ecf20Sopenharmony_ci } 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci map = bpf_object__find_map_by_name(obj, "mim_hash"); 11978c2ecf20Sopenharmony_ci if (IS_ERR(map)) { 11988c2ecf20Sopenharmony_ci printf("Failed to load hash of maps from test prog\n"); 11998c2ecf20Sopenharmony_ci goto out_map_in_map; 12008c2ecf20Sopenharmony_ci } 12018c2ecf20Sopenharmony_ci mim_fd = bpf_map__fd(map); 12028c2ecf20Sopenharmony_ci if (mim_fd < 0) { 12038c2ecf20Sopenharmony_ci printf("Failed to get descriptor for hash of maps\n"); 12048c2ecf20Sopenharmony_ci goto out_map_in_map; 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci err = bpf_map_update_elem(mim_fd, &pos, &fd, 0); 12088c2ecf20Sopenharmony_ci if (err) { 12098c2ecf20Sopenharmony_ci printf("Failed to update hash of maps\n"); 12108c2ecf20Sopenharmony_ci goto out_map_in_map; 12118c2ecf20Sopenharmony_ci } 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci close(fd); 12148c2ecf20Sopenharmony_ci bpf_object__close(obj); 12158c2ecf20Sopenharmony_ci return; 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ciout_map_in_map: 12188c2ecf20Sopenharmony_ci close(fd); 12198c2ecf20Sopenharmony_ci exit(1); 12208c2ecf20Sopenharmony_ci} 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci#define MAP_SIZE (32 * 1024) 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_cistatic void test_map_large(void) 12258c2ecf20Sopenharmony_ci{ 12268c2ecf20Sopenharmony_ci struct bigkey { 12278c2ecf20Sopenharmony_ci int a; 12288c2ecf20Sopenharmony_ci char b[116]; 12298c2ecf20Sopenharmony_ci long long c; 12308c2ecf20Sopenharmony_ci } key; 12318c2ecf20Sopenharmony_ci int fd, i, value; 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 12348c2ecf20Sopenharmony_ci MAP_SIZE, map_flags); 12358c2ecf20Sopenharmony_ci if (fd < 0) { 12368c2ecf20Sopenharmony_ci printf("Failed to create large map '%s'!\n", strerror(errno)); 12378c2ecf20Sopenharmony_ci exit(1); 12388c2ecf20Sopenharmony_ci } 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci for (i = 0; i < MAP_SIZE; i++) { 12418c2ecf20Sopenharmony_ci key = (struct bigkey) { .c = i }; 12428c2ecf20Sopenharmony_ci value = i; 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci key.c = -1; 12488c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 12498c2ecf20Sopenharmony_ci errno == E2BIG); 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci /* Iterate through all elements. */ 12528c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 12538c2ecf20Sopenharmony_ci key.c = -1; 12548c2ecf20Sopenharmony_ci for (i = 0; i < MAP_SIZE; i++) 12558c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &key) == 0); 12568c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci key.c = 0; 12598c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 12608c2ecf20Sopenharmony_ci key.a = 1; 12618c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci close(fd); 12648c2ecf20Sopenharmony_ci} 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci#define run_parallel(N, FN, DATA) \ 12678c2ecf20Sopenharmony_ci printf("Fork %u tasks to '" #FN "'\n", N); \ 12688c2ecf20Sopenharmony_ci __run_parallel(N, FN, DATA) 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_cistatic void __run_parallel(unsigned int tasks, 12718c2ecf20Sopenharmony_ci void (*fn)(unsigned int task, void *data), 12728c2ecf20Sopenharmony_ci void *data) 12738c2ecf20Sopenharmony_ci{ 12748c2ecf20Sopenharmony_ci pid_t pid[tasks]; 12758c2ecf20Sopenharmony_ci int i; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci fflush(stdout); 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci for (i = 0; i < tasks; i++) { 12808c2ecf20Sopenharmony_ci pid[i] = fork(); 12818c2ecf20Sopenharmony_ci if (pid[i] == 0) { 12828c2ecf20Sopenharmony_ci fn(i, data); 12838c2ecf20Sopenharmony_ci exit(0); 12848c2ecf20Sopenharmony_ci } else if (pid[i] == -1) { 12858c2ecf20Sopenharmony_ci printf("Couldn't spawn #%d process!\n", i); 12868c2ecf20Sopenharmony_ci exit(1); 12878c2ecf20Sopenharmony_ci } 12888c2ecf20Sopenharmony_ci } 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci for (i = 0; i < tasks; i++) { 12918c2ecf20Sopenharmony_ci int status; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci assert(waitpid(pid[i], &status, 0) == pid[i]); 12948c2ecf20Sopenharmony_ci assert(status == 0); 12958c2ecf20Sopenharmony_ci } 12968c2ecf20Sopenharmony_ci} 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_cistatic void test_map_stress(void) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci run_parallel(100, test_hashmap, NULL); 13018c2ecf20Sopenharmony_ci run_parallel(100, test_hashmap_percpu, NULL); 13028c2ecf20Sopenharmony_ci run_parallel(100, test_hashmap_sizes, NULL); 13038c2ecf20Sopenharmony_ci run_parallel(100, test_hashmap_walk, NULL); 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci run_parallel(100, test_arraymap, NULL); 13068c2ecf20Sopenharmony_ci run_parallel(100, test_arraymap_percpu, NULL); 13078c2ecf20Sopenharmony_ci} 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci#define TASKS 1024 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci#define DO_UPDATE 1 13128c2ecf20Sopenharmony_ci#define DO_DELETE 0 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_cistatic void test_update_delete(unsigned int fn, void *data) 13158c2ecf20Sopenharmony_ci{ 13168c2ecf20Sopenharmony_ci int do_update = ((int *)data)[1]; 13178c2ecf20Sopenharmony_ci int fd = ((int *)data)[0]; 13188c2ecf20Sopenharmony_ci int i, key, value; 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci for (i = fn; i < MAP_SIZE; i += TASKS) { 13218c2ecf20Sopenharmony_ci key = value = i; 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci if (do_update) { 13248c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, 13258c2ecf20Sopenharmony_ci BPF_NOEXIST) == 0); 13268c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, 13278c2ecf20Sopenharmony_ci BPF_EXIST) == 0); 13288c2ecf20Sopenharmony_ci } else { 13298c2ecf20Sopenharmony_ci assert(bpf_map_delete_elem(fd, &key) == 0); 13308c2ecf20Sopenharmony_ci } 13318c2ecf20Sopenharmony_ci } 13328c2ecf20Sopenharmony_ci} 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_cistatic void test_map_parallel(void) 13358c2ecf20Sopenharmony_ci{ 13368c2ecf20Sopenharmony_ci int i, fd, key = 0, value = 0; 13378c2ecf20Sopenharmony_ci int data[2]; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 13408c2ecf20Sopenharmony_ci MAP_SIZE, map_flags); 13418c2ecf20Sopenharmony_ci if (fd < 0) { 13428c2ecf20Sopenharmony_ci printf("Failed to create map for parallel test '%s'!\n", 13438c2ecf20Sopenharmony_ci strerror(errno)); 13448c2ecf20Sopenharmony_ci exit(1); 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci /* Use the same fd in children to add elements to this map: 13488c2ecf20Sopenharmony_ci * child_0 adds key=0, key=1024, key=2048, ... 13498c2ecf20Sopenharmony_ci * child_1 adds key=1, key=1025, key=2049, ... 13508c2ecf20Sopenharmony_ci * child_1023 adds key=1023, ... 13518c2ecf20Sopenharmony_ci */ 13528c2ecf20Sopenharmony_ci data[0] = fd; 13538c2ecf20Sopenharmony_ci data[1] = DO_UPDATE; 13548c2ecf20Sopenharmony_ci run_parallel(TASKS, test_update_delete, data); 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci /* Check that key=0 is already there. */ 13578c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 && 13588c2ecf20Sopenharmony_ci errno == EEXIST); 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci /* Check that all elements were inserted. */ 13618c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 13628c2ecf20Sopenharmony_ci key = -1; 13638c2ecf20Sopenharmony_ci for (i = 0; i < MAP_SIZE; i++) 13648c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &key) == 0); 13658c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci /* Another check for all elements */ 13688c2ecf20Sopenharmony_ci for (i = 0; i < MAP_SIZE; i++) { 13698c2ecf20Sopenharmony_ci key = MAP_SIZE - i - 1; 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && 13728c2ecf20Sopenharmony_ci value == key); 13738c2ecf20Sopenharmony_ci } 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci /* Now let's delete all elemenets in parallel. */ 13768c2ecf20Sopenharmony_ci data[1] = DO_DELETE; 13778c2ecf20Sopenharmony_ci run_parallel(TASKS, test_update_delete, data); 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci /* Nothing should be left. */ 13808c2ecf20Sopenharmony_ci key = -1; 13818c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT); 13828c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT); 13838c2ecf20Sopenharmony_ci} 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_cistatic void test_map_rdonly(void) 13868c2ecf20Sopenharmony_ci{ 13878c2ecf20Sopenharmony_ci int fd, key = 0, value = 0; 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 13908c2ecf20Sopenharmony_ci MAP_SIZE, map_flags | BPF_F_RDONLY); 13918c2ecf20Sopenharmony_ci if (fd < 0) { 13928c2ecf20Sopenharmony_ci printf("Failed to create map for read only test '%s'!\n", 13938c2ecf20Sopenharmony_ci strerror(errno)); 13948c2ecf20Sopenharmony_ci exit(1); 13958c2ecf20Sopenharmony_ci } 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci key = 1; 13988c2ecf20Sopenharmony_ci value = 1234; 13998c2ecf20Sopenharmony_ci /* Try to insert key=1 element. */ 14008c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 && 14018c2ecf20Sopenharmony_ci errno == EPERM); 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci /* Check that key=1 is not found. */ 14048c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT); 14058c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT); 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci close(fd); 14088c2ecf20Sopenharmony_ci} 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_cistatic void test_map_wronly_hash(void) 14118c2ecf20Sopenharmony_ci{ 14128c2ecf20Sopenharmony_ci int fd, key = 0, value = 0; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value), 14158c2ecf20Sopenharmony_ci MAP_SIZE, map_flags | BPF_F_WRONLY); 14168c2ecf20Sopenharmony_ci if (fd < 0) { 14178c2ecf20Sopenharmony_ci printf("Failed to create map for write only test '%s'!\n", 14188c2ecf20Sopenharmony_ci strerror(errno)); 14198c2ecf20Sopenharmony_ci exit(1); 14208c2ecf20Sopenharmony_ci } 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci key = 1; 14238c2ecf20Sopenharmony_ci value = 1234; 14248c2ecf20Sopenharmony_ci /* Insert key=1 element. */ 14258c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci /* Check that reading elements and keys from the map is not allowed. */ 14288c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM); 14298c2ecf20Sopenharmony_ci assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM); 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci close(fd); 14328c2ecf20Sopenharmony_ci} 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_cistatic void test_map_wronly_stack_or_queue(enum bpf_map_type map_type) 14358c2ecf20Sopenharmony_ci{ 14368c2ecf20Sopenharmony_ci int fd, value = 0; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci assert(map_type == BPF_MAP_TYPE_QUEUE || 14398c2ecf20Sopenharmony_ci map_type == BPF_MAP_TYPE_STACK); 14408c2ecf20Sopenharmony_ci fd = bpf_create_map(map_type, 0, sizeof(value), MAP_SIZE, 14418c2ecf20Sopenharmony_ci map_flags | BPF_F_WRONLY); 14428c2ecf20Sopenharmony_ci /* Stack/Queue maps do not support BPF_F_NO_PREALLOC */ 14438c2ecf20Sopenharmony_ci if (map_flags & BPF_F_NO_PREALLOC) { 14448c2ecf20Sopenharmony_ci assert(fd < 0 && errno == EINVAL); 14458c2ecf20Sopenharmony_ci return; 14468c2ecf20Sopenharmony_ci } 14478c2ecf20Sopenharmony_ci if (fd < 0) { 14488c2ecf20Sopenharmony_ci printf("Failed to create map '%s'!\n", strerror(errno)); 14498c2ecf20Sopenharmony_ci exit(1); 14508c2ecf20Sopenharmony_ci } 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci value = 1234; 14538c2ecf20Sopenharmony_ci assert(bpf_map_update_elem(fd, NULL, &value, BPF_ANY) == 0); 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci /* Peek element should fail */ 14568c2ecf20Sopenharmony_ci assert(bpf_map_lookup_elem(fd, NULL, &value) == -1 && errno == EPERM); 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci /* Pop element should fail */ 14598c2ecf20Sopenharmony_ci assert(bpf_map_lookup_and_delete_elem(fd, NULL, &value) == -1 && 14608c2ecf20Sopenharmony_ci errno == EPERM); 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci close(fd); 14638c2ecf20Sopenharmony_ci} 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_cistatic void test_map_wronly(void) 14668c2ecf20Sopenharmony_ci{ 14678c2ecf20Sopenharmony_ci test_map_wronly_hash(); 14688c2ecf20Sopenharmony_ci test_map_wronly_stack_or_queue(BPF_MAP_TYPE_STACK); 14698c2ecf20Sopenharmony_ci test_map_wronly_stack_or_queue(BPF_MAP_TYPE_QUEUE); 14708c2ecf20Sopenharmony_ci} 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_cistatic void prepare_reuseport_grp(int type, int map_fd, size_t map_elem_size, 14738c2ecf20Sopenharmony_ci __s64 *fds64, __u64 *sk_cookies, 14748c2ecf20Sopenharmony_ci unsigned int n) 14758c2ecf20Sopenharmony_ci{ 14768c2ecf20Sopenharmony_ci socklen_t optlen, addrlen; 14778c2ecf20Sopenharmony_ci struct sockaddr_in6 s6; 14788c2ecf20Sopenharmony_ci const __u32 index0 = 0; 14798c2ecf20Sopenharmony_ci const int optval = 1; 14808c2ecf20Sopenharmony_ci unsigned int i; 14818c2ecf20Sopenharmony_ci u64 sk_cookie; 14828c2ecf20Sopenharmony_ci void *value; 14838c2ecf20Sopenharmony_ci __s32 fd32; 14848c2ecf20Sopenharmony_ci __s64 fd64; 14858c2ecf20Sopenharmony_ci int err; 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci s6.sin6_family = AF_INET6; 14888c2ecf20Sopenharmony_ci s6.sin6_addr = in6addr_any; 14898c2ecf20Sopenharmony_ci s6.sin6_port = 0; 14908c2ecf20Sopenharmony_ci addrlen = sizeof(s6); 14918c2ecf20Sopenharmony_ci optlen = sizeof(sk_cookie); 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci for (i = 0; i < n; i++) { 14948c2ecf20Sopenharmony_ci fd64 = socket(AF_INET6, type, 0); 14958c2ecf20Sopenharmony_ci CHECK(fd64 == -1, "socket()", 14968c2ecf20Sopenharmony_ci "sock_type:%d fd64:%lld errno:%d\n", 14978c2ecf20Sopenharmony_ci type, fd64, errno); 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci err = setsockopt(fd64, SOL_SOCKET, SO_REUSEPORT, 15008c2ecf20Sopenharmony_ci &optval, sizeof(optval)); 15018c2ecf20Sopenharmony_ci CHECK(err == -1, "setsockopt(SO_REUSEPORT)", 15028c2ecf20Sopenharmony_ci "err:%d errno:%d\n", err, errno); 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci /* reuseport_array does not allow unbound sk */ 15058c2ecf20Sopenharmony_ci if (map_elem_size == sizeof(__u64)) 15068c2ecf20Sopenharmony_ci value = &fd64; 15078c2ecf20Sopenharmony_ci else { 15088c2ecf20Sopenharmony_ci assert(map_elem_size == sizeof(__u32)); 15098c2ecf20Sopenharmony_ci fd32 = (__s32)fd64; 15108c2ecf20Sopenharmony_ci value = &fd32; 15118c2ecf20Sopenharmony_ci } 15128c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index0, value, BPF_ANY); 15138c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != EINVAL, 15148c2ecf20Sopenharmony_ci "reuseport array update unbound sk", 15158c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 15168c2ecf20Sopenharmony_ci type, err, errno); 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci err = bind(fd64, (struct sockaddr *)&s6, sizeof(s6)); 15198c2ecf20Sopenharmony_ci CHECK(err == -1, "bind()", 15208c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", type, err, errno); 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci if (i == 0) { 15238c2ecf20Sopenharmony_ci err = getsockname(fd64, (struct sockaddr *)&s6, 15248c2ecf20Sopenharmony_ci &addrlen); 15258c2ecf20Sopenharmony_ci CHECK(err == -1, "getsockname()", 15268c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 15278c2ecf20Sopenharmony_ci type, err, errno); 15288c2ecf20Sopenharmony_ci } 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_ci err = getsockopt(fd64, SOL_SOCKET, SO_COOKIE, &sk_cookie, 15318c2ecf20Sopenharmony_ci &optlen); 15328c2ecf20Sopenharmony_ci CHECK(err == -1, "getsockopt(SO_COOKIE)", 15338c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", type, err, errno); 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci if (type == SOCK_STREAM) { 15368c2ecf20Sopenharmony_ci /* 15378c2ecf20Sopenharmony_ci * reuseport_array does not allow 15388c2ecf20Sopenharmony_ci * non-listening tcp sk. 15398c2ecf20Sopenharmony_ci */ 15408c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index0, value, 15418c2ecf20Sopenharmony_ci BPF_ANY); 15428c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != EINVAL, 15438c2ecf20Sopenharmony_ci "reuseport array update non-listening sk", 15448c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 15458c2ecf20Sopenharmony_ci type, err, errno); 15468c2ecf20Sopenharmony_ci err = listen(fd64, 0); 15478c2ecf20Sopenharmony_ci CHECK(err == -1, "listen()", 15488c2ecf20Sopenharmony_ci "sock_type:%d, err:%d errno:%d\n", 15498c2ecf20Sopenharmony_ci type, err, errno); 15508c2ecf20Sopenharmony_ci } 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci fds64[i] = fd64; 15538c2ecf20Sopenharmony_ci sk_cookies[i] = sk_cookie; 15548c2ecf20Sopenharmony_ci } 15558c2ecf20Sopenharmony_ci} 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_cistatic void test_reuseport_array(void) 15588c2ecf20Sopenharmony_ci{ 15598c2ecf20Sopenharmony_ci#define REUSEPORT_FD_IDX(err, last) ({ (err) ? last : !last; }) 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci const __u32 array_size = 4, index0 = 0, index3 = 3; 15628c2ecf20Sopenharmony_ci int types[2] = { SOCK_STREAM, SOCK_DGRAM }, type; 15638c2ecf20Sopenharmony_ci __u64 grpa_cookies[2], sk_cookie, map_cookie; 15648c2ecf20Sopenharmony_ci __s64 grpa_fds64[2] = { -1, -1 }, fd64 = -1; 15658c2ecf20Sopenharmony_ci const __u32 bad_index = array_size; 15668c2ecf20Sopenharmony_ci int map_fd, err, t, f; 15678c2ecf20Sopenharmony_ci __u32 fds_idx = 0; 15688c2ecf20Sopenharmony_ci int fd; 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, 15718c2ecf20Sopenharmony_ci sizeof(__u32), sizeof(__u64), array_size, 0); 15728c2ecf20Sopenharmony_ci CHECK(map_fd == -1, "reuseport array create", 15738c2ecf20Sopenharmony_ci "map_fd:%d, errno:%d\n", map_fd, errno); 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci /* Test lookup/update/delete with invalid index */ 15768c2ecf20Sopenharmony_ci err = bpf_map_delete_elem(map_fd, &bad_index); 15778c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != E2BIG, "reuseport array del >=max_entries", 15788c2ecf20Sopenharmony_ci "err:%d errno:%d\n", err, errno); 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &bad_index, &fd64, BPF_ANY); 15818c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != E2BIG, 15828c2ecf20Sopenharmony_ci "reuseport array update >=max_entries", 15838c2ecf20Sopenharmony_ci "err:%d errno:%d\n", err, errno); 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci err = bpf_map_lookup_elem(map_fd, &bad_index, &map_cookie); 15868c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != ENOENT, 15878c2ecf20Sopenharmony_ci "reuseport array update >=max_entries", 15888c2ecf20Sopenharmony_ci "err:%d errno:%d\n", err, errno); 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci /* Test lookup/delete non existence elem */ 15918c2ecf20Sopenharmony_ci err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 15928c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != ENOENT, 15938c2ecf20Sopenharmony_ci "reuseport array lookup not-exist elem", 15948c2ecf20Sopenharmony_ci "err:%d errno:%d\n", err, errno); 15958c2ecf20Sopenharmony_ci err = bpf_map_delete_elem(map_fd, &index3); 15968c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != ENOENT, 15978c2ecf20Sopenharmony_ci "reuseport array del not-exist elem", 15988c2ecf20Sopenharmony_ci "err:%d errno:%d\n", err, errno); 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci for (t = 0; t < ARRAY_SIZE(types); t++) { 16018c2ecf20Sopenharmony_ci type = types[t]; 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci prepare_reuseport_grp(type, map_fd, sizeof(__u64), grpa_fds64, 16048c2ecf20Sopenharmony_ci grpa_cookies, ARRAY_SIZE(grpa_fds64)); 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci /* Test BPF_* update flags */ 16078c2ecf20Sopenharmony_ci /* BPF_EXIST failure case */ 16088c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 16098c2ecf20Sopenharmony_ci BPF_EXIST); 16108c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != ENOENT, 16118c2ecf20Sopenharmony_ci "reuseport array update empty elem BPF_EXIST", 16128c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 16138c2ecf20Sopenharmony_ci type, err, errno); 16148c2ecf20Sopenharmony_ci fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci /* BPF_NOEXIST success case */ 16178c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 16188c2ecf20Sopenharmony_ci BPF_NOEXIST); 16198c2ecf20Sopenharmony_ci CHECK(err == -1, 16208c2ecf20Sopenharmony_ci "reuseport array update empty elem BPF_NOEXIST", 16218c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 16228c2ecf20Sopenharmony_ci type, err, errno); 16238c2ecf20Sopenharmony_ci fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci /* BPF_EXIST success case. */ 16268c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 16278c2ecf20Sopenharmony_ci BPF_EXIST); 16288c2ecf20Sopenharmony_ci CHECK(err == -1, 16298c2ecf20Sopenharmony_ci "reuseport array update same elem BPF_EXIST", 16308c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", type, err, errno); 16318c2ecf20Sopenharmony_ci fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci /* BPF_NOEXIST failure case */ 16348c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 16358c2ecf20Sopenharmony_ci BPF_NOEXIST); 16368c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != EEXIST, 16378c2ecf20Sopenharmony_ci "reuseport array update non-empty elem BPF_NOEXIST", 16388c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 16398c2ecf20Sopenharmony_ci type, err, errno); 16408c2ecf20Sopenharmony_ci fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci /* BPF_ANY case (always succeed) */ 16438c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 16448c2ecf20Sopenharmony_ci BPF_ANY); 16458c2ecf20Sopenharmony_ci CHECK(err == -1, 16468c2ecf20Sopenharmony_ci "reuseport array update same sk with BPF_ANY", 16478c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", type, err, errno); 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci fd64 = grpa_fds64[fds_idx]; 16508c2ecf20Sopenharmony_ci sk_cookie = grpa_cookies[fds_idx]; 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci /* The same sk cannot be added to reuseport_array twice */ 16538c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_ANY); 16548c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != EBUSY, 16558c2ecf20Sopenharmony_ci "reuseport array update same sk with same index", 16568c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 16578c2ecf20Sopenharmony_ci type, err, errno); 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index0, &fd64, BPF_ANY); 16608c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != EBUSY, 16618c2ecf20Sopenharmony_ci "reuseport array update same sk with different index", 16628c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 16638c2ecf20Sopenharmony_ci type, err, errno); 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci /* Test delete elem */ 16668c2ecf20Sopenharmony_ci err = bpf_map_delete_elem(map_fd, &index3); 16678c2ecf20Sopenharmony_ci CHECK(err == -1, "reuseport array delete sk", 16688c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 16698c2ecf20Sopenharmony_ci type, err, errno); 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ci /* Add it back with BPF_NOEXIST */ 16728c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST); 16738c2ecf20Sopenharmony_ci CHECK(err == -1, 16748c2ecf20Sopenharmony_ci "reuseport array re-add with BPF_NOEXIST after del", 16758c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", type, err, errno); 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci /* Test cookie */ 16788c2ecf20Sopenharmony_ci err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 16798c2ecf20Sopenharmony_ci CHECK(err == -1 || sk_cookie != map_cookie, 16808c2ecf20Sopenharmony_ci "reuseport array lookup re-added sk", 16818c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d sk_cookie:0x%llx map_cookie:0x%llxn", 16828c2ecf20Sopenharmony_ci type, err, errno, sk_cookie, map_cookie); 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci /* Test elem removed by close() */ 16858c2ecf20Sopenharmony_ci for (f = 0; f < ARRAY_SIZE(grpa_fds64); f++) 16868c2ecf20Sopenharmony_ci close(grpa_fds64[f]); 16878c2ecf20Sopenharmony_ci err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 16888c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != ENOENT, 16898c2ecf20Sopenharmony_ci "reuseport array lookup after close()", 16908c2ecf20Sopenharmony_ci "sock_type:%d err:%d errno:%d\n", 16918c2ecf20Sopenharmony_ci type, err, errno); 16928c2ecf20Sopenharmony_ci } 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci /* Test SOCK_RAW */ 16958c2ecf20Sopenharmony_ci fd64 = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP); 16968c2ecf20Sopenharmony_ci CHECK(fd64 == -1, "socket(SOCK_RAW)", "err:%d errno:%d\n", 16978c2ecf20Sopenharmony_ci err, errno); 16988c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST); 16998c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != ENOTSUPP, "reuseport array update SOCK_RAW", 17008c2ecf20Sopenharmony_ci "err:%d errno:%d\n", err, errno); 17018c2ecf20Sopenharmony_ci close(fd64); 17028c2ecf20Sopenharmony_ci 17038c2ecf20Sopenharmony_ci /* Close the 64 bit value map */ 17048c2ecf20Sopenharmony_ci close(map_fd); 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci /* Test 32 bit fd */ 17078c2ecf20Sopenharmony_ci map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, 17088c2ecf20Sopenharmony_ci sizeof(__u32), sizeof(__u32), array_size, 0); 17098c2ecf20Sopenharmony_ci CHECK(map_fd == -1, "reuseport array create", 17108c2ecf20Sopenharmony_ci "map_fd:%d, errno:%d\n", map_fd, errno); 17118c2ecf20Sopenharmony_ci prepare_reuseport_grp(SOCK_STREAM, map_fd, sizeof(__u32), &fd64, 17128c2ecf20Sopenharmony_ci &sk_cookie, 1); 17138c2ecf20Sopenharmony_ci fd = fd64; 17148c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, &index3, &fd, BPF_NOEXIST); 17158c2ecf20Sopenharmony_ci CHECK(err == -1, "reuseport array update 32 bit fd", 17168c2ecf20Sopenharmony_ci "err:%d errno:%d\n", err, errno); 17178c2ecf20Sopenharmony_ci err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 17188c2ecf20Sopenharmony_ci CHECK(err != -1 || errno != ENOSPC, 17198c2ecf20Sopenharmony_ci "reuseport array lookup 32 bit fd", 17208c2ecf20Sopenharmony_ci "err:%d errno:%d\n", err, errno); 17218c2ecf20Sopenharmony_ci close(fd); 17228c2ecf20Sopenharmony_ci close(map_fd); 17238c2ecf20Sopenharmony_ci} 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_cistatic void run_all_tests(void) 17268c2ecf20Sopenharmony_ci{ 17278c2ecf20Sopenharmony_ci test_hashmap(0, NULL); 17288c2ecf20Sopenharmony_ci test_hashmap_percpu(0, NULL); 17298c2ecf20Sopenharmony_ci test_hashmap_walk(0, NULL); 17308c2ecf20Sopenharmony_ci test_hashmap_zero_seed(); 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci test_arraymap(0, NULL); 17338c2ecf20Sopenharmony_ci test_arraymap_percpu(0, NULL); 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci test_arraymap_percpu_many_keys(); 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci test_devmap(0, NULL); 17388c2ecf20Sopenharmony_ci test_devmap_hash(0, NULL); 17398c2ecf20Sopenharmony_ci test_sockmap(0, NULL); 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci test_map_large(); 17428c2ecf20Sopenharmony_ci test_map_parallel(); 17438c2ecf20Sopenharmony_ci test_map_stress(); 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci test_map_rdonly(); 17468c2ecf20Sopenharmony_ci test_map_wronly(); 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci test_reuseport_array(); 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci test_queuemap(0, NULL); 17518c2ecf20Sopenharmony_ci test_stackmap(0, NULL); 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci test_map_in_map(); 17548c2ecf20Sopenharmony_ci} 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci#define DEFINE_TEST(name) extern void test_##name(void); 17578c2ecf20Sopenharmony_ci#include <map_tests/tests.h> 17588c2ecf20Sopenharmony_ci#undef DEFINE_TEST 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ciint main(void) 17618c2ecf20Sopenharmony_ci{ 17628c2ecf20Sopenharmony_ci srand(time(NULL)); 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci map_flags = 0; 17658c2ecf20Sopenharmony_ci run_all_tests(); 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci map_flags = BPF_F_NO_PREALLOC; 17688c2ecf20Sopenharmony_ci run_all_tests(); 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci#define DEFINE_TEST(name) test_##name(); 17718c2ecf20Sopenharmony_ci#include <map_tests/tests.h> 17728c2ecf20Sopenharmony_ci#undef DEFINE_TEST 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci printf("test_maps: OK, %d SKIPPED\n", skips); 17758c2ecf20Sopenharmony_ci return 0; 17768c2ecf20Sopenharmony_ci} 1777