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 __u64 batch = 0; 59 int err, step; 60 DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts, 61 .elem_flags = 0, 62 .flags = 0, 63 ); 64 65 xattr.max_entries = max_entries; 66 map_fd = bpf_create_map_xattr(&xattr); 67 CHECK(map_fd == -1, 68 "bpf_create_map_xattr()", "error:%s\n", strerror(errno)); 69 70 keys = malloc(max_entries * sizeof(int)); 71 values = malloc(max_entries * sizeof(int)); 72 visited = malloc(max_entries * sizeof(int)); 73 CHECK(!keys || !values || !visited, "malloc()", "error:%s\n", 74 strerror(errno)); 75 76 /* populate elements to the map */ 77 map_batch_update(map_fd, max_entries, keys, values); 78 79 /* test 1: lookup in a loop with various steps. */ 80 total_success = 0; 81 for (step = 1; step < max_entries; step++) { 82 map_batch_update(map_fd, max_entries, keys, values); 83 map_batch_verify(visited, max_entries, keys, values); 84 memset(keys, 0, max_entries * sizeof(*keys)); 85 memset(values, 0, max_entries * sizeof(*values)); 86 batch = 0; 87 total = 0; 88 /* iteratively lookup/delete elements with 'step' 89 * elements each. 90 */ 91 count = step; 92 while (true) { 93 err = bpf_map_lookup_batch(map_fd, 94 total ? &batch : NULL, &batch, 95 keys + total, 96 values + total, 97 &count, &opts); 98 99 CHECK((err && errno != ENOENT), "lookup with steps", 100 "error: %s\n", strerror(errno)); 101 102 total += count; 103 if (err) 104 break; 105 106 } 107 108 CHECK(total != max_entries, "lookup with steps", 109 "total = %u, max_entries = %u\n", total, max_entries); 110 111 map_batch_verify(visited, max_entries, keys, values); 112 113 total_success++; 114 } 115 116 CHECK(total_success == 0, "check total_success", 117 "unexpected failure\n"); 118 119 printf("%s:PASS\n", __func__); 120 121 free(keys); 122 free(values); 123 free(visited); 124 } 125