Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2021 Facebook */
0003 
0004 #include <test_progs.h>
0005 #include <network_helpers.h>
0006 #include "bpf_loop.skel.h"
0007 
0008 static void check_nr_loops(struct bpf_loop *skel)
0009 {
0010     struct bpf_link *link;
0011 
0012     link = bpf_program__attach(skel->progs.test_prog);
0013     if (!ASSERT_OK_PTR(link, "link"))
0014         return;
0015 
0016     /* test 0 loops */
0017     skel->bss->nr_loops = 0;
0018 
0019     usleep(1);
0020 
0021     ASSERT_EQ(skel->bss->nr_loops_returned, skel->bss->nr_loops,
0022           "0 loops");
0023 
0024     /* test 500 loops */
0025     skel->bss->nr_loops = 500;
0026 
0027     usleep(1);
0028 
0029     ASSERT_EQ(skel->bss->nr_loops_returned, skel->bss->nr_loops,
0030           "500 loops");
0031     ASSERT_EQ(skel->bss->g_output, (500 * 499) / 2, "g_output");
0032 
0033     /* test exceeding the max limit */
0034     skel->bss->nr_loops = -1;
0035 
0036     usleep(1);
0037 
0038     ASSERT_EQ(skel->bss->err, -E2BIG, "over max limit");
0039 
0040     bpf_link__destroy(link);
0041 }
0042 
0043 static void check_callback_fn_stop(struct bpf_loop *skel)
0044 {
0045     struct bpf_link *link;
0046 
0047     link = bpf_program__attach(skel->progs.test_prog);
0048     if (!ASSERT_OK_PTR(link, "link"))
0049         return;
0050 
0051     /* testing that loop is stopped when callback_fn returns 1 */
0052     skel->bss->nr_loops = 400;
0053     skel->data->stop_index = 50;
0054 
0055     usleep(1);
0056 
0057     ASSERT_EQ(skel->bss->nr_loops_returned, skel->data->stop_index + 1,
0058           "nr_loops_returned");
0059     ASSERT_EQ(skel->bss->g_output, (50 * 49) / 2,
0060           "g_output");
0061 
0062     bpf_link__destroy(link);
0063 }
0064 
0065 static void check_null_callback_ctx(struct bpf_loop *skel)
0066 {
0067     struct bpf_link *link;
0068 
0069     /* check that user is able to pass in a null callback_ctx */
0070     link = bpf_program__attach(skel->progs.prog_null_ctx);
0071     if (!ASSERT_OK_PTR(link, "link"))
0072         return;
0073 
0074     skel->bss->nr_loops = 10;
0075 
0076     usleep(1);
0077 
0078     ASSERT_EQ(skel->bss->nr_loops_returned, skel->bss->nr_loops,
0079           "nr_loops_returned");
0080 
0081     bpf_link__destroy(link);
0082 }
0083 
0084 static void check_invalid_flags(struct bpf_loop *skel)
0085 {
0086     struct bpf_link *link;
0087 
0088     /* check that passing in non-zero flags returns -EINVAL */
0089     link = bpf_program__attach(skel->progs.prog_invalid_flags);
0090     if (!ASSERT_OK_PTR(link, "link"))
0091         return;
0092 
0093     usleep(1);
0094 
0095     ASSERT_EQ(skel->bss->err, -EINVAL, "err");
0096 
0097     bpf_link__destroy(link);
0098 }
0099 
0100 static void check_nested_calls(struct bpf_loop *skel)
0101 {
0102     __u32 nr_loops = 100, nested_callback_nr_loops = 4;
0103     struct bpf_link *link;
0104 
0105     /* check that nested calls are supported */
0106     link = bpf_program__attach(skel->progs.prog_nested_calls);
0107     if (!ASSERT_OK_PTR(link, "link"))
0108         return;
0109 
0110     skel->bss->nr_loops = nr_loops;
0111     skel->bss->nested_callback_nr_loops = nested_callback_nr_loops;
0112 
0113     usleep(1);
0114 
0115     ASSERT_EQ(skel->bss->nr_loops_returned, nr_loops * nested_callback_nr_loops
0116           * nested_callback_nr_loops, "nr_loops_returned");
0117     ASSERT_EQ(skel->bss->g_output, (4 * 3) / 2 * nested_callback_nr_loops
0118         * nr_loops, "g_output");
0119 
0120     bpf_link__destroy(link);
0121 }
0122 
0123 static void check_non_constant_callback(struct bpf_loop *skel)
0124 {
0125     struct bpf_link *link =
0126         bpf_program__attach(skel->progs.prog_non_constant_callback);
0127 
0128     if (!ASSERT_OK_PTR(link, "link"))
0129         return;
0130 
0131     skel->bss->callback_selector = 0x0F;
0132     usleep(1);
0133     ASSERT_EQ(skel->bss->g_output, 0x0F, "g_output #1");
0134 
0135     skel->bss->callback_selector = 0xF0;
0136     usleep(1);
0137     ASSERT_EQ(skel->bss->g_output, 0xF0, "g_output #2");
0138 
0139     bpf_link__destroy(link);
0140 }
0141 
0142 static void check_stack(struct bpf_loop *skel)
0143 {
0144     struct bpf_link *link = bpf_program__attach(skel->progs.stack_check);
0145     const int max_key = 12;
0146     int key;
0147     int map_fd;
0148 
0149     if (!ASSERT_OK_PTR(link, "link"))
0150         return;
0151 
0152     map_fd = bpf_map__fd(skel->maps.map1);
0153 
0154     if (!ASSERT_GE(map_fd, 0, "bpf_map__fd"))
0155         goto out;
0156 
0157     for (key = 1; key <= max_key; ++key) {
0158         int val = key;
0159         int err = bpf_map_update_elem(map_fd, &key, &val, BPF_NOEXIST);
0160 
0161         if (!ASSERT_OK(err, "bpf_map_update_elem"))
0162             goto out;
0163     }
0164 
0165     usleep(1);
0166 
0167     for (key = 1; key <= max_key; ++key) {
0168         int val;
0169         int err = bpf_map_lookup_elem(map_fd, &key, &val);
0170 
0171         if (!ASSERT_OK(err, "bpf_map_lookup_elem"))
0172             goto out;
0173         if (!ASSERT_EQ(val, key + 1, "bad value in the map"))
0174             goto out;
0175     }
0176 
0177 out:
0178     bpf_link__destroy(link);
0179 }
0180 
0181 void test_bpf_loop(void)
0182 {
0183     struct bpf_loop *skel;
0184 
0185     skel = bpf_loop__open_and_load();
0186     if (!ASSERT_OK_PTR(skel, "bpf_loop__open_and_load"))
0187         return;
0188 
0189     skel->bss->pid = getpid();
0190 
0191     if (test__start_subtest("check_nr_loops"))
0192         check_nr_loops(skel);
0193     if (test__start_subtest("check_callback_fn_stop"))
0194         check_callback_fn_stop(skel);
0195     if (test__start_subtest("check_null_callback_ctx"))
0196         check_null_callback_ctx(skel);
0197     if (test__start_subtest("check_invalid_flags"))
0198         check_invalid_flags(skel);
0199     if (test__start_subtest("check_nested_calls"))
0200         check_nested_calls(skel);
0201     if (test__start_subtest("check_non_constant_callback"))
0202         check_non_constant_callback(skel);
0203     if (test__start_subtest("check_stack"))
0204         check_stack(skel);
0205 
0206     bpf_loop__destroy(skel);
0207 }