1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2021 Facebook */
3 #include <test_progs.h>
4 #include <network_helpers.h>
5 #include "for_each_hash_map_elem.skel.h"
6 #include "for_each_array_map_elem.skel.h"
7 
8 static unsigned int duration;
9 
10 static void test_hash_map(void)
11 {
12 	int i, err, hashmap_fd, max_entries, percpu_map_fd;
13 	struct for_each_hash_map_elem *skel;
14 	__u64 *percpu_valbuf = NULL;
15 	__u32 key, num_cpus, retval;
16 	__u64 val;
17 
18 	skel = for_each_hash_map_elem__open_and_load();
19 	if (!ASSERT_OK_PTR(skel, "for_each_hash_map_elem__open_and_load"))
20 		return;
21 
22 	hashmap_fd = bpf_map__fd(skel->maps.hashmap);
23 	max_entries = bpf_map__max_entries(skel->maps.hashmap);
24 	for (i = 0; i < max_entries; i++) {
25 		key = i;
26 		val = i + 1;
27 		err = bpf_map_update_elem(hashmap_fd, &key, &val, BPF_ANY);
28 		if (!ASSERT_OK(err, "map_update"))
29 			goto out;
30 	}
31 
32 	num_cpus = bpf_num_possible_cpus();
33 	percpu_map_fd = bpf_map__fd(skel->maps.percpu_map);
34 	percpu_valbuf = malloc(sizeof(__u64) * num_cpus);
35 	if (!ASSERT_OK_PTR(percpu_valbuf, "percpu_valbuf"))
36 		goto out;
37 
38 	key = 1;
39 	for (i = 0; i < num_cpus; i++)
40 		percpu_valbuf[i] = i + 1;
41 	err = bpf_map_update_elem(percpu_map_fd, &key, percpu_valbuf, BPF_ANY);
42 	if (!ASSERT_OK(err, "percpu_map_update"))
43 		goto out;
44 
45 	err = bpf_prog_test_run(bpf_program__fd(skel->progs.test_pkt_access),
46 				1, &pkt_v4, sizeof(pkt_v4), NULL, NULL,
47 				&retval, &duration);
48 	if (CHECK(err || retval, "ipv4", "err %d errno %d retval %d\n",
49 		  err, errno, retval))
50 		goto out;
51 
52 	ASSERT_EQ(skel->bss->hashmap_output, 4, "hashmap_output");
53 	ASSERT_EQ(skel->bss->hashmap_elems, max_entries, "hashmap_elems");
54 
55 	key = 1;
56 	err = bpf_map_lookup_elem(hashmap_fd, &key, &val);
57 	ASSERT_ERR(err, "hashmap_lookup");
58 
59 	ASSERT_EQ(skel->bss->percpu_called, 1, "percpu_called");
60 	ASSERT_LT(skel->bss->cpu, num_cpus, "num_cpus");
61 	ASSERT_EQ(skel->bss->percpu_map_elems, 1, "percpu_map_elems");
62 	ASSERT_EQ(skel->bss->percpu_key, 1, "percpu_key");
63 	ASSERT_EQ(skel->bss->percpu_val, skel->bss->cpu + 1, "percpu_val");
64 	ASSERT_EQ(skel->bss->percpu_output, 100, "percpu_output");
65 out:
66 	free(percpu_valbuf);
67 	for_each_hash_map_elem__destroy(skel);
68 }
69 
70 static void test_array_map(void)
71 {
72 	__u32 key, num_cpus, max_entries, retval;
73 	int i, arraymap_fd, percpu_map_fd, err;
74 	struct for_each_array_map_elem *skel;
75 	__u64 *percpu_valbuf = NULL;
76 	__u64 val, expected_total;
77 
78 	skel = for_each_array_map_elem__open_and_load();
79 	if (!ASSERT_OK_PTR(skel, "for_each_array_map_elem__open_and_load"))
80 		return;
81 
82 	arraymap_fd = bpf_map__fd(skel->maps.arraymap);
83 	expected_total = 0;
84 	max_entries = bpf_map__max_entries(skel->maps.arraymap);
85 	for (i = 0; i < max_entries; i++) {
86 		key = i;
87 		val = i + 1;
88 		/* skip the last iteration for expected total */
89 		if (i != max_entries - 1)
90 			expected_total += val;
91 		err = bpf_map_update_elem(arraymap_fd, &key, &val, BPF_ANY);
92 		if (!ASSERT_OK(err, "map_update"))
93 			goto out;
94 	}
95 
96 	num_cpus = bpf_num_possible_cpus();
97 	percpu_map_fd = bpf_map__fd(skel->maps.percpu_map);
98 	percpu_valbuf = malloc(sizeof(__u64) * num_cpus);
99 	if (!ASSERT_OK_PTR(percpu_valbuf, "percpu_valbuf"))
100 		goto out;
101 
102 	key = 0;
103 	for (i = 0; i < num_cpus; i++)
104 		percpu_valbuf[i] = i + 1;
105 	err = bpf_map_update_elem(percpu_map_fd, &key, percpu_valbuf, BPF_ANY);
106 	if (!ASSERT_OK(err, "percpu_map_update"))
107 		goto out;
108 
109 	err = bpf_prog_test_run(bpf_program__fd(skel->progs.test_pkt_access),
110 				1, &pkt_v4, sizeof(pkt_v4), NULL, NULL,
111 				&retval, &duration);
112 	if (CHECK(err || retval, "ipv4", "err %d errno %d retval %d\n",
113 		  err, errno, retval))
114 		goto out;
115 
116 	ASSERT_EQ(skel->bss->arraymap_output, expected_total, "array_output");
117 	ASSERT_EQ(skel->bss->cpu + 1, skel->bss->percpu_val, "percpu_val");
118 
119 out:
120 	free(percpu_valbuf);
121 	for_each_array_map_elem__destroy(skel);
122 }
123 
124 void test_for_each(void)
125 {
126 	if (test__start_subtest("hash_map"))
127 		test_hash_map();
128 	if (test__start_subtest("array_map"))
129 		test_array_map();
130 }
131