Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | // SPDX-License-Identifier: GPL-2.0 #include <arpa/inet.h> #include <linux/bpf.h> #include <netinet/in.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <bpf/bpf.h> #include <bpf/libbpf.h> #include <test_maps.h> struct test_lpm_key { __u32 prefix; struct in_addr ipv4; }; static void map_batch_update(int map_fd, __u32 max_entries, struct test_lpm_key *keys, int *values) { __u32 i; int err; char buff[16] = { 0 }; DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts, .elem_flags = 0, .flags = 0, ); for (i = 0; i < max_entries; i++) { keys[i].prefix = 32; snprintf(buff, 16, "192.168.1.%d", i + 1); inet_pton(AF_INET, buff, &keys[i].ipv4); values[i] = i + 1; } err = bpf_map_update_batch(map_fd, keys, values, &max_entries, &opts); CHECK(err, "bpf_map_update_batch()", "error:%s\n", strerror(errno)); } static void map_batch_verify(int *visited, __u32 max_entries, struct test_lpm_key *keys, int *values) { char buff[16] = { 0 }; int lower_byte = 0; __u32 i; memset(visited, 0, max_entries * sizeof(*visited)); for (i = 0; i < max_entries; i++) { inet_ntop(AF_INET, &keys[i].ipv4, buff, 32); CHECK(sscanf(buff, "192.168.1.%d", &lower_byte) == EOF, "sscanf()", "error: i %d\n", i); CHECK(lower_byte != values[i], "key/value checking", "error: i %d key %s value %d\n", i, buff, values[i]); visited[i] = 1; } for (i = 0; i < max_entries; i++) { CHECK(visited[i] != 1, "visited checking", "error: keys array at index %d missing\n", i); } } void test_lpm_trie_map_batch_ops(void) { LIBBPF_OPTS(bpf_map_create_opts, create_opts, .map_flags = BPF_F_NO_PREALLOC); struct test_lpm_key *keys, key; int map_fd, *values, *visited; __u32 step, count, total, total_success; const __u32 max_entries = 10; __u64 batch = 0; int err; DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts, .elem_flags = 0, .flags = 0, ); map_fd = bpf_map_create(BPF_MAP_TYPE_LPM_TRIE, "lpm_trie_map", sizeof(struct test_lpm_key), sizeof(int), max_entries, &create_opts); CHECK(map_fd == -1, "bpf_map_create()", "error:%s\n", strerror(errno)); keys = malloc(max_entries * sizeof(struct test_lpm_key)); values = malloc(max_entries * sizeof(int)); visited = malloc(max_entries * sizeof(int)); CHECK(!keys || !values || !visited, "malloc()", "error:%s\n", strerror(errno)); total_success = 0; for (step = 1; step < max_entries; step++) { map_batch_update(map_fd, max_entries, keys, values); map_batch_verify(visited, max_entries, keys, values); memset(keys, 0, max_entries * sizeof(*keys)); memset(values, 0, max_entries * sizeof(*values)); batch = 0; total = 0; /* iteratively lookup/delete elements with 'step' * elements each. */ count = step; while (true) { err = bpf_map_lookup_batch(map_fd, total ? &batch : NULL, &batch, keys + total, values + total, &count, &opts); CHECK((err && errno != ENOENT), "lookup with steps", "error: %s\n", strerror(errno)); total += count; if (err) break; } CHECK(total != max_entries, "lookup with steps", "total = %u, max_entries = %u\n", total, max_entries); map_batch_verify(visited, max_entries, keys, values); total = 0; count = step; while (total < max_entries) { if (max_entries - total < step) count = max_entries - total; err = bpf_map_delete_batch(map_fd, keys + total, &count, &opts); CHECK((err && errno != ENOENT), "delete batch", "error: %s\n", strerror(errno)); total += count; if (err) break; } CHECK(total != max_entries, "delete with steps", "total = %u, max_entries = %u\n", total, max_entries); /* check map is empty, errono == ENOENT */ err = bpf_map_get_next_key(map_fd, NULL, &key); CHECK(!err || errno != ENOENT, "bpf_map_get_next_key()", "error: %s\n", strerror(errno)); total_success++; } CHECK(total_success == 0, "check total_success", "unexpected failure\n"); printf("%s:PASS\n", __func__); free(keys); free(values); free(visited); close(map_fd); } |