127 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (C) 2022. Huawei Technologies Co., Ltd */3#define _GNU_SOURCE4#include <sched.h>5#include <stdbool.h>6#include <test_progs.h>7#include "htab_update.skel.h"8 9struct htab_update_ctx {10 int fd;11 int loop;12 bool stop;13};14 15static void test_reenter_update(void)16{17 struct htab_update *skel;18 unsigned int key, value;19 int err;20 21 skel = htab_update__open();22 if (!ASSERT_OK_PTR(skel, "htab_update__open"))23 return;24 25 /* lookup_elem_raw() may be inlined and find_kernel_btf_id() will return -ESRCH */26 bpf_program__set_autoload(skel->progs.lookup_elem_raw, true);27 err = htab_update__load(skel);28 if (!ASSERT_TRUE(!err || err == -ESRCH, "htab_update__load") || err)29 goto out;30 31 skel->bss->pid = getpid();32 err = htab_update__attach(skel);33 if (!ASSERT_OK(err, "htab_update__attach"))34 goto out;35 36 /* Will trigger the reentrancy of bpf_map_update_elem() */37 key = 0;38 value = 0;39 err = bpf_map_update_elem(bpf_map__fd(skel->maps.htab), &key, &value, 0);40 if (!ASSERT_OK(err, "add element"))41 goto out;42 43 ASSERT_EQ(skel->bss->update_err, -EBUSY, "no reentrancy");44out:45 htab_update__destroy(skel);46}47 48static void *htab_update_thread(void *arg)49{50 struct htab_update_ctx *ctx = arg;51 cpu_set_t cpus;52 int i;53 54 /* Pinned on CPU 0 */55 CPU_ZERO(&cpus);56 CPU_SET(0, &cpus);57 pthread_setaffinity_np(pthread_self(), sizeof(cpus), &cpus);58 59 i = 0;60 while (i++ < ctx->loop && !ctx->stop) {61 unsigned int key = 0, value = 0;62 int err;63 64 err = bpf_map_update_elem(ctx->fd, &key, &value, 0);65 if (err) {66 ctx->stop = true;67 return (void *)(long)err;68 }69 }70 71 return NULL;72}73 74static void test_concurrent_update(void)75{76 struct htab_update_ctx ctx;77 struct htab_update *skel;78 unsigned int i, nr;79 pthread_t *tids;80 int err;81 82 skel = htab_update__open_and_load();83 if (!ASSERT_OK_PTR(skel, "htab_update__open_and_load"))84 return;85 86 ctx.fd = bpf_map__fd(skel->maps.htab);87 ctx.loop = 1000;88 ctx.stop = false;89 90 nr = 4;91 tids = calloc(nr, sizeof(*tids));92 if (!ASSERT_NEQ(tids, NULL, "no mem"))93 goto out;94 95 for (i = 0; i < nr; i++) {96 err = pthread_create(&tids[i], NULL, htab_update_thread, &ctx);97 if (!ASSERT_OK(err, "pthread_create")) {98 unsigned int j;99 100 ctx.stop = true;101 for (j = 0; j < i; j++)102 pthread_join(tids[j], NULL);103 goto out;104 }105 }106 107 for (i = 0; i < nr; i++) {108 void *thread_err = NULL;109 110 pthread_join(tids[i], &thread_err);111 ASSERT_EQ(thread_err, NULL, "update error");112 }113 114out:115 if (tids)116 free(tids);117 htab_update__destroy(skel);118}119 120void test_htab_update(void)121{122 if (test__start_subtest("reenter_update"))123 test_reenter_update();124 if (test__start_subtest("concurrent_update"))125 test_concurrent_update();126}127