Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include <stdio.h>
0004 #include <errno.h>
0005 #include <string.h>
0006 
0007 #include <bpf/bpf.h>
0008 #include <bpf/libbpf.h>
0009 
0010 #include <test_maps.h>
0011 
0012 static int nr_cpus;
0013 
0014 static void map_batch_update(int map_fd, __u32 max_entries, int *keys,
0015                  __s64 *values, bool is_pcpu)
0016 {
0017     int i, j, err;
0018     int cpu_offset = 0;
0019     DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
0020         .elem_flags = 0,
0021         .flags = 0,
0022     );
0023 
0024     for (i = 0; i < max_entries; i++) {
0025         keys[i] = i;
0026         if (is_pcpu) {
0027             cpu_offset = i * nr_cpus;
0028             for (j = 0; j < nr_cpus; j++)
0029                 (values + cpu_offset)[j] = i + 1 + j;
0030         } else {
0031             values[i] = i + 1;
0032         }
0033     }
0034 
0035     err = bpf_map_update_batch(map_fd, keys, values, &max_entries, &opts);
0036     CHECK(err, "bpf_map_update_batch()", "error:%s\n", strerror(errno));
0037 }
0038 
0039 static void map_batch_verify(int *visited, __u32 max_entries, int *keys,
0040                  __s64 *values, bool is_pcpu)
0041 {
0042     int i, j;
0043     int cpu_offset = 0;
0044 
0045     memset(visited, 0, max_entries * sizeof(*visited));
0046     for (i = 0; i < max_entries; i++) {
0047         if (is_pcpu) {
0048             cpu_offset = i * nr_cpus;
0049             for (j = 0; j < nr_cpus; j++) {
0050                 __s64 value = (values + cpu_offset)[j];
0051                 CHECK(keys[i] + j + 1 != value,
0052                       "key/value checking",
0053                       "error: i %d j %d key %d value %lld\n", i,
0054                       j, keys[i], value);
0055             }
0056         } else {
0057             CHECK(keys[i] + 1 != values[i], "key/value checking",
0058                   "error: i %d key %d value %lld\n", i, keys[i],
0059                   values[i]);
0060         }
0061         visited[i] = 1;
0062     }
0063     for (i = 0; i < max_entries; i++) {
0064         CHECK(visited[i] != 1, "visited checking",
0065               "error: keys array at index %d missing\n", i);
0066     }
0067 }
0068 
0069 static void __test_map_lookup_and_update_batch(bool is_pcpu)
0070 {
0071     int map_fd, *keys, *visited;
0072     __u32 count, total, total_success;
0073     const __u32 max_entries = 10;
0074     __u64 batch = 0;
0075     int err, step, value_size;
0076     void *values;
0077     DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
0078         .elem_flags = 0,
0079         .flags = 0,
0080     );
0081 
0082     map_fd = bpf_map_create(is_pcpu ? BPF_MAP_TYPE_PERCPU_ARRAY : BPF_MAP_TYPE_ARRAY,
0083                 "array_map", sizeof(int), sizeof(__s64), max_entries, NULL);
0084     CHECK(map_fd == -1,
0085           "bpf_map_create()", "error:%s\n", strerror(errno));
0086 
0087     value_size = sizeof(__s64);
0088     if (is_pcpu)
0089         value_size *= nr_cpus;
0090 
0091     keys = calloc(max_entries, sizeof(*keys));
0092     values = calloc(max_entries, value_size);
0093     visited = calloc(max_entries, sizeof(*visited));
0094     CHECK(!keys || !values || !visited, "malloc()", "error:%s\n",
0095           strerror(errno));
0096 
0097     /* test 1: lookup in a loop with various steps. */
0098     total_success = 0;
0099     for (step = 1; step < max_entries; step++) {
0100         map_batch_update(map_fd, max_entries, keys, values, is_pcpu);
0101         map_batch_verify(visited, max_entries, keys, values, is_pcpu);
0102         memset(keys, 0, max_entries * sizeof(*keys));
0103         memset(values, 0, max_entries * value_size);
0104         batch = 0;
0105         total = 0;
0106         /* iteratively lookup/delete elements with 'step'
0107          * elements each.
0108          */
0109         count = step;
0110         while (true) {
0111             err = bpf_map_lookup_batch(map_fd,
0112                            total ? &batch : NULL,
0113                            &batch, keys + total,
0114                            values + total * value_size,
0115                            &count, &opts);
0116 
0117             CHECK((err && errno != ENOENT), "lookup with steps",
0118                   "error: %s\n", strerror(errno));
0119 
0120             total += count;
0121             if (err)
0122                 break;
0123 
0124         }
0125 
0126         CHECK(total != max_entries, "lookup with steps",
0127               "total = %u, max_entries = %u\n", total, max_entries);
0128 
0129         map_batch_verify(visited, max_entries, keys, values, is_pcpu);
0130 
0131         total_success++;
0132     }
0133 
0134     CHECK(total_success == 0, "check total_success",
0135           "unexpected failure\n");
0136 
0137     free(keys);
0138     free(values);
0139     free(visited);
0140 }
0141 
0142 static void array_map_batch_ops(void)
0143 {
0144     __test_map_lookup_and_update_batch(false);
0145     printf("test_%s:PASS\n", __func__);
0146 }
0147 
0148 static void array_percpu_map_batch_ops(void)
0149 {
0150     __test_map_lookup_and_update_batch(true);
0151     printf("test_%s:PASS\n", __func__);
0152 }
0153 
0154 void test_array_map_batch_ops(void)
0155 {
0156     nr_cpus = libbpf_num_possible_cpus();
0157 
0158     CHECK(nr_cpus < 0, "nr_cpus checking",
0159           "error: get possible cpus failed");
0160 
0161     array_map_batch_ops();
0162     array_percpu_map_batch_ops();
0163 }