0001
0002
0003 #include <arpa/inet.h>
0004 #include <linux/bpf.h>
0005 #include <netinet/in.h>
0006 #include <stdio.h>
0007 #include <errno.h>
0008 #include <string.h>
0009 #include <stdlib.h>
0010
0011 #include <bpf/bpf.h>
0012 #include <bpf/libbpf.h>
0013
0014 #include <test_maps.h>
0015
0016 struct test_lpm_key {
0017 __u32 prefix;
0018 struct in_addr ipv4;
0019 };
0020
0021 static void map_batch_update(int map_fd, __u32 max_entries,
0022 struct test_lpm_key *keys, int *values)
0023 {
0024 __u32 i;
0025 int err;
0026 char buff[16] = { 0 };
0027 DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
0028 .elem_flags = 0,
0029 .flags = 0,
0030 );
0031
0032 for (i = 0; i < max_entries; i++) {
0033 keys[i].prefix = 32;
0034 snprintf(buff, 16, "192.168.1.%d", i + 1);
0035 inet_pton(AF_INET, buff, &keys[i].ipv4);
0036 values[i] = i + 1;
0037 }
0038
0039 err = bpf_map_update_batch(map_fd, keys, values, &max_entries, &opts);
0040 CHECK(err, "bpf_map_update_batch()", "error:%s\n", strerror(errno));
0041 }
0042
0043 static void map_batch_verify(int *visited, __u32 max_entries,
0044 struct test_lpm_key *keys, int *values)
0045 {
0046 char buff[16] = { 0 };
0047 int lower_byte = 0;
0048 __u32 i;
0049
0050 memset(visited, 0, max_entries * sizeof(*visited));
0051 for (i = 0; i < max_entries; i++) {
0052 inet_ntop(AF_INET, &keys[i].ipv4, buff, 32);
0053 CHECK(sscanf(buff, "192.168.1.%d", &lower_byte) == EOF,
0054 "sscanf()", "error: i %d\n", i);
0055 CHECK(lower_byte != values[i], "key/value checking",
0056 "error: i %d key %s value %d\n", i, buff, values[i]);
0057 visited[i] = 1;
0058 }
0059 for (i = 0; i < max_entries; i++) {
0060 CHECK(visited[i] != 1, "visited checking",
0061 "error: keys array at index %d missing\n", i);
0062 }
0063 }
0064
0065 void test_lpm_trie_map_batch_ops(void)
0066 {
0067 LIBBPF_OPTS(bpf_map_create_opts, create_opts, .map_flags = BPF_F_NO_PREALLOC);
0068 struct test_lpm_key *keys, key;
0069 int map_fd, *values, *visited;
0070 __u32 step, count, total, total_success;
0071 const __u32 max_entries = 10;
0072 __u64 batch = 0;
0073 int err;
0074 DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
0075 .elem_flags = 0,
0076 .flags = 0,
0077 );
0078
0079 map_fd = bpf_map_create(BPF_MAP_TYPE_LPM_TRIE, "lpm_trie_map",
0080 sizeof(struct test_lpm_key), sizeof(int),
0081 max_entries, &create_opts);
0082 CHECK(map_fd == -1, "bpf_map_create()", "error:%s\n",
0083 strerror(errno));
0084
0085 keys = malloc(max_entries * sizeof(struct test_lpm_key));
0086 values = malloc(max_entries * sizeof(int));
0087 visited = malloc(max_entries * sizeof(int));
0088 CHECK(!keys || !values || !visited, "malloc()", "error:%s\n",
0089 strerror(errno));
0090
0091 total_success = 0;
0092 for (step = 1; step < max_entries; step++) {
0093 map_batch_update(map_fd, max_entries, keys, values);
0094 map_batch_verify(visited, max_entries, keys, values);
0095 memset(keys, 0, max_entries * sizeof(*keys));
0096 memset(values, 0, max_entries * sizeof(*values));
0097 batch = 0;
0098 total = 0;
0099
0100
0101
0102 count = step;
0103 while (true) {
0104 err = bpf_map_lookup_batch(map_fd,
0105 total ? &batch : NULL, &batch,
0106 keys + total, values + total, &count, &opts);
0107
0108 CHECK((err && errno != ENOENT), "lookup with steps",
0109 "error: %s\n", strerror(errno));
0110
0111 total += count;
0112 if (err)
0113 break;
0114 }
0115
0116 CHECK(total != max_entries, "lookup with steps",
0117 "total = %u, max_entries = %u\n", total, max_entries);
0118
0119 map_batch_verify(visited, max_entries, keys, values);
0120
0121 total = 0;
0122 count = step;
0123 while (total < max_entries) {
0124 if (max_entries - total < step)
0125 count = max_entries - total;
0126 err = bpf_map_delete_batch(map_fd, keys + total, &count,
0127 &opts);
0128 CHECK((err && errno != ENOENT), "delete batch",
0129 "error: %s\n", strerror(errno));
0130 total += count;
0131 if (err)
0132 break;
0133 }
0134 CHECK(total != max_entries, "delete with steps",
0135 "total = %u, max_entries = %u\n", total, max_entries);
0136
0137
0138 err = bpf_map_get_next_key(map_fd, NULL, &key);
0139 CHECK(!err || errno != ENOENT, "bpf_map_get_next_key()",
0140 "error: %s\n", strerror(errno));
0141
0142 total_success++;
0143 }
0144
0145 CHECK(total_success == 0, "check total_success",
0146 "unexpected failure\n");
0147
0148 printf("%s:PASS\n", __func__);
0149
0150 free(keys);
0151 free(values);
0152 free(visited);
0153 }