1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <stdio.h> 4 #include <errno.h> 5 #include <string.h> 6 7 #include <bpf/bpf.h> 8 #include <bpf/libbpf.h> 9 10 #include <test_maps.h> 11 12 static void map_batch_update(int map_fd, __u32 max_entries, int *keys, 13 int *values) 14 { 15 int i, err; 16 DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts, 17 .elem_flags = 0, 18 .flags = 0, 19 ); 20 21 for (i = 0; i < max_entries; i++) { 22 keys[i] = i; 23 values[i] = i + 1; 24 } 25 26 err = bpf_map_update_batch(map_fd, keys, values, &max_entries, &opts); 27 CHECK(err, "bpf_map_update_batch()", "error:%s\n", strerror(errno)); 28 } 29 30 static void map_batch_verify(int *visited, __u32 max_entries, 31 int *keys, int *values) 32 { 33 int i; 34 35 memset(visited, 0, max_entries * sizeof(*visited)); 36 for (i = 0; i < max_entries; i++) { 37 CHECK(keys[i] + 1 != values[i], "key/value checking", 38 "error: i %d key %d value %d\n", i, keys[i], values[i]); 39 visited[i] = 1; 40 } 41 for (i = 0; i < max_entries; i++) { 42 CHECK(visited[i] != 1, "visited checking", 43 "error: keys array at index %d missing\n", i); 44 } 45 } 46 47 void test_array_map_batch_ops(void) 48 { 49 struct bpf_create_map_attr xattr = { 50 .name = "array_map", 51 .map_type = BPF_MAP_TYPE_ARRAY, 52 .key_size = sizeof(int), 53 .value_size = sizeof(int), 54 }; 55 int map_fd, *keys, *values, *visited; 56 __u32 count, total, total_success; 57 const __u32 max_entries = 10; 58 bool nospace_err; 59 __u64 batch = 0; 60 int err, step; 61 DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts, 62 .elem_flags = 0, 63 .flags = 0, 64 ); 65 66 xattr.max_entries = max_entries; 67 map_fd = bpf_create_map_xattr(&xattr); 68 CHECK(map_fd == -1, 69 "bpf_create_map_xattr()", "error:%s\n", strerror(errno)); 70 71 keys = malloc(max_entries * sizeof(int)); 72 values = malloc(max_entries * sizeof(int)); 73 visited = malloc(max_entries * sizeof(int)); 74 CHECK(!keys || !values || !visited, "malloc()", "error:%s\n", 75 strerror(errno)); 76 77 /* populate elements to the map */ 78 map_batch_update(map_fd, max_entries, keys, values); 79 80 /* test 1: lookup in a loop with various steps. */ 81 total_success = 0; 82 for (step = 1; step < max_entries; step++) { 83 map_batch_update(map_fd, max_entries, keys, values); 84 map_batch_verify(visited, max_entries, keys, values); 85 memset(keys, 0, max_entries * sizeof(*keys)); 86 memset(values, 0, max_entries * sizeof(*values)); 87 batch = 0; 88 total = 0; 89 /* iteratively lookup/delete elements with 'step' 90 * elements each. 91 */ 92 count = step; 93 nospace_err = false; 94 while (true) { 95 err = bpf_map_lookup_batch(map_fd, 96 total ? &batch : NULL, &batch, 97 keys + total, 98 values + total, 99 &count, &opts); 100 101 CHECK((err && errno != ENOENT), "lookup with steps", 102 "error: %s\n", strerror(errno)); 103 104 total += count; 105 if (err) 106 break; 107 108 } 109 110 if (nospace_err == true) 111 continue; 112 113 CHECK(total != max_entries, "lookup with steps", 114 "total = %u, max_entries = %u\n", total, max_entries); 115 116 map_batch_verify(visited, max_entries, keys, values); 117 118 total_success++; 119 } 120 121 CHECK(total_success == 0, "check total_success", 122 "unexpected failure\n"); 123 124 printf("%s:PASS\n", __func__); 125 126 free(keys); 127 free(values); 128 free(visited); 129 } 130