Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only
2 : /*
3 : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : */
5 :
6 : #include "core/set.h"
7 :
8 : #include <errno.h>
9 : #include <stdint.h>
10 : #include <stdlib.h>
11 : #include <string.h>
12 : #include <time.h>
13 :
14 : #include "bpfilter/cgen/prog/map.h"
15 : #include "bpfilter/cgen/runtime.h"
16 : #include "core/dump.h"
17 : #include "core/helper.h"
18 : #include "core/list.h"
19 : #include "core/logger.h"
20 : #include "core/marsh.h"
21 :
22 0 : size_t _bf_set_type_elem_size(enum bf_set_type type)
23 : {
24 : static const size_t sizes[_BF_SET_MAX] = {
25 : [BF_SET_IP4] = 4,
26 : [BF_SET_SRCIP6PORT] = 18,
27 : [BF_SET_SRCIP6] = 16,
28 : [BF_SET_IP4_SUBNET] = sizeof(struct bf_ip4_lpm_key),
29 : [BF_SET_IP6_SUBNET] = sizeof(struct bf_ip6_lpm_key),
30 : };
31 :
32 : static_assert(ARRAY_SIZE(sizes) == _BF_SET_MAX,
33 : "missing entries in set elems size array");
34 :
35 0 : return sizes[type];
36 : }
37 :
38 0 : int bf_set_new(struct bf_set **set, enum bf_set_type type)
39 : {
40 0 : bf_assert(set);
41 :
42 0 : *set = malloc(sizeof(**set));
43 0 : if (!*set)
44 : return -ENOMEM;
45 :
46 0 : (*set)->type = type;
47 0 : (*set)->elem_size = _bf_set_type_elem_size(type);
48 0 : bf_list_init(&(*set)->elems,
49 0 : (bf_list_ops[]) {{.free = (bf_list_ops_free)freep}});
50 :
51 0 : return 0;
52 : }
53 :
54 0 : int bf_set_new_from_marsh(struct bf_set **set, const struct bf_marsh *marsh)
55 : {
56 0 : _free_bf_set_ struct bf_set *_set = NULL;
57 : struct bf_marsh *child;
58 : enum bf_set_type type;
59 : int r;
60 :
61 0 : bf_assert(set);
62 0 : bf_assert(marsh);
63 :
64 0 : if (!(child = bf_marsh_next_child(marsh, NULL)))
65 : return -EINVAL;
66 0 : memcpy(&type, child->data, sizeof(type));
67 :
68 0 : r = bf_set_new(&_set, type);
69 0 : if (r < 0)
70 : return r;
71 :
72 0 : if (!(child = bf_marsh_next_child(marsh, child)))
73 : return -EINVAL;
74 :
75 0 : for (size_t i = 0; i < child->data_len / _set->elem_size; ++i) {
76 0 : _cleanup_free_ void *elem = malloc(_set->elem_size);
77 0 : if (!elem)
78 : return -ENOMEM;
79 :
80 0 : memcpy(elem, child->data + (i * _set->elem_size), _set->elem_size);
81 0 : r = bf_list_add_tail(&_set->elems, elem);
82 0 : if (r < 0)
83 : return r;
84 :
85 : TAKE_PTR(elem);
86 : }
87 :
88 0 : *set = TAKE_PTR(_set);
89 :
90 0 : return 0;
91 : }
92 :
93 0 : void bf_set_free(struct bf_set **set)
94 : {
95 0 : bf_assert(set);
96 :
97 0 : if (!*set)
98 : return;
99 :
100 0 : bf_list_clean(&(*set)->elems);
101 : freep((void *)set);
102 : }
103 :
104 0 : int bf_set_marsh(const struct bf_set *set, struct bf_marsh **marsh)
105 : {
106 0 : _free_bf_marsh_ struct bf_marsh *_marsh = NULL;
107 : _cleanup_free_ uint8_t *data = NULL;
108 : size_t elem_idx = 0;
109 : int r;
110 :
111 0 : bf_assert(set);
112 0 : bf_assert(marsh);
113 :
114 0 : r = bf_marsh_new(&_marsh, NULL, 0);
115 0 : if (r < 0)
116 : return r;
117 :
118 0 : r = bf_marsh_add_child_raw(&_marsh, &set->type, sizeof(set->type));
119 0 : if (r < 0)
120 : return r;
121 :
122 0 : data = malloc(set->elem_size * bf_list_size(&set->elems));
123 0 : if (!data)
124 0 : return bf_err_r(r, "failed to allocate memory for the set's content");
125 :
126 0 : bf_list_foreach (&set->elems, elem_node) {
127 0 : memcpy(data + (elem_idx * set->elem_size),
128 0 : bf_list_node_get_data(elem_node), set->elem_size);
129 0 : ++elem_idx;
130 : }
131 :
132 0 : r = bf_marsh_add_child_raw(&_marsh, data,
133 0 : set->elem_size * bf_list_size(&set->elems));
134 0 : if (r < 0)
135 : return r;
136 :
137 0 : *marsh = TAKE_PTR(_marsh);
138 :
139 0 : return 0;
140 : }
141 :
142 0 : void bf_set_dump(const struct bf_set *set, prefix_t *prefix)
143 : {
144 0 : bf_assert(set && prefix);
145 :
146 0 : DUMP(prefix, "struct bf_set at %p", set);
147 0 : bf_dump_prefix_push(prefix);
148 :
149 0 : DUMP(prefix, "type: %s", bf_set_type_to_str(set->type));
150 0 : DUMP(prefix, "elem_size: %lu", set->elem_size);
151 0 : DUMP(bf_dump_prefix_last(prefix), "elems: bf_list<bytes>[%lu]",
152 : bf_list_size(&set->elems));
153 :
154 0 : bf_dump_prefix_push(prefix);
155 0 : bf_list_foreach (&set->elems, elem_node) {
156 0 : if (bf_list_is_tail(&set->elems, elem_node))
157 0 : bf_dump_prefix_last(prefix);
158 :
159 0 : DUMP(prefix, "void * @ %p", bf_list_node_get_data(elem_node));
160 0 : bf_dump_prefix_push(prefix);
161 0 : bf_dump_hex(prefix, bf_list_node_get_data(elem_node), set->elem_size);
162 0 : bf_dump_prefix_pop(prefix);
163 : }
164 0 : bf_dump_prefix_pop(prefix);
165 :
166 0 : bf_dump_prefix_pop(prefix);
167 0 : }
168 :
169 0 : int bf_set_add_elem(struct bf_set *set, void *elem)
170 : {
171 : _cleanup_free_ void *_elem = NULL;
172 : int r;
173 :
174 0 : bf_assert(set);
175 0 : bf_assert(elem);
176 :
177 0 : _elem = malloc(set->elem_size);
178 0 : if (!_elem)
179 : return -ENOMEM;
180 :
181 0 : memcpy(_elem, elem, set->elem_size);
182 :
183 0 : r = bf_list_add_tail(&set->elems, _elem);
184 0 : if (r < 0)
185 0 : return r;
186 :
187 : TAKE_PTR(_elem);
188 :
189 : return 0;
190 : }
191 :
192 : static const char *_bf_set_type_strs[] = {
193 : [BF_SET_IP4] = "BF_SET_IP4",
194 : [BF_SET_SRCIP6PORT] = "BF_SET_SRCIP6PORT",
195 : [BF_SET_SRCIP6] = "BF_SET_SRCIP6",
196 : [BF_SET_IP4_SUBNET] = "BF_SET_IP4_SUBNET",
197 : [BF_SET_IP6_SUBNET] = "BF_SET_IP6_SUBNET",
198 : };
199 :
200 : static_assert(ARRAY_SIZE(_bf_set_type_strs) == _BF_SET_MAX, "");
201 :
202 0 : const char *bf_set_type_to_str(enum bf_set_type type)
203 : {
204 0 : bf_assert(0 <= type && type < _BF_SET_MAX);
205 :
206 0 : return _bf_set_type_strs[type];
207 : }
208 :
209 : static enum bf_map_bpf_type _bf_set_type_to_map_bpf_type[] = {
210 : [BF_SET_IP4] = BF_MAP_BPF_TYPE_HASH,
211 : [BF_SET_SRCIP6PORT] = BF_MAP_BPF_TYPE_HASH,
212 : [BF_SET_SRCIP6] = BF_MAP_BPF_TYPE_HASH,
213 : [BF_SET_IP4_SUBNET] = BF_MAP_BPF_TYPE_LPM_TRIE,
214 : [BF_SET_IP6_SUBNET] = BF_MAP_BPF_TYPE_LPM_TRIE,
215 : };
216 :
217 : static_assert(ARRAY_SIZE(_bf_set_type_to_map_bpf_type) == _BF_SET_MAX, "");
218 :
219 0 : enum bf_map_bpf_type bf_set_type_to_map_bpf_type(enum bf_set_type type)
220 : {
221 0 : return _bf_set_type_to_map_bpf_type[type];
222 : }
223 :
224 0 : int bf_set_type_from_str(const char *str, enum bf_set_type *type)
225 : {
226 0 : bf_assert(str);
227 0 : bf_assert(type);
228 :
229 0 : for (size_t i = 0; i < _BF_SET_MAX; ++i) {
230 0 : if (bf_streq(_bf_set_type_strs[i], str)) {
231 0 : *type = i;
232 0 : return 0;
233 : }
234 : }
235 :
236 : return -EINVAL;
237 : }
|