1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2019 Richard Palethorpe <rpalethorpe@suse.com> 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * Trivial Extended Berkeley Packet Filter (eBPF) test. 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * Sanity check creating and updating maps. 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci/* 10f08c3bdfSopenharmony_ci * If test is executed in a loop and limit for locked memory (ulimit -l) is 11f08c3bdfSopenharmony_ci * too low bpf() call can fail with EPERM due to deffered freeing. 12f08c3bdfSopenharmony_ci */ 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci#include <limits.h> 15f08c3bdfSopenharmony_ci#include <string.h> 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_ci#include "config.h" 18f08c3bdfSopenharmony_ci#include "tst_test.h" 19f08c3bdfSopenharmony_ci#include "bpf_common.h" 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci#define VAL_SZ 1024 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_cistatic void *key4; 24f08c3bdfSopenharmony_cistatic void *key8; 25f08c3bdfSopenharmony_cistatic char *val_set; 26f08c3bdfSopenharmony_cistatic char *val_get; 27f08c3bdfSopenharmony_cistatic union bpf_attr *attr; 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_cistruct map_type { 30f08c3bdfSopenharmony_ci uint32_t id; 31f08c3bdfSopenharmony_ci char *name; 32f08c3bdfSopenharmony_ci int key_size; 33f08c3bdfSopenharmony_ci void **key; 34f08c3bdfSopenharmony_ci}; 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_cistatic const struct map_type map_types[] = { 37f08c3bdfSopenharmony_ci {BPF_MAP_TYPE_HASH, "hash", 8, &key8}, 38f08c3bdfSopenharmony_ci {BPF_MAP_TYPE_ARRAY, "array", 4, &key4} 39f08c3bdfSopenharmony_ci}; 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_civoid run(unsigned int n) 42f08c3bdfSopenharmony_ci{ 43f08c3bdfSopenharmony_ci int fd, i; 44f08c3bdfSopenharmony_ci void *key = *map_types[n].key; 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_ci memset(attr, 0, sizeof(*attr)); 47f08c3bdfSopenharmony_ci attr->map_type = map_types[n].id; 48f08c3bdfSopenharmony_ci attr->key_size = map_types[n].key_size; 49f08c3bdfSopenharmony_ci attr->value_size = VAL_SZ; 50f08c3bdfSopenharmony_ci attr->max_entries = 1; 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci fd = bpf_map_create(attr); 53f08c3bdfSopenharmony_ci tst_res(TPASS, "Created %s map", map_types[n].name); 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci memset(attr, 0, sizeof(*attr)); 56f08c3bdfSopenharmony_ci attr->map_fd = fd; 57f08c3bdfSopenharmony_ci attr->key = ptr_to_u64(key); 58f08c3bdfSopenharmony_ci attr->value = ptr_to_u64(val_get); 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci memset(val_get, 'x', VAL_SZ); 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci TEST(bpf(BPF_MAP_LOOKUP_ELEM, attr, sizeof(*attr))); 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci switch (map_types[n].id) { 65f08c3bdfSopenharmony_ci case BPF_MAP_TYPE_HASH: 66f08c3bdfSopenharmony_ci if (TST_RET != -1 || TST_ERR != ENOENT) { 67f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 68f08c3bdfSopenharmony_ci "Empty hash map lookup should fail with ENOENT"); 69f08c3bdfSopenharmony_ci } else { 70f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "Empty hash map lookup"); 71f08c3bdfSopenharmony_ci } 72f08c3bdfSopenharmony_ci break; 73f08c3bdfSopenharmony_ci case BPF_MAP_TYPE_ARRAY: 74f08c3bdfSopenharmony_ci if (TST_RET != -1) { 75f08c3bdfSopenharmony_ci for (i = 0; i < VAL_SZ; i++) { 76f08c3bdfSopenharmony_ci if (val_get[i] != 0) { 77f08c3bdfSopenharmony_ci tst_res(TFAIL, 78f08c3bdfSopenharmony_ci "Preallocated array map val not zero"); 79f08c3bdfSopenharmony_ci break; 80f08c3bdfSopenharmony_ci } 81f08c3bdfSopenharmony_ci } 82f08c3bdfSopenharmony_ci if (i < VAL_SZ) 83f08c3bdfSopenharmony_ci tst_res(TPASS, "Preallocated array map lookup"); 84f08c3bdfSopenharmony_ci } else { 85f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "Prellocated array map lookup"); 86f08c3bdfSopenharmony_ci } 87f08c3bdfSopenharmony_ci break; 88f08c3bdfSopenharmony_ci } 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci memset(attr, 0, sizeof(*attr)); 91f08c3bdfSopenharmony_ci attr->map_fd = fd; 92f08c3bdfSopenharmony_ci attr->key = ptr_to_u64(key); 93f08c3bdfSopenharmony_ci attr->value = ptr_to_u64(val_set); 94f08c3bdfSopenharmony_ci attr->flags = BPF_ANY; 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci TEST(bpf(BPF_MAP_UPDATE_ELEM, attr, sizeof(*attr))); 97f08c3bdfSopenharmony_ci if (TST_RET == -1) { 98f08c3bdfSopenharmony_ci tst_brk(TFAIL | TTERRNO, 99f08c3bdfSopenharmony_ci "Update %s map element", 100f08c3bdfSopenharmony_ci map_types[n].name); 101f08c3bdfSopenharmony_ci } else { 102f08c3bdfSopenharmony_ci tst_res(TPASS, 103f08c3bdfSopenharmony_ci "Update %s map element", 104f08c3bdfSopenharmony_ci map_types[n].name); 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci memset(attr, 0, sizeof(*attr)); 108f08c3bdfSopenharmony_ci attr->map_fd = fd; 109f08c3bdfSopenharmony_ci attr->key = ptr_to_u64(key); 110f08c3bdfSopenharmony_ci attr->value = ptr_to_u64(val_get); 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci TEST(bpf(BPF_MAP_LOOKUP_ELEM, attr, sizeof(*attr))); 113f08c3bdfSopenharmony_ci if (TST_RET == -1) { 114f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 115f08c3bdfSopenharmony_ci "%s map lookup missing", 116f08c3bdfSopenharmony_ci map_types[n].name); 117f08c3bdfSopenharmony_ci } else if (memcmp(val_set, val_get, (size_t) VAL_SZ)) { 118f08c3bdfSopenharmony_ci tst_res(TFAIL, 119f08c3bdfSopenharmony_ci "%s map lookup returned different value", 120f08c3bdfSopenharmony_ci map_types[n].name); 121f08c3bdfSopenharmony_ci } else { 122f08c3bdfSopenharmony_ci tst_res(TPASS, "%s map lookup", map_types[n].name); 123f08c3bdfSopenharmony_ci } 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 126f08c3bdfSopenharmony_ci} 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_cistatic void setup(void) 129f08c3bdfSopenharmony_ci{ 130f08c3bdfSopenharmony_ci unsigned int i; 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci rlimit_bump_memlock(); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci memcpy(key8, "12345678", 8); 135f08c3bdfSopenharmony_ci memset(key4, 0, 4); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci for (i = 0; i < VAL_SZ; i++) 138f08c3bdfSopenharmony_ci val_set[i] = i % 256; 139f08c3bdfSopenharmony_ci} 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_cistatic struct tst_test test = { 142f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(map_types), 143f08c3bdfSopenharmony_ci .test = run, 144f08c3bdfSopenharmony_ci .setup = setup, 145f08c3bdfSopenharmony_ci .min_kver = "3.19", 146f08c3bdfSopenharmony_ci .bufs = (struct tst_buffers []) { 147f08c3bdfSopenharmony_ci {&key4, .size = 4}, 148f08c3bdfSopenharmony_ci {&key8, .size = 8}, 149f08c3bdfSopenharmony_ci {&val_set, .size = VAL_SZ}, 150f08c3bdfSopenharmony_ci {&val_get, .size = VAL_SZ}, 151f08c3bdfSopenharmony_ci {&attr, .size = sizeof(*attr)}, 152f08c3bdfSopenharmony_ci {}, 153f08c3bdfSopenharmony_ci }, 154f08c3bdfSopenharmony_ci}; 155