cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lpm_trie_map_batch_ops.c (4092B)


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